commit 470e122388e219af51de3a27050f8658efa7a339 Author: hoshuchiu Date: Tue Jun 9 00:41:55 2026 +0800 docs diff --git a/ARCHITECTURE.md b/ARCHITECTURE.md new file mode 100644 index 0000000..82a3bc2 --- /dev/null +++ b/ARCHITECTURE.md @@ -0,0 +1,737 @@ +# 人机协作 Agent 原型 —— 系统架构总览 + +> 本文档提供系统级的全景视图,描述各子系统的职责、边界、交互方式以及数据流动路径。阅读前建议先浏览 `DESIGN_DECISIONS.md` 了解设计动机。 + +--- + +## 1. 系统总体架构 + +系统由五个核心子系统构成,围绕"中央路由"呈星型拓扑: + +``` +┌─────────────────────────────────────────────────────────────┐ +│ 可视化与交互层 │ +│ (树状图 · 模块关系图 · 评审会界面 · 配置面板) │ +└─────────────────────────────────────────────────────────────┘ + ↑↓ +┌─────────────────────────────────────────────────────────────┐ +│ 中央路由 (Central Router) │ +│ (消息转发 · 权限过滤 · 日志审计 · 路由策略) │ +└─────────────────────────────────────────────────────────────┘ + ↑↓ + ┌──────────┬──────────┼──────────┬──────────┐ + ↑↓ ↑↓ ↑↓ ↑↓ ↑↓ + ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ + │ 产品 │ │ 测试 │ │Supervisor│ │ 人类 │ │ 其他 │ + │ Agent │ │ Agent │ │/知识库 │ │(Supervi-│ │ 工具 │ + │ │ │ │ │ Agent │ │sory) │ │ 服务 │ + └────┬────┘ └────┬────┘ └────┬────┘ └────┬────┘ └────┬────┘ + └───────────┴───────────┴───────────┴───────────┘ + ↑↓ +┌─────────────────────────────────────────────────────────────┐ +│ 工作台与快照系统 │ +│ (工作区隔离 · 快照管理 · 分支Fork · 树状存储 · 存档检索) │ +└─────────────────────────────────────────────────────────────┘ +``` + +**设计原则**:任何两个 Agent(含人类)不直接通信,所有交互必须经过中央路由。任何 Agent 不直接操作文件系统,所有持久化必须经过工作台快照系统。 + +--- + +## 2. 核心子系统详解 + +### 2.1 中央路由 (Central Router) + +#### 职责 +- **消息转发**:根据路由规则将消息从发送方递送到接收方/组。 +- **权限过滤**:在转发前检查"发送方是否有权向接收方发送此类消息"。 +- **日志审计**:记录所有经过的消息元数据(不含 payload 内容,只记录谁发给谁、消息类型、时间戳、引用 ID)。 +- **路由策略执行**:当前为硬编码规则,未来可替换为 LLM 动态决策。 + +#### 内部结构 +``` +Central Router +├── Inbound Queue(入站队列,所有 Agent 提交消息至此) +├── Routing Engine(路由引擎,决定消息去向) +│ └── 当前:代码规则表 +│ └── 未来:LLM 策略模型 +├── Permission Gate(权限门,拦截越权消息) +├── Outbound Dispatcher(出站分发器) +└── Audit Log(审计日志,只存元数据) +``` + +#### 消息格式(标准信封) +所有经过中央路由的消息必须遵守统一格式: + +``` +{ + "msg_id": "uuid", + "timestamp": "ISO8601", + "from": "agent_id", + "to": "agent_id | group_id | broadcast", + "msg_type": "QUERY | RESPONSE | NOTIFY | DECISION | MEETING_CALL", + "payload_ref": "snapshot_id#object_path", + "payload_summary": "人类可读摘要(用于日志和通知)", + "session_id": "当前任务会话 ID", + "branch_id": "所属分支 ID(主干为 main)", + "priority": "LOW | NORMAL | HIGH | CRITICAL" +} +``` + +**注意**:`payload_ref` 指向工作台快照系统中的对象,消息本身不携带内容。接收方凭引用 ID 和自身权限向工作台申请拉取。 + +#### 通信模式实现 + +| 模式 | 路由行为 | +|------|----------| +| 点对点 | `to` 填目标 Agent ID,直接投递 | +| 点对组 | `to` 填 group_id,Router 查询组成员列表后分别投递 | +| 组内广播 | 特殊消息类型 `BROADCAST`,Router 向组内所有成员投递,并标记"同一条消息的副本"便于关联 | + +--- + +### 2.2 工作台与快照系统 (Workbench & Snapshot System) + +#### 职责 +- 为每个 Agent 提供**隔离的工作区**(独立的文件系统视图)。 +- 提供**快照(Snapshot)**的创建、读取、对比、回溯能力。 +- 维护**树状的快照历史**(支持分支、合并、差异对比)。 +- 提供**存档(Archive)**的写入和检索(工作过程存档 + 评审会存档)。 +- 作为中央路由的**内容存储后端**:Agent 通过引用 ID 向工作台申请拉取内容。 + +#### 核心概念 + +**工作区(Workspace)** +- 每个 Agent 拥有一个独立工作区目录。 +- 工作区之间默认不可见(文件系统级别隔离)。 +- 人类(Supervisory Agent)拥有跨工作区读取权限(但写入需显式授权)。 +- 工作区的"当前状态"随时可以被快照捕获。 + +**快照(Snapshot)** +- 快照是工作区某一时刻的只读副本。 +- 快照**只在决策节点创建**:分叉点(Fork)和挂起点(Suspend)。中间运行过程不创建快照。 +- 快照不可修改,只能通过"基于快照创建新工作区"来延续。 +- 每个快照包含: + - 文件系统哈希树(保证完整性) + - Agent 上下文引用(推理历史 ID) + - 父快照 ID(支持回溯) + - 分支 ID(支持多线历史) + - 节点类型(`FORK` 或 `SUSPEND`) + - 创建原因(详细枚举见数据模型) + +**快照树(Snapshot Tree)** +- 快照之间通过 `parent_id` 形成树结构。 +- `main` 分支是主时间线。 +- 树节点按语义分为两类: + - **分叉节点(Fork Node)**:新分支的起点,表示"AI 在这里做了一个选择"。 + - **挂起节点(Suspend Node)**:分支暂停的断点,表示"AI 在这里停下来了"。 +- **Fork 操作强制要求原因**:Agent 调用 `fork()` 时必须提供结构化原因说明(观察到的现象、假设的根因、尝试的方向),否则工作台拒绝执行。 +- Fork 操作创建新分支:基于某快照创建新工作区,新工作区的首次快照是**分叉节点**,指向父快照,但携带新的 `branch_id`。 +- 挂起操作在当前分支末端创建一个**挂起节点**,标记该分支进入暂停状态。 +- 树节点支持以下查询: + - `trace(node_id)`:返回从根到该节点的快照链(即 AI 的完整思考链)。 + - `diff(node_a, node_b)`:返回两个节点从最近公共祖先开始的差异(即分叉后的不同路径)。 + - `checkout(node_id)`:基于该快照创建新工作区,供人类或 Agent 继续工作。 + +**平级链(Side Chain)** +- 每个主树节点可以挂载一条平级链,记录到达该节点之前的中间操作快照。 +- 平级链上的快照**不参与树的拓扑结构**,只是该节点的历史附件。 +- 典型内容:危险操作前备份、开发阶段中间状态、挂起被打回后的重试记录。 +- 挂起被打回时:原挂起节点的快照被挂载到"下一个推演起点"的平级链头部。 +- 查询:`side_chain(node_id)` 返回该节点的平级链快照列表(按时间倒序)。 + +**存档(Archive)** +- 存档是"业务事件"的持久化记录,与快照(技术状态)分离存储。 +- 两类存档: + 1. **工作存档**:每次快照创建时的原因、触发者、关联的消息 ID 列表。 + 2. **评审会存档**:评审会的完整记录(见 2.5 节)。 +- 存档支持按 `session_id`、`branch_id`、`timestamp`、`event_type` 检索。 + +#### 数据模型 + +``` +Session(任务会话) +├── session_id: UUID +├── requirement: 原始需求文本(人类输入) +├── current_req_version_id: 当前有效需求版本 ID +├── strategy_config: 挂起策略配置(允许哪些挂起类型) +├── supervisor_permissions: Supervisor 当前解锁的权限列表 +├── status: ACTIVE | SUSPENDED | ABORTED +├── root_snapshot_id: 初始快照 +├── current_main_snapshot_id: main 分支最新快照 +├── branch_registry: { branch_id → { parent_snapshot_id, status, owner_agent_id } } +└── meeting_history: [meeting_id, ...] + +RequirementSnapshot(需求版本) +├── req_version_id: UUID +├── session_id: 所属会话 +├── version_number: 整数版本号(v1, v2, v3...) +├── parent_version_id: 父版本(v1 为 null) +├── content: 结构化需求规格 +│ ├── 功能描述 +│ ├── 验收标准 +│ ├── 边界条件 +│ └── 已知歧义点 +├── status: DRAFT | ACTIVE | SUPERSEDED | SUSPENDED +├── created_by: 创建者 Agent ID(产品经理或人类) +├── created_at: 时间戳 +└── code_snapshots_based_on: [snapshot_id, ...] // 基于该需求的代码快照列表 + +Snapshot +├── snapshot_id: UUID +├── session_id: 所属会话 +├── branch_id: 所属分支 +├── parent_snapshot_id: 父快照(根节点为 null,平级链快照为 null) +├── node_type: 节点类型枚举 +│ └── FORK(分叉节点)| SUSPEND(挂起节点)| SIDECHAIN(平级链节点) +├── is_sidechain: bool // 是否为平级链快照(不参与主树拓扑) +├── attached_to: Option // 平级链快照挂载在哪个主树节点上 +├── created_by: 创建者 Agent ID +├── created_at: 时间戳 +├── reason: 创建原因枚举 +│ └── FORK_BRANCH(开新分支)| SUSPEND_TECHNICAL(技术性挂起) +│ SUSPEND_COGNITIVE(认知性挂起)| SUSPEND_RISK(风险性挂起) +│ SUSPEND_ALL_BRANCHES(所有分支挂起触发评审会) +│ PRE_DANGER(危险操作前备份)| ATTEMPT_RETRY(挂起被打回后的重试) +├── filesystem_hash: 文件系统 Merkle Tree 根哈希 +├── context_ref: Agent 上下文存储位置 +└── tags: [废弃标记等] + +ArchiveEntry +├── archive_id: UUID +├── session_id: 所属会话 +├── snapshot_id: 关联快照(可选) +├── event_type: WORK | MEETING | DECISION +├── content: 事件详情(JSON) +└── searchable_text: 用于全文检索的文本摘要 +``` + +--- + +### 2.3 Agent 运行时 + +#### 产品 Agent (Product Agent) + +**生命周期状态**: +``` +IDLE → PLANNING → CODING → TESTING → REVIEWING → SUSPENDED +``` + +- **PLANNING**:基于需求生成实现方案(不允许分支,单线程)。生成**Todo List**作为开发路线图。 +- **CODING**:按 Todo List 线性推进,逐项完成。Todo 项状态流转:`TODO → DOING → DONE`。遇到阻碍时可标记为 `BLOCKED`。 + - 此阶段**禁止分叉**:即使遇到多种实现思路,也必须先选一条路走到底。 + - 遇到危险操作前通知工作台创建快照(但开发阶段的快照**不进入**快照树,只作为工作区备份)。 +- **TESTING**:将代码提交给测试 Agent(通过中央路由发送测试请求,附带代码快照引用)。等待测试结果。 +- **REVIEWING**:测试返回结果后,分析是否通过。 + - 通过:请求进入评审会(挂起)。 + - 未通过:**进入修复阶段**,此时允许开分支探索多种修复方案(必须提供分叉原因)。 +- **SUSPENDED**:任务挂起,等待外部事件。 + +**输出物**: +- 代码文件(在工作区中)。 +- Todo List(开发路线图,供人类查看进度)。 +- 模块关系图描述(用于可视化)。 +- 逐模块阐释文本(用于评审会)。 + +#### 测试 Agent (Test Agent) + +**生命周期状态**: +``` +IDLE → RECEIVING_REQ → ANALYZING → GENERATING_TESTS → EXECUTING → REPORTING → SUSPENDED +``` + +- **RECEIVING_REQ**:通过中央路由接收测试请求。 +- **ANALYZING**:只读取需求规格(不读产品代码),分析测试点。 +- **GENERATING_TESTS**:基于需求写测试用例和测试代码。 +- **EXECUTING**:运行测试(在自己的工作区中,可能需要向工作台申请"基于产品快照创建只读副本"来运行,但不读取内容只执行)。 +- **REPORTING**:生成测试报告,通过中央路由发送给产品 Agent 和人类。 +- **SUSPENDED**:等待下一个测试请求。 + +**关键约束**: +- 测试 Agent 的工作区对代码内容的访问是"盲执行":它可以运行编译和测试命令,但设计上不能"阅读"源代码的逻辑(通过工具链限制实现,如只提供编译后的二进制或接口定义)。 +- 如果测试需要接口定义,由产品 Agent 在提交测试请求时单独提供接口契约文件(`interface.json` 等),不包含实现细节。 + +#### Supervisor / 知识库 Agent + +**生命周期状态**: +``` +IDLE → RECEIVING_QUERY → ANALYZING → RETRIEVING → INJECTING → FOLLOWUP → SUSPENDED +``` + +- **RECEIVING_QUERY**:通过中央路由接收认知型支援请求。 +- **ANALYZING**:分析问题类型(缺文档?缺上下文?缺业务规则?)。 +- **RETRIEVING**:查询知识库(本地文档、历史存档、外部资源等)。 +- **INJECTING**:将检索到的信息通过消息发送回请求方。 +- **FOLLOWUP**:记录本次支援的尝试次数。如果同一问题被多次查询且超上限,升级通知。 +- **SUSPENDED**:等待下一个查询。 + +**权限边界**: +- 当前:只能响应 `COGNITIVE_SUPPORT` 类型的请求。 +- 未来可解锁:`TECHNICAL_APPROVAL`、`RISK_APPROVAL`、`BRANCH_LIFE_DECISION` 等。 + +#### 产品经理 Agent (PM Agent) + +**生命周期状态**: +``` +IDLE → RECEIVING_REQ → STRUCTURING → REVIEWING → SUSPENDED +``` + +- **RECEIVING_REQ**:接收人类的原始需求(可能是一句模糊的话)。 +- **STRUCTURING**:将原始需求转化为结构化需求规格(功能描述、验收标准、边界条件、已知歧义点)。 +- **REVIEWING**:组织需求对齐评审会,确认产品 Agent 和测试 Agent 对需求的理解一致。 + - 对齐通过:需求规格标记为 `ACTIVE`,进入编码阶段。 + - 对齐不通过:需求规格**挂起**(走统一评审会流程)。 +- **SUSPENDED**:等待人类反馈或新需求输入。 + +**工作空间**: +- 与产品/测试 Agent 使用同一套快照系统,但**没有分叉权**。 +- 维护内容:原始需求、需求规格 v1/v2/v3...、概要设计、详细设计、接口契约定义。 + +#### 人类 (Supervisory Agent) + +**特殊之处**: +- 在系统中以特殊 Agent ID(如 `human://user_id`)注册。 +- 权限列表为 `ALL`,但实际操作受前端 UI 的显式确认保护(防止误触)。 +- 可以加入任意组,可以接收所有类型的通知。 +- 可以通过可视化界面直接操作工具(如打开编辑器修改代码、运行测试、创建快照)。 +- 操作同样经过中央路由(人类的前端视为一个 Agent 客户端),确保所有操作可追溯。 +- **小挂起响应**:当工具层发送 `PERMISSION_REQUEST` 时,人类可以直接在通知栏输入密码或点击授权,不需要进入评审会。 + +--- + +### 2.4 分支管理引擎 + +#### 职责 +- 管理分支的生命周期:创建、运行、监控、挂起、废弃。 +- 执行 BFS 调度:并行推进多条活跃分支,收集各分支状态。 +- 触发全局事件:当所有活跃分支都挂起时,向中央路由发送 `ALL_BRANCHES_SUSPENDED` 事件。 + +#### 分支状态机 +``` +CREATED → RUNNING → SUSPENDED ──→ ABANDONED(由人类在评审会上标记) + ↑ │ │ + └─────────┴─────────┘(人类或 Supervisor 决策后可恢复为 RUNNING) +``` + +#### BFS 调度逻辑 +``` +while 存在 RUNNING 分支: + for 每个 RUNNING 分支: + 推进一步(执行一个 Agent 动作或等待外部响应) + if 分支挂起: + 发送分支挂起通知 + if 所有分支都 SUSPENDED: + 发送 ALL_BRANCHES_SUSPENDED 事件 + 触发评审会 + break +``` + +**注意**:"推进一步"的粒度是可配置的。可以是"一个 LLM 调用",也可以是"一个完整的测试周期"。MVP 阶段建议以"一个完整的修复-测试循环"为一步。 + +--- + +### 2.5 评审会系统 (Meeting System) + +#### 职责 +- 组织评审会议程。 +- 收集并展示评审材料(模块关系图、接口定义、测试报告、逐模块阐释)。 +- 记录完整会议过程。 +- 将会议结论转化为系统动作(恢复分支、废弃分支、调整策略、修改需求等)。 + +#### 评审会触发条件 +1. **强制触发(代码穷尽)**:所有代码分支都挂起时,系统自动创建评审会。 +2. **强制触发(需求挂起)**:需求规格被标记为挂起(需求对齐不通过)时,系统自动创建评审会。 +3. **手动触发**:人类在任意时刻通过 UI 发起。 +4. **定时触发**:某条分支挂起超过设定时间未处理,系统提醒人类"是否开会"。 + +#### 评审会流程 +``` +1. 创建会议(生成 meeting_id,创建会议组,邀请相关 Agent 和人类) +2. 分配临时工作区(工作台为评审会创建独立的临时工作区,所有会议期间的代码修改仅限于此) +3. 冻结材料(基于当前各分支快照锁定评审材料,防止会议期间正式工作区代码变动) +4. 材料展示(通过可视化层展示模块关系图、接口、测试报告) +5. 逐模块阐释(产品 Agent 依次阐释每个模块,提供证据) +6. 质询环节(测试 Agent、人类、Supervisor 提出问题) +7. 临时修改(如人类想在会议中试改代码,只能在临时工作区进行,不影响正式分支) +8. 决策(人类做出最终决策:操作哪些分支、注入什么新提示词、是否调整需求等) +9. 执行决策(工作台根据结论向分支管理引擎下发指令,不直接修改代码) +10. 存档(完整会议记录作为独立存档写入 Archive,通过 trigger_snapshot_id 关联到触发节点) +``` + +#### 会议结论类型(通用,适用于代码分支和需求规格) +- `RESUME_WITH_PROMPT(target_id, prompt)`:给挂起对象注入新提示词后恢复。 + - 对代码分支:给分支新的修复思路,继续运行。 + - 对需求规格:澄清歧义后,重新组织需求对齐评审。 +- `ABANDON(target_id)`:废弃挂起对象。 + - 对代码分支:废弃该修复路线。 + - 对需求规格:废弃当前版本,由产品经理重新撰写。 +- `FORK_NEW_BRANCH(parent_snapshot_id, strategy)`:基于某代码快照开新分支尝试新方案。(仅适用于代码) +- `ADJUST_REQUIREMENT(new_requirement_spec)`:发布新需求版本。 + - 旧版本标记为 `SUPERSEDED`。 + - 所有基于旧版本的活跃代码分支标记为 `STALE_REQUIREMENT`。 +- `ADJUST_STRATEGY(new_strategy_config)`:调整挂起策略(如临时开放认知型挂起)。 +- `ESCALATE`:升级给更高权限的人类(如当前审阅者权限不足)。 +- `TERMINATE`:终止整个任务(保留存档,但不再运行)。 + +--- + +### 2.5.1 小挂起处理机制(执行时阻塞) + +#### 职责 +- 在工具层拦截操作系统级别的权限/环境阻塞。 +- 向人类发送轻量级权限请求,不需要进入评审会。 +- 记录授权历史,支持"记住本次选择"。 + +#### 处理流程 +``` +Agent 调用工具(如 run_command("sudo apt install ...")) + │ + ▼ +工具层执行命令 + │ + ▼ +操作系统返回 Permission denied / 需要密码 + │ + ▼ +工具层发送 PERMISSION_REQUEST 给中央路由 + │ + ▼ +人类收到通知(弹窗/消息栏) + │ + ├────→ 输入密码 / 点击"允许一次" + │ │ + │ ▼ + │ 工具层重新执行命令(带上授权) + │ │ + │ ▼ + │ Agent 继续运行,状态不变 + │ + └────→ 点击"拒绝" + │ + ▼ + 工具层返回错误给 Agent + Agent 自行决定下一步(可能进入大挂起) +``` + +#### 授权缓存 +``` +AuthorizationCache +├── tool_name: "run_command" +├── pattern: "sudo *" +├── granted_by: "human://user_id" +├── grant_type: ONCE | SESSION | PERMANENT +└── expires_at: 时间戳(可选) +``` + +--- + +### 2.6 可视化与交互层 + +#### 职责 +- 渲染快照树(树状图)。 +- 渲染模块关系图(方框+连线,点击穿透接口详情)。 +- 提供评审会的交互界面。 +- 提供配置面板(挂起策略、Supervisor 权限、通知偏好等)。 +- 提供工具的统一操作入口(代码编辑、测试运行、快照操作)。 + +#### 核心视图 + +**视图 A:需求时间线(Requirement Timeline View)** +- 垂直时间轴布局,需求版本按时间顺序从上到下排列:v1 → v2 → v3 → ... +- 当前有效版本高亮显示,已替代版本灰显但可点击查看历史。 +- 每个版本节点显示:版本号、创建者、状态(ACTIVE / SUPERSEDED / SUSPENDED)。 +- 点击版本节点:右侧面板显示该版本的完整需求规格内容。 +- 点击版本节点:代码树中高亮所有基于该版本的代码节点,其他节点变灰。 +- 需求规格挂起时,对应版本节点闪烁红色,并显示"等待评审会"标记。 + +**视图 B:快照树(Snapshot Tree View)** +- 垂直时间轴布局,根在上,叶子在下。 +- 主干(main)居中高亮,分支向两侧展开。 +- 节点颜色编码:绿色(运行中)、黄色(挂起-认知)、橙色(挂起-风险)、红色(挂起-技术)、灰色(废弃)。 +- 点击节点:右侧面板显示从根到该节点的思考链(时间线形式)。 +- 点击节点旁的"历史"图标:展开该节点的**平级链**,显示到达此节点之前的所有中间操作(危险操作、重试记录等)。 +- Ctrl+点击两个节点:显示差异对比视图(公共祖先 + 分叉后的不同路径)。 +- 双击节点:`checkout` 该快照,打开对应工作区内容。 + +**视图 C:模块关系图(Module Graph View)** +- 力导向图或层次布局:方框 = 模块,连线 = 接口依赖。 +- 点击方框:展开模块详情(职责描述、代码位置、所属分支)。 +- 点击连线:弹出接口定义面板(输入/输出类型、契约、变更历史)。 +- 红色虚线 = 未通过测试的接口。 +- 黄色闪烁 = 当前评审会正在讨论的模块。 + +**视图 D:评审会界面(Meeting Room View)** +- 左侧:参会成员列表(在线状态)。 +- 中间:当前展示的材料(模块图 / 代码 diff / 测试报告)。 +- 右侧:批注面板(人类的实时批注、历史批注)。 +- 底部:决策操作栏(恢复/废弃/开分支/调整策略等按钮)。 + +--- + +## 3. 数据流全景 + +### 3.1 正常任务执行流(无分支) + +``` +人类提交需求 ──→ 中央路由 ──→ 产品 Agent + │ + ▼ + [PLANNING 阶段] + │ + ▼ + [CODING 阶段] + (危险操作前:工作台自动快照) + │ + ▼ + 提交测试请求(元数据消息) + │ + ▼ + 中央路由 ──→ 测试 Agent + │ + ▼ + [GENERATING_TESTS] + │ + ▼ + [EXECUTING] + │ + ▼ + 测试报告 ──→ 中央路由 + │ + ▼ + 产品 Agent + 人类 + │ + ▼ + 请求进入评审会 + │ + ▼ + 评审会系统 + (会议前:工作台快照) + │ + ▼ + 人类决策:挂起 / 继续 + │ + ▼ + 存档 + 任务挂起 +``` + +### 3.2 分支探索流(测试发现问题后) + +``` +测试报告:失败 ──→ 产品 Agent 分析 + │ + ▼ + 决定开 3 条修复分支 + │ + ▼ + 分支管理引擎创建 3 个 Fork + (基于当前快照,各新建工作区) + │ + ┌───────────────┼───────────────┐ + ▼ ▼ ▼ + 分支 A 分支 B 分支 C + 方案:重构 方案:补丁 方案:绕开 + │ │ │ + ▼ ▼ ▼ + 运行测试 运行测试 运行测试 + │ │ │ + ┌────┴────┐ ┌────┴────┐ ┌────┴────┐ + ▼ ▼ ▼ ▼ ▼ ▼ + 通过 挂起 挂起 挂起 通过 挂起 + (技术) (风险) (认知) (技术) (技术) (风险) + │ │ │ │ │ │ + ▼ ▼ ▼ ▼ ▼ ▼ + 继续 通知 通知 通知 继续 通知 + 运行 人类 Supervisor 人类 运行 人类 + + │ + ▼ + 分支 A 和 C 还在运行,B 已挂起 + │ + ▼ + (假设 A 和 C 后续也挂了) + │ + ▼ + ALL_BRANCHES_SUSPENDED 事件 + │ + ▼ + 强制触发评审会 +``` + +### 3.3 认知型挂起处理流(Supervisor 介入) + +``` +产品 Agent 遇到认知盲区 + │ + ▼ +策略检查:认知型挂起是否被允许? + │ + ┌────┴────┐ + ▼ ▼ + 否 是 + │ │ + ▼ ▼ +硬撑继续 发送 COGNITIVE_SUPPORT 请求 +(到测试阶段 │ + 再暴露) ▼ + 中央路由 + │ + ▼ + Supervisor Agent + │ + ┌────┴────┐ + ▼ ▼ + 查知识库 找不到 + │ │ + ▼ ▼ + 返回信息 尝试次数 +1 + │ 超上限? + │ ┌────┴────┐ + │ ▼ ▼ + │ 否 是 + │ │ │ + │ ▼ ▼ + │ 继续等待 升级为真正挂起 + │ (通知人类) + ▼ + 产品 Agent 基于新信息继续 +``` + +--- + +## 4. 状态机总览 + +### 4.1 任务级状态机(Session) + +``` + ┌─────────────────────────────────────┐ + │ │ + ▼ │ +CREATED ──→ PLANNING ──→ EXECUTING ──→ MEETING ──→ SUSPENDED + │ │ ↑ │ │ + │ │ │ │ │ + │ ▼ │ ▼ │ + │ CHECKPOINT ABORTED │ + │ │ │ │ │ + │ └───┘ └──────────────┘ + │ │ + └────────────────────────────────────────────┘ + (人类或 Supervisor 决策后恢复) +``` + +- `CREATED`:需求已接收,尚未开始。 +- `PLANNING`:产品 Agent 生成方案阶段(线性,无分支)。 +- `EXECUTING`:编码 + 测试 + 分支探索阶段。 +- `CHECKPOINT`:执行过程中的暂停点(检查点),可能由挂起触发。 +- `MEETING`:评审会进行中,材料冻结,等待人类决策。 +- `SUSPENDED`:任务挂起,保留完整上下文,可随时恢复或终止。 +- `ABORTED`:任务被终止(仍保留存档,只是不再运行)。 + +### 4.2 分支级状态机(Branch) + +``` +FORKED ──→ ACTIVE ──→ SUSPENDED ──→ [评审会决策] + │ + ┌─────────┼─────────┐ + ▼ ▼ ▼ + RESUMED ABANDONED MERGED + │ │ + └───────────────────┘ + │ + ▼ + (回到 ACTIVE 或结束) +``` + +- `FORKED`:刚创建,尚未开始运行。 +- `ACTIVE`:正在运行中(BFS 调度的一环)。 +- `SUSPENDED`:挂起,等待外部决策。 +- `RESUMED`:决策后恢复运行。 +- `ABANDONED`:被废弃(在快照树上标记为灰色,但记录保留)。 +- `MERGED`:被合并到另一分支或主干(记录合并关系)。 + +--- + +## 5. 接口契约(子系统间) + +### 5.1 中央路由 ↔ Agent + +``` +Agent.register(agent_id, role_card_id, capabilities, permission_list) +Agent.send(message_envelope) +Agent.receive() → message_envelope +Agent.join_group(group_id) +Agent.leave_group(group_id) +``` + +**身份牌(Role Card)**: +Agent 注册时必须绑定一个身份牌,身份牌定义了该 Agent 的决策模型、可用工具集和工作区权限。身份牌本身由工作台系统统一管理,支持动态切换(如人类可以临时给某个 Agent 换一张更保守/更激进的身份牌)。 + +### 5.2 中央路由 ↔ 工作台 + +``` +Router.request_content(snapshot_id, object_path, requester_id) + → { allowed: bool, content_ref: string } + +Router.log_audit(event_metadata) +``` + +### 5.3 Agent ↔ 工作台 + +``` +Workspace.create(agent_id) → workspace_id +Workspace.snapshot(workspace_id, reason) → snapshot_id +Workspace.fork(snapshot_id, new_agent_id) → new_workspace_id +Workspace.checkout(snapshot_id) → workspace_id +Workspace.read(workspace_id, path) → content +Workspace.write(workspace_id, path, content) → { success, new_snapshot_id } +Workspace.diff(snapshot_a, snapshot_b) → diff_object +Workspace.trace(snapshot_id) → [snapshot_id, ...] // 从根到该节点 +``` + +### 5.4 评审会系统 ↔ 其他子系统 + +``` +Meeting.create(session_id, trigger_reason, branch_ids) → meeting_id +Meeting.freeze_materials(meeting_id) → { snapshot_refs } +Meeting.add_annotation(meeting_id, agent_id, target_module, text) +Meeting.make_decision(meeting_id, agent_id, decision_type, params) +Meeting.archive(meeting_id) → archive_id +Meeting.get_transcript(meeting_id) → full_record +``` + +### 5.5 可视化层 ↔ 其他子系统 + +``` +Visual.get_snapshot_tree(session_id) → tree_data +Visual.get_module_graph(snapshot_id) → graph_data +Visual.get_diff_view(snapshot_a, snapshot_b) → diff_data +Visual.get_meeting_room(meeting_id) → meeting_state +Visual.execute_tool(tool_name, params, user_id) → result +``` + +--- + +## 6. 关键技术选型建议(非约束,供参考) + +| 层面 | 当前建议 | 理由 | +|------|----------|------| +| 工作区隔离 | 文件系统目录 + 权限掩码 | MVP 阶段足够轻量,无需 Docker | +| 快照系统 | 基于 Git 对象模型,但自定义索引 | 利用 Git 的 diffs 和 Merkle Tree,但绕过工作区限制 | +| 消息队列 | 内存通道(单进程多线程) | 原型阶段足够,未来可替换为 Redis/RabbitMQ | +| 存档存储 | SQLite + 文件系统 | 结构化查询 + 大文件(代码快照)分离存储 | +| 可视化 | TUI(ratatui)或轻量 Web(Leptos)| 取决于团队前端能力,两者都支持树状图和模块图 | +| LLM 接口 | 预留 OpenAI/Claude 兼容层 | MVP 先用硬编码模拟,接口保持一致 | + +--- + +## 7. 未解决问题(需在原型中验证) + +1. **快照树的规模上限**:复杂任务可能产生数百个快照,树状渲染性能如何? +2. **盲执行的实现细节**:测试 Agent 如何在"看不到源代码"的情况下编译和运行测试?(可能需要产品 Agent 提供预编译产物或接口桩) +3. **Supervisor 知识库的范围和更新机制**:知识库是静态文件还是可动态写入?谁负责维护? +4. **多人类协作的并发控制**:如果两个人类同时加入评审会并做出矛盾决策,系统如何处理? +5. **BFS 的"一步"粒度**:以"修复-测试循环"为一步可能太慢,以"单个 LLM 调用"为一步可能太快,需在原型中调参。 + +--- + +*文档版本:2026-06-08* +*状态:等待审阅* diff --git a/DESIGN_DECISIONS.md b/DESIGN_DECISIONS.md new file mode 100644 index 0000000..740f40c --- /dev/null +++ b/DESIGN_DECISIONS.md @@ -0,0 +1,463 @@ +# 人机协作 Agent 原型 —— 设计决策记录 + +> 本文档汇总所有已确认的设计决策及决策原因,供后续开发参考。文档中标记【已确认】的条目为当前共识,标记【待验证】的条目为假设性设计,需通过原型验证。 + +--- + +## 1. 核心哲学 + +### 1.1 任务没有"完成",只有"挂起"【已确认】 +**决策**:系统状态机中删除 `Completed` 状态,任务生命周期以 `Suspended`(挂起)为终态。 + +**原因**: +- LLM 天然倾向于"给出一个答案就结束",这种"完成幻觉"是质量失控的根源。 +- "挂起"意味着"本次推进暂停,保留随时重启和重新审视的权利",符合工程现实中"代码写完只是开始"的真理。 +- 与后续"评审会"机制天然配合:任务只有经过评审会才能从"执行中"进入"挂起",没有 shortcut。 + +### 1.2 "废弃"是"挂起"的子集【已确认】 +**决策**:分支的"废弃"不作为一种独立终态,而是挂起状态上的一个标签(`abandoned: true`)。 + +**原因**: +- AI 无权宣告任何东西"死亡",只能宣告"我推不动了"。 +- 人类可能在事后发现被废弃的分支其实有 salvage value,保留挂起状态便于回溯和复活。 + +--- + +## 2. 角色与权限体系 + +### 2.1 角色清单【已确认】 + +| 角色 | 职责 | 当前权限 | 未来可扩展权限 | +|------|------|----------|----------------| +| 产品经理 Agent | 接收人类原始需求,转化为结构化需求规格,组织需求对齐评审 | 需求结构化、需求版本管理、需求对齐评审主持 | — | +| 产品 Agent | 根据需求规格写代码 | 编码、请求知识支援、声明挂起 | — | +| 测试 Agent | 根据需求规格写测试、运行测试 | 测试生成、测试执行、标记技术性挂起 | — | +| Supervisor / 知识库 Agent | 处理认知型挂起,查资料补信息 | 知识查询、信息注入、有限次数的自动重试 | 技术性/风险性挂起的审批、分支生死判决 | +| 人类(Supervisory Agent) | 最高决策者 | 完整权限:加入任意组、使用任意工具、审批任意挂起、调整策略配置 | — | + +**原因**: +- 将人类建模为"权限最高的 Agent"而非系统外的"上帝视角",使通信模型和工具层完全统一。 +- 团队成员可以被赋予不同等级的 Supervisory 权限(例如初级成员只能审认知型挂起,资深成员可以审风险型)。 + +### 2.2 信息隔离原则【已确认】 +**决策**:产品 Agent 和测试 Agent 互为黑盒。 +- 产品 Agent 的工作区对测试 Agent 不可见。 +- 测试 Agent 的工作区对产品 Agent 不可见。 +- 两者唯一的共享 ground truth 是**需求规格**。 + +**原因**: +- 避免测试 Agent 根据实现细节写测试(即避免"测试看了代码后只测已经存在的逻辑")。 +- 迫使测试 Agent 真正从需求出发设计用例,提升测试的有效性。 +- 模拟真实工程中"测试团队独立于开发团队"的组织约束。 + +### 2.3 Supervisor 的渐进式放权【已确认】 +**决策**:Supervisor 当前仅处理"认知型挂起"(查资料、补信息、尝试修复)。其他挂起类型和分支生死权暂不开放,但架构上预留配置开关。 + +**原因**: +- 当前 LLM 的可靠性不足以承担广泛的决策权,先从"信息检索"这种低风险的职责开始验证。 +- 通过实际运行数据观察 Supervisor 的表现,逐步解锁权限,避免"一次性给权后无法收回"的困境。 + +--- + +## 3. 通信与路由 + +### 3.1 中央路由架构【已确认】 +**决策**:所有 Agent 之间的通信必须经过中央路由(Central Router),禁止点对点直连。 + +**原因**: +- 解耦 Agent 之间的直接依赖,新增或替换 Agent 无需修改其他 Agent 的代码。 +- 为未来的"AI 控制路由策略"预留空间:当前路由规则用代码写死,未来可让大模型根据上下文动态决定消息转发路径。 +- 便于实现日志、审计、权限控制(路由层可以统一做"谁可以看什么"的过滤)。 + +### 3.2 消息只带元数据【已确认】 +**决策**:消息 payload 中不包含完整上下文(如代码内容),只包含引用 ID(如快照 ID、文件路径、行号范围)。接收方通过快照系统按需拉取。 + +**原因**: +- 减少消息体积,避免广播时网络/内存爆炸。 +- 权限控制更精细:接收方能否看到内容,由快照系统的权限层决定,而不是由发送方在消息里"塞什么"决定。 +- 便于实现"事后回放":消息是轻量的,但可以通过引用 ID 还原当时的完整上下文。 + +### 3.3 三种通信模式【已确认】 +**决策**:工作台支持以下通信原语: +1. **点对点(P2P)**:Agent A → Agent B +2. **点对组(P2Group)**:Agent A → 任意多方组成的临时组 +3. **组内广播(Group Broadcast)**:组内所有成员收到同一条消息 + +**原因**: +- 评审会的本质就是"创建一个临时组并广播"。 +- 人类可能和同事组成一个"审核小组"共同审 AI 的产出,需要组的概念。 +- 组的成员是动态划定的,不是预设固定角色,保证灵活性。 + +--- + +## 4. 分支与执行策略 + +### 4.1 编码阶段禁止分支【已确认】 +**决策**:产品 Agent 在编码/实现阶段必须线性推进,不允许开分支探索多种实现方案。 + +**原因**: +- 防止开发过程中的"选择困难症"和过度设计。 +- 强制聚焦:先把一条路走到底,问题在测试阶段暴露,而不是在编码阶段纠结。 + +### 4.2 测试阶段才允许开分支【已确认】 +**决策**:只有在测试发现问题后,才允许针对"如何修复这个问题"开多条分支并行探索。 + +**原因**: +- 分支的目的是"修复验证",不是"方案选型"。 +- 避免无意义的方案爆炸:没有测试反馈的分支探索是盲目的。 + +### 4.3 BFS 并行 + 分支挂起通知【已确认】 +**决策**:多条修复分支以广度优先(BFS)方式并行运行。任何一个分支挂起时,立即产生通知。当**所有分支都挂起**时,强制触发评审会。 + +**原因**: +- BFS 保证"先广后深",人类可以快速看到"有哪些修复路线可走",而不是在一条路上钻太深。 +- "所有分支挂起 = 会议迫在眉睫"是一个穷尽性触发条件:不是"AI 觉得不行",而是"所有能试的路都试过了,全走不通"。 +- 避免人类被淹没在"每个小错误都要来问我"的噪音中。 + +### 4.4 分支 = 上下文 Fork【已确认】 +**决策**:开一个分支等价于 fork 该 Agent 当前的完整上下文(推理历史、工作区状态),在此基础上继续推理。 + +**原因**: +- 保证分支之间的完全隔离:分支 A 的尝试不会污染分支 B 的上下文。 +- 便于实现树状可视化:每个节点都可以回溯到根,看到完整的思考链。 +- 与快照系统天然配合:fork 操作本质上就是创建一个基于父快照的新快照。 + +### 4.5 分叉原因强制记录【已确认】 +**决策**:在工具层面强制要求:Agent 创建分叉时必须提供结构化原因说明,否则工作台系统拒绝接受该分叉请求。 + +**原因模板**: +``` +观察到了 [现象/测试结果], +进行了 [已尝试的修复/验证], +[或] 觉得可能是因为 [假设根因], +于是进行 [新的尝试方向]。 +``` + +**原因**: +- 防止 Agent 随意开分支导致爆炸:"写明原因"本身就是一道门槛,迫使 Agent 在分叉前做初步分析。 +- 人类在树状图上查看分叉节点时,能立刻理解"为什么在这里分了叉",无需深入代码 diff。 +- 为后续的评审会提供上下文:评审会上可以直接追问"你当时假设根因是 X,现在验证结果如何?" + +--- + +## 5. 开发阶段:Todo 系统 + +### 5.0 开发阶段用 Todo 而非分支【已确认】 +**决策**:在**编码/开发阶段**(非查错阶段),产品 Agent 不通过分叉来管理注意力,而是通过**Todo List**来规划线性开发步骤: +- 先实现模块 A +- 再实现模块 B +- 最后集成测试 + +只有在**测试发现问题后的修复阶段**,才启用分叉机制进行多路径探索。 + +**原因**: +- 开发阶段需要的是"有序推进"而不是"并行尝试":写代码时开分支探索"多种写法"是过度设计。 +- Todo List 提供可追踪的进度感:人类可以随时查看"AI 做到哪一步了,下一步计划做什么"。 +- 与"编码阶段禁止分支"(4.1)的原则对齐:开发是线性的,试错才分叉。 + +### 5.0.1 Todo 项的状态流转 +``` +TODO → DOING → DONE + ↓ + BLOCKED(遇到阻碍,可能触发挂起或 Supervisor 介入) +``` + +--- + +## 6. 需求规格与版本链 + +### 6.1 需求是线性版本链,不是树【已确认】 +**决策**:需求以**线性版本链**管理,新版本取代旧版本,需求本身**不允许分叉**。 + +- 需求版本:`v1 → v2 → v3 → ...` +- 旧版本发布新版本后自动标记为 `SUPERSEDED`(已被替代),不再是有效需求。 +- 需求**没有回退能力**:如果要"改回原来的决策",必须发布一个新的需求版本(如 v4 的内容回到 v2 的决策),而不是回退到 v2。 + +**原因**: +- 需求分叉会导致代码管理噩梦:分叉后的代码独立演化,最终变成两个完全不同的项目。 +- 线性版本链保证"同一时刻只有一个有效需求",避免多方对"到底要做什么"产生分歧。 +- 历史仍然保留(所有旧版本可读),只是不允许重新激活旧版本。 + +### 6.2 需求规格可以被挂起【已确认】 +**决策**:需求规格本身也纳入挂起模型。当产品 Agent 和测试 Agent 对需求规格的理解不一致,或人类认为需求规格需要修改时,需求规格进入**挂起状态**。 + +**原因**: +- 统一挂起模型:代码分支会挂起,需求规格也会挂起,所有挂起对象都走同一套评审会流程。 +- 防止在错误的需求基础上继续投入:需求不对齐时,强行推进编码和测试是浪费。 + +### 6.3 产品经理工作空间与 Agent 使用同一套快照系统【已确认】 +**决策**:产品经理 Agent 的工作空间(维护项目文档:需求、概要设计、详细设计、接口契约等)与产品/测试 Agent 的工作空间使用**完全相同的快照系统**。唯一的区别是:产品经理 Agent**没有分叉权**。 + +**原因**: +- 需求文档不需要分叉探索:需求是线性演进的,不存在"尝试两种不同需求规格并行推进"的场景。 +- 统一技术栈降低复杂度:不需要为文档维护一套独立的版本系统。 + +### 6.4 需求对齐评审会与修复评审会本质相同【已确认】 +**决策**:不存在独立的"需求对齐评审会"类型。需求对齐不通过导致的需求规格挂起,与代码分支挂起一样,都进入**统一的评审会**处理。 + +评审会对挂起对象的决策选项通用: +- **给新提示词继续**(`RESUME_WITH_PROMPT`):对需求规格,意味着澄清后重新对齐;对代码分支,意味着注入新思路继续修复。 +- **直接 kill**(`ABANDON`):对需求规格,意味着废弃当前版本重新撰写;对代码分支,意味着废弃该修复路线。 +- **发布新版本**(`ADJUST_REQUIREMENT`):仅适用于需求规格,发布新版本后所有基于旧需求的代码分支标记为 `STALE_REQUIREMENT`。 + +**原因**: +- 评审会的本质是"对挂起节点的决策",不应该因为挂起对象的类型不同而设计两套流程。 +- 统一模型降低系统复杂度,人类也只需要学习一种评审交互模式。 + +--- + +## 7. Agent 决策模型与身份牌 + +### 7.0 每个 Agent 绑定决策模型【已确认】 +**决策**:每个 Agent 在注册时必须绑定一个**身份牌(Role Card)**,身份牌定义了: +- 该 Agent 的决策模式(如何规划工作、何时分叉、何时挂起)。 +- 该 Agent 可用的工具集合。 +- 该 Agent 的工作区操作权限(读/写/执行的范围)。 + +**原因**: +- 不同角色的 Agent 需要不同的行为逻辑:产品 Agent 适合"产品开发型"决策(先做设计再编码),测试 Agent 适合"验证型"决策(先分析需求再生成测试)。 +- 未来可以扩展新角色(如"安全审计 Agent"、"文档生成 Agent"),只需发放新的身份牌,无需改核心架构。 +- 身份牌让系统的行为可预测、可配置:人类可以通过调整身份牌参数来改变 Agent 的行为倾向(如"更激进地尝试修复"或"更保守地尽早挂起")。 + +--- + +## 8. 挂起机制 + +### 8.1 挂起类型分类【已确认】 +**决策**:挂起分为三类,每类有不同的默认策略和处理路径: + +| 类型 | 定义 | 默认策略 | 处理路径 | +|------|------|----------|----------| +| 技术性挂起 | 测试失败、编译错误、运行时异常 | 允许 | 直接通知,等待评审 | +| 认知性挂起 | AI 不确定、缺少关键信息、触及能力边界 | **默认禁止** | 先走 Supervisor(查知识库),有尝试上限,超上限后升级为真正挂起 | +| 风险性挂起 | 改动影响面广、具有破坏性、不可逆操作 | 允许 | 直接通知,等待评审 | + +**原因**: +- 认知性挂起默认禁止,是为了逼 AI 在喊停之前尽可能收集信息、尝试推理,而不是轻易放弃。 +- 风险性挂起始终允许,因为这是安全底线,不能为了"推进"而掩盖风险。 +- 分类让人类在树状图上一眼看出"为什么停了"。 + +### 8.2 认知性挂起的出口:Supervisor 介入【已确认】 +**决策**:当认知性挂起被策略允许(或被强制触发)时,不直接叫人类,而是先由 Supervisor 尝试解决: +1. Supervisor 分析问题,查询知识库。 +2. Supervisor 通过消息注入或关键词注入给产品 Agent 补充信息。 +3. 产品 Agent 基于新信息继续尝试。 +4. 设尝试上限(如 3 次),超上限后进入真正挂起(通知人类或进评审会)。 + +**原因**: +- 大量认知型问题其实可以通过补文档、补上下文解决,不需要消耗人类注意力。 +- 尝试上限防止 Supervisor 在知识盲区里无限循环。 + +### 8.3 挂起策略可配置【已确认】 +**决策**:人类可以通过 UI 为每个任务配置"允许哪些挂起类型"。 + +**原因**: +- 不同任务对"容忍度"的要求不同:写排序算法时认知性挂起应严格禁止;做探索性研究时可以放开。 +- 配置粒度跟随任务,而非全局统一,保证灵活性。 + +### 8.4 "小挂起":执行时环境阻塞【已确认】 +**决策**:当 Agent 执行命令时被操作系统层面拒绝(如 `Permission denied`、`EACCES`、需要 `sudo`、需要交互式密码输入等),系统触发**小挂起**(执行时阻塞),**不走挂起状态机**。 + +**处理流程**: +1. Agent 调用工具(如 `run_command`)。 +2. 工具层执行命令,操作系统返回权限错误。 +3. 工具层**不**将错误上报给 Agent 推理层,而是直接向中央路由发送 `PERMISSION_REQUEST`。 +4. 人类收到通知,选择帮助 Agent 完成操作(如输入 sudo 密码、修改文件权限等)。 +5. 人类完成后,工具层重新执行命令。 +6. Agent 继续运行,状态保持 `RUNNING`,**不创建快照,不进评审会**。 + +**与"大挂起"的核心区别**: + +| 维度 | 小挂起(环境阻塞) | 大挂起(状态挂起) | +|------|-------------------|-------------------| +| 触发原因 | 操作系统权限不足 | AI 遇到认知/技术边界 | +| 触发层 | 工具层 | Agent 推理层 | +| Agent 状态 | 保持 RUNNING,被工具阻塞 | 变为 SUSPENDED | +| 是否快照 | 否 | 是 | +| 是否进树 | 否 | 是 | +| 人类动作 | 帮 AI 完成操作(输入密码等) | 做决策(评审会) | +| 是否可记忆 | 是(记住本次授权) | 否 | + +**原因**: +- 这不是 AI 的决策问题,是客观环境限制:AI 的代码逻辑没错,只是系统不给它跑。 +- 如果走评审会,人类被频繁拉入无意义的会议:输入 sudo 密码不需要"开会讨论"。 +- 工具层有强制执行力:操作系统说 `Permission denied`,不需要 prompt 来定义什么是小挂起。 + +--- + +## 9. 快照与存档 + +### 9.1 快照只在决策节点创建【已确认】 +**决策**:快照**不是**在 Agent 运行的每一步都创建,而只在两类**决策节点**创建: +1. **分叉点(Fork)**:开新分支时,必须快照当前完整上下文作为新分支的起点。 +2. **挂起点(Suspend)**:任务/分支挂起时,必须快照当前状态以便后续恢复或回溯。 + +中间过程(编码、测试执行、Supervisor 查资料)不创建快照。 + +**原因**: +- 避免快照数量爆炸导致树状图变成"毛线团"。 +- 快照的语义是"决策里程碑",不是"运行日志":人类只关心"AI 在哪做了选择"和"AI 在哪停了下来"。 +- 大幅降低存储和索引压力,让回溯操作保持轻量。 + +### 9.2 存档范围:工作过程 + 评审会【已确认】 +**决策**:以下两类内容必须进入存档: +1. **工作过程快照**:代码状态、测试状态、Agent 上下文。 +2. **评审会完整记录**:谁参与了、展示了什么、讨论了什么问题、人类的批注和最终决策。 + +**原因**: +- 工作过程存档支持回溯和分支复活。 +- 评审会存档支持"为什么当时做这个决策"的长期追溯,避免"当时怎么想的忘了"的维护噩梦。 + +### 9.3 快照树节点类型【已确认】 +**决策**:快照树中的节点按语义分为两类: +- **分叉节点(Fork Node)**:新分支的起点,标志着"AI 在这里做了一个选择,走了另一条路"。 +- **挂起节点(Suspend Node)**:任务/分支暂停的断点,标志着"AI 在这里停下来了,需要外部输入"。 + +中间运行状态不出现在快照树中。 + +**原因**: +- 保持树的稀疏性和语义清晰度:人类一眼看到的是"决策-困境"地图。 +- 与"只在决策节点快照"的原则对齐。 + +### 9.4 平级链:节点的操作历史附录【已确认】 +**决策**:每个主树节点(分叉节点或挂起节点)可以挂载一条**平级链(Side Chain)**,记录到达该节点之前的所有中间操作快照。 + +- **平级链上的快照不参与树的拓扑结构**:它们不改变主树的分叉/挂起语义,只是该节点的历史附件。 +- **平级链内容**:危险操作前备份、开发阶段中间状态、挂起被打回后的重试记录等。 +- **挂起被打回时的处理**:原挂起节点的快照被挂载到"下一个推演起点"的平级链头部,作为历史上下文保留。 + +**示例**: +``` +节点 N(挂起节点) +├── 主树上下文:父节点 → 分叉点 F → ... → 根 +└── 平级链(Side Chain) + ├── 快照 attempt-1:挂起被打回后的第一次重试 + ├── 快照 pre-danger-2:危险操作前(删除旧缓存) + └── 快照 pre-danger-1:危险操作前(编译产物写入) +``` + +**原因**: +- 主树保持稀疏和清晰:人类一眼看到的是"决策-困境"地图,不被中间操作淹没。 +- 审计需求得到满足:当需要追溯"AI 是怎么走到这一步的"时,平级链提供了完整的操作日志。 +- 挂起被打回的历史不被丢弃:每次尝试都保留在平级链上,便于后续分析"为什么这次重试成功了/失败了"。 + +### 9.5 树状快照组织【已确认】 +**决策**:快照以树状结构组织,支持以下操作: +- 查看任意节点的完整思考链(从根到该节点)。 +- 查看任意节点的平级链(该节点的操作历史附录)。 +- 对比两个分叉节点的差异(从分叉点开始的不同路径)。 +- 快速回溯到任意历史节点。 + +**原因**: +- 人类需要理解"AI 是怎么走到这一步的",线性日志无法满足。 +- 分叉对比是评估不同修复方案的核心交互。 + +--- + +## 10. 可视化与交互 + +### 10.1 树状图:核心诊断面板【已确认】 +**决策**:工作台提供树状图可视化,作为人类观察 AI 思维过程的**主要界面**。 + +**核心交互**: +- 每个节点代表一个快照/决策点。 +- 点击节点:展示从根到该节点的完整思考链。 +- 点击两个不同节点:展示从分叉点开始的差异对比。 +- 挂起节点用颜色/图标标识其类型(技术/认知/风险)。 +- 点击挂起节点:查看挂起原因、相关日志、建议的修复方案。 + +**原因**: +- 人类不是在看"AI 的输出结果",而是在看"AI 的推理过程"。树状图是这个过程的最佳映射。 +- 颜色编码让"哪里卡住了"一目了然。 + +### 10.2 模块关系图 + 接口查看【已确认】 +**决策**:在评审会或逐模块阐释时,提供模块关系图(方框表示模块,连线表示接口依赖)。点击连线可查看接口的具体定义。 + +**原因**: +- 评审会上的"逐模块阐释"需要直观的拓扑视图,而不是堆砌文本。 +- 接口是模块契约的核心,需要可点击穿透的详情展示。 + +--- + +## 11. 评审会 + +### 11.1 评审会是强制关卡【已确认】 +**决策**:评审会是任务推进的必经关卡。触发条件: +- **所有分支都挂起**时,**强制**触发评审会(不可跳过)。 +- **需求规格挂起**时,强制触发评审会(需求对齐不通过)。 +- 人类可**手动**随时触发评审会(即使还有分支在运行)。 + +**原因**: +- "所有分支挂起"是穷尽性信号:AI 已经尝试了所有能试的路线,必须引入人类判断。 +- "需求规格挂起"是早期拦截信号:防止在错误理解的需求上继续投入。 +- 手动触发保留人类的主动干预权。 + +### 11.2 评审会在临时工作区中进行【已确认】 +**决策**:评审会期间,人类或 Agent 对代码的任何修改只能在**工作台分配的临时工作区**中进行,**不允许直接写入项目主干或任何活跃分支的工作区**。 + +**原因**: +- 评审会是"审查和讨论"的场所,不是"直接修改生产环境"的场所。 +- 防止会议期间的"随手改"污染正式工作区,保证快照树的纯净性。 +- 只有经过显式决策的结论(如"批准分支 B 继续"、"给分支 C 注入新提示词")才会被工作台作为系统指令下发执行。 + +### 11.3 评审会结果是操作挂起对象【已确认】 +**决策**:评审会不产生直接代码修改,只产生对**挂起对象**的操作指令。挂起对象可以是代码分支,也可以是需求规格,决策选项通用: + +| 决策指令 | 对代码分支的含义 | 对需求规格的含义 | +|----------|-----------------|-----------------| +| `ABANDON` | 废弃该修复分支 | 废弃当前需求版本,重新撰写 | +| `RESUME_WITH_PROMPT` | 给分支注入新提示词继续修复 | 澄清需求后重新组织对齐评审 | +| `FORK` | 基于某快照开新分支尝试 | 不适用 | +| `ADJUST_REQUIREMENT` | 发布新需求版本,当前分支标记为基于旧需求 | 发布新版本需求规格 | + +**原因**: +- 把"审查"和"执行"分离:评审会负责"决定做什么",分支管理引擎/产品经理负责"实际去做"。 +- 所有操作都可追溯、可回滚,符合快照系统的树状语义。 +- 统一模型降低认知负担:人类无论审代码还是审需求,交互模式相同。 + +### 11.4 评审会记录独立存储【已确认】 +**决策**:评审会的完整会议记录**不属于快照节点系统**,而是作为**独立存档**存储。会议记录通过 `trigger_snapshot_id` 字段关联到导致评审会的挂起节点,但本身不成为树节点。 + +**原因**: +- 快照树只反映 Agent 实际推进过的代码状态,评审会的临时改动和讨论不应出现在树上。 +- 人类可以通过点击挂起节点查看关联的会议记录(像查看"附件"),但会议记录不参与树的拓扑计算。 +- 保持树的语义纯粹:节点 = 代码状态里程碑,附件 = 当时的人类决策上下文。 + +--- + +## 12. 工具层 + +### 12.1 工具对 Agent 和人类统一开放【已确认】 +**决策**:Agent 使用的所有工具(代码编辑器、测试运行器、知识库查询、快照操作等)人类也可以通过界面使用。 + +**原因**: +- 人类不是系统的旁观者,而是网络中权限最高的参与者。 +- 统一工具层避免"人类想看代码却找不到入口"的尴尬。 +- 便于人类在评审会上直接操作(如修改代码、运行测试),而不是"口头指挥 AI 去改"。 + +--- + +## 13. 待验证假设【待验证】 + +以下设计决策基于当前讨论形成,但需要通过原型运行验证其可行性: + +1. **Supervisor 的知识库查询能否有效降低认知型挂起升级到人类的频率?** + - 假设:70% 的认知型问题可以通过补文档解决。 + - 风险:Supervisor 可能检索到错误信息,反而误导产品 Agent。 + +2. **BFS 分支并行在资源受限环境下是否可运行?** + - 假设:3-5 条分支的并行在单机上可接受。 + - 风险:如果任务复杂,分支数爆炸可能导致内存/CPU 不足。 + +3. **树状可视化的信息密度 humans 能否承受?** + - 假设:10-20 个节点的树对人类是可读的。 + - 风险:复杂任务可能产生上百个节点,树状图变成"毛线团"。 + +4. **信息隔离是否会导致测试 Agent 写出过于宽泛或过于严苛的测试?** + - 假设:基于需求写测试的质量高于基于实现写测试。 + - 风险:测试 Agent 对需求的理解偏差可能导致测试与实现永远无法对齐。 + +--- + +*文档版本:2026-06-08* +*状态:等待审阅*