- commit
- 8fe3836
- parent
- 3283b54
- author
- im_wower
- date
- 2026-03-27 22:25:11 +0800 CST
docs(claude): BAA instruction system review — BUG-018/019/020, MISSING-001/002/003, OPT-002~006
12 files changed,
+258,
-9
1@@ -1,8 +1,11 @@
2 # BUG-018: preflight 整批失败 — 一条坏指令杀死所有并行指令
3
4+> 提交者:Claude(代码审查)
5+> 日期:2026-03-27
6+
7 ## 现象
8
9-AI 发 3 个 baa 代码块,其中 1 个 target 不支持,preflight 对第一个不支持的指令 throw,导致整批 3 条指令全部失败。
10+AI 发 3 个 baa 代码块,其中 1 个 target 不支持(比如 `@browser.chatgpt::send`),preflight 对第一个不支持的指令 throw BaaInstructionCenterError,导致整批 3 条指令全部失败,包括 2 条完全合法的 `@conductor::exec`。
11
12 ## 文件
13
14@@ -14,8 +17,30 @@ preflight 用 `.map()` + throw,一个失败整个 map 中断。
15
16 ## 修复
17
18-改为 filter-and-collect:合法指令继续执行,不合法的收集到 denied 数组。processAssistantMessage 结果中包含 denied 信息。
19+改为 filter-and-collect 模式——合法指令继续执行,不合法的收集到 denied 数组:
20+
21+```typescript
22+private preflight(instructions) {
23+ const routed = [];
24+ const denied = [];
25+ for (const inst of instructions) {
26+ const decision = evaluateBaaInstructionPolicy(inst);
27+ if (!decision.ok) {
28+ denied.push({ instruction: inst, reason: decision.message });
29+ continue;
30+ }
31+ try {
32+ routed.push({ instruction: inst, route: routeBaaInstruction(inst) });
33+ } catch (error) {
34+ denied.push({ instruction: inst, reason: error.message });
35+ }
36+ }
37+ return { routed, denied };
38+}
39+```
40+
41+processAssistantMessage 结果中包含 denied 信息,让调用方知道哪些被拒了。
42
43 ## 严重度
44
45-High
46+High — 直接影响并行执行的核心场景
1@@ -1,8 +1,11 @@
2 # BUG-019: 未关闭的 baa 代码块导致整条消息处理失败
3
4+> 提交者:Claude(代码审查)
5+> 日期:2026-03-27
6+
7 ## 现象
8
9-AI 回复中有一个未关闭的 ` ```baa ` 块时,extractBaaInstructionBlocks throw,已关闭的合法 baa 块也不会被处理。
10+AI 回复中有一个未关闭的 ` ```baa ` 块(比如 AI 在写示例时忘了关闭),extractBaaInstructionBlocks throw BaaInstructionExtractError,已关闭的合法 baa 块也不会被处理。
11
12 ## 文件
13
14@@ -18,8 +21,16 @@ if (pending?.isBaa) {
15
16 ## 修复
17
18-未关闭的块忽略(warn log),不 throw。已关闭的合法块正常返回。
19+未关闭的块忽略(warn log),不 throw。已关闭的合法块正常返回:
20+
21+```javascript
22+if (pending?.isBaa) {
23+ // 未关闭的 baa 块 → 忽略,不 throw
24+ // 可选:记录 warning
25+}
26+return blocks;
27+```
28
29 ## 严重度
30
31-Medium
32+Medium — AI 偶尔会输出未关闭的代码块
1@@ -1,8 +1,11 @@
2 # BUG-020: InMemory 去重器无上限,长期运行内存泄漏
3
4+> 提交者:Claude(代码审查)
5+> 日期:2026-03-27
6+
7 ## 现象
8
9-InMemoryBaaInstructionDeduper 和 InMemoryBaaLiveInstructionMessageDeduper 的 Set 只 add 不清理,没有 TTL 或 maxSize。
10+InMemoryBaaInstructionDeduper 和 InMemoryBaaLiveInstructionMessageDeduper 的 Set 只 add 不清理,没有 TTL 或 maxSize。长时间运行后 Set 无限增长。
11
12 ## 文件
13
14@@ -11,7 +14,26 @@ InMemoryBaaInstructionDeduper 和 InMemoryBaaLiveInstructionMessageDeduper 的 S
15
16 ## 修复
17
18-加 maxSize 限制(默认 10000),超出时清理最旧的 20%。或用 Map<string, number> 记录时间戳做 LRU。
19+加 maxSize 限制(默认 10000),超出时清理最旧的 20%。或改用 Map<string, number> 记录时间戳做 LRU:
20+
21+```typescript
22+class InMemoryBaaInstructionDeduper {
23+ private readonly keys = new Map<string, number>();
24+ private readonly maxSize = 10000;
25+
26+ add(instruction) {
27+ if (this.keys.size >= this.maxSize) {
28+ const entries = [...this.keys.entries()].sort((a, b) => a[1] - b[1]);
29+ for (let i = 0; i < entries.length * 0.2; i++) {
30+ this.keys.delete(entries[i][0]);
31+ }
32+ }
33+ this.keys.set(instruction.dedupeKey, Date.now());
34+ }
35+
36+ has(dedupeKey) { return this.keys.has(dedupeKey); }
37+}
38+```
39
40 ## 严重度
41
1@@ -0,0 +1,47 @@
2+# MISSING-001: 执行结果没有回注到 AI 对话
3+
4+> 提交者:Claude(代码审查)
5+> 日期:2026-03-27
6+
7+## 优先级
8+
9+**最高** — 端到端闭环的最后一环
10+
11+## 现状
12+
13+instructions/ 模块完成了 提取 → 解析 → 去重 → 权限 → 路由 → 执行 的完整链路。
14+artifacts/ 模块有 materialize、manifest、delivery-plan、upload-session 的完整代码。
15+
16+但**从执行结果到实际注入 AI 对话框**没有接通:
17+
18+- `upload-session.ts` 有 `this.bridge.injectMessage()` 和 `this.bridge.uploadFile()` 调用
19+- 但 `this.bridge` 是抽象接口,没有和 firefox-bridge 的实际 wiring
20+- conductor 执行完指令后,结果停留在 `BaaInstructionProcessResult` 中
21+- firefox-ws.ts 的 `handleBrowserFinalMessage` 调用了 `instructionIngest.ingestAssistantFinalMessage()`,但拿到结果后没有后续动作
22+
23+## 需要补的链路
24+
25+```
26+firefox-ws.ts 收到 browser.final_message
27+→ instructionIngest.ingestAssistantFinalMessage() 执行指令
28+→ 拿到 BaaInstructionProcessResult
29+→ 调 artifact materializer(根据结果大小决定 inline/artifact/artifact_only)
30+→ 生成 delivery plan
31+→ 通过 WS 下发 delivery plan 给插件
32+→ 插件执行上传(如有 artifact)
33+→ 插件返回 upload receipt
34+→ conductor 确认后生成索引文本
35+→ 通过 WS 让插件注入索引文本并发送
36+```
37+
38+## 涉及文件
39+
40+- `apps/conductor-daemon/src/firefox-ws.ts`:handleBrowserFinalMessage 需要加后续流程
41+- `apps/conductor-daemon/src/artifacts/upload-session.ts`:bridge 接口需要和 firefox-bridge 对接
42+- `plugins/baa-firefox/controller.js`:需要加处理 delivery_plan 消息的分支
43+
44+## 验收
45+
46+1. Claude 对话中 AI 回复包含 `@conductor::exec::pwd` → conductor 自动执行 → 结果回注到 Claude 对话框
47+2. 大结果走文件上传 + 索引文本
48+3. 小结果直接文本注入
1@@ -0,0 +1,37 @@
2+# MISSING-002: 插件侧没有 delivery plan 执行器
3+
4+> 提交者:Claude(代码审查)
5+> 日期:2026-03-27
6+
7+## 优先级
8+
9+**最高** — 和 MISSING-001 配合,缺一不可
10+
11+## 现状
12+
13+controller.js 有 `relayObservedFinalMessage` 把最终消息发给 conductor,但没有处理 conductor 返回的 delivery plan。
14+
15+## 需要补
16+
17+controller.js 中加处理 WS 消息的新分支:
18+
19+```javascript
20+case "delivery_plan":
21+ await handleDeliveryPlan(message);
22+ break;
23+```
24+
25+handleDeliveryPlan 需要:
26+1. 按 plan.uploads 逐个上传文件(模拟拖拽到 AI 输入框的文件区域)
27+2. 每个上传完成后发 upload_receipt 回 conductor
28+3. 全部上传完成后,注入 plan.messageText 到 AI 输入框
29+4. 点击发送按钮
30+
31+## 涉及文件
32+
33+- `plugins/baa-firefox/controller.js`
34+
35+## 验收
36+
37+1. conductor 下发 delivery plan → 插件成功上传文件 + 注入文本 + 发送
38+2. 上传失败时返回失败 receipt,conductor 降级为文本注入
1@@ -0,0 +1,25 @@
2+# MISSING-003: browser.* target 在 Phase 1 被完全拒绝
3+
4+> 提交者:Claude(代码审查)
5+> 日期:2026-03-27
6+
7+## 优先级
8+
9+Medium
10+
11+## 现状
12+
13+`instructions/policy.ts` 的 SUPPORTED_TARGETS 只有 `conductor` 和 `system`。
14+
15+根据 BAA_INSTRUCTION_SYSTEM.md 的设计,Phase 1 应该包含 `browser.claude` 的 send/current 能力——这是能力互补的核心场景。
16+
17+## 修复
18+
19+1. policy.ts:SUPPORTED_TARGETS 加 `browser.claude`
20+2. router.ts:加 `browser.claude` → `POST /v1/browser/request` 的路由
21+3. send 工具:把 params 映射为 browser/request 的 body
22+
23+## 涉及文件
24+
25+- `apps/conductor-daemon/src/instructions/policy.ts`
26+- `apps/conductor-daemon/src/instructions/router.ts`
+16,
-0
1@@ -0,0 +1,16 @@
2+# OPT-002: executor 缺少超时保护
3+
4+> 提交者:Claude(代码审查)
5+> 日期:2026-03-27
6+
7+## 文件
8+
9+`apps/conductor-daemon/src/instructions/executor.ts`
10+
11+## 现状
12+
13+executeBaaInstruction() 直接调 handleConductorHttpRequest 无超时。如果 exec 命令卡住(死循环 shell 脚本),整个 instruction pipeline 无限阻塞。
14+
15+## 建议
16+
17+加 Promise.race 超时(默认 30s,exec 可配 60s)。或在 handleConductorHttpRequest 调用时传 AbortController。
+16,
-0
1@@ -0,0 +1,16 @@
2+# OPT-003: policy 应支持配置化
3+
4+> 提交者:Claude(代码审查)
5+> 日期:2026-03-27
6+
7+## 文件
8+
9+`apps/conductor-daemon/src/instructions/policy.ts`
10+
11+## 现状
12+
13+SUPPORTED_TARGETS 和 SUPPORTED_TOOLS 硬编码为 Set 常量。Phase 2 加新 target/tool 时需要改代码。
14+
15+## 建议
16+
17+改为 BaaInstructionCenter 构造时可传入自定义 policy(allowedTargets/allowedTools),默认值仍是当前 Phase 1 集合。
1@@ -0,0 +1,16 @@
2+# OPT-004: final-message.js Claude SSE 拼接需要 fallback
3+
4+> 提交者:Claude(代码审查)
5+> 日期:2026-03-27
6+
7+## 文件
8+
9+`plugins/baa-firefox/final-message.js`
10+
11+## 现状
12+
13+Claude 的最终消息提取依赖 SSE chunk 中 `type: "completion"` + `completion` 字段拼接。如果 Claude SSE 格式变化(新版 API 可能用 content_block_delta),拼接会断。
14+
15+## 建议
16+
17+加 fallback:SSE 拼接为空时,尝试从 DOM 提取最终文本(找到最后一个 assistant message 的文本节点)。
1@@ -0,0 +1,16 @@
2+# OPT-005: normalize 阶段 parse 错误不应中断整批
3+
4+> 提交者:Claude(代码审查)
5+> 日期:2026-03-27
6+
7+## 文件
8+
9+`apps/conductor-daemon/src/instructions/loop.ts` normalize()
10+
11+## 现状
12+
13+.map() 遍历 blocks 解析,中间某个 block 格式错误 throw 后,后面的合法 blocks 不会被处理。和 BUG-018 同类问题。
14+
15+## 建议
16+
17+改为 flatMap + try/catch,解析失败的 block 跳过并记录到 parseErrors 数组,不影响其他 blocks。
+17,
-0
1@@ -0,0 +1,17 @@
2+# OPT-006: DB 表缺少自动清理策略
3+
4+> 提交者:Claude(代码审查)
5+> 日期:2026-03-27
6+
7+## 文件
8+
9+- `ops/sql/migrations/0003_baa_execution_persistence.sql`
10+- `packages/db/src/index.ts`
11+
12+## 现状
13+
14+baa_message_dedupes、baa_instruction_dedupes、baa_execution_journal 三张表没有自动清理。store.ts 的 listBaaExecutionJournal 有 limit 参数但只影响查询,不影响存储。
15+
16+## 建议
17+
18+packages/db 中加定期清理方法(保留最近 30 天或最近 10000 条),在 conductor 启动时和每小时调用一次。
1@@ -1,6 +1,7 @@
2 # BAA 指令系统代码审查(Codex commit 72de524)
3
4-日期:2026-03-27
5+> 提交者:Claude(代码审查)
6+> 日期:2026-03-27
7 审查范围:instructions/(11 文件)、artifacts/(5 文件)、final-message.js、content-script.js 扩展、firefox-ws.ts 扩展、local-api.ts 扩展、DB migration 0003
8
9 ---