baa-conductor

git clone 

commit
79c932a
parent
a29ea3c
author
codex@macbookpro
date
2026-03-26 17:00:49 +0800 CST
docs: refine firefox bridge planning
3 files changed,  +623, -0
M plans/BROWSER_BRIDGE_PERSISTENCE_REQUIREMENTS.md
+44, -0
 1@@ -6,6 +6,11 @@
 2 - 优先级:`high`
 3 - 记录时间:`2026-03-26`
 4 
 5+## 关联文档
 6+
 7+- [FIREFOX_BRIDGE_CONTROL_REQUIREMENTS.md](/Users/george/code/baa-conductor/plans/FIREFOX_BRIDGE_CONTROL_REQUIREMENTS.md)
 8+- [DISCUSS-FIREFOX-BRIDGE-CONTROL.md](/Users/george/code/baa-conductor/plans/discuss/DISCUSS-FIREFOX-BRIDGE-CONTROL.md)
 9+
10 ## 背景
11 
12 当前 Firefox 插件已经能发现登录态、账户和 API 端点,但 `conductor` 侧更偏内存态浏览器桥接摘要。
13@@ -19,6 +24,7 @@
14 - `conductor` 不持久化原始 `cookie`、`token`、`header` 值
15 - 浏览器侧只保留一个空壳标签页,不承载真实对话 UI
16 - 业务请求走已拦截和已验证过的 API 端点,由浏览器侧代发
17+- 首版以 `client_id` 作为执行侧唯一标识;`host` / `browser` 先作为元数据保存,不在首版参与复杂调度
18 
19 ## 需求目标
20 
21@@ -72,6 +78,43 @@
22   - 用原始凭证在浏览器本地代发请求
23 - 插件向 `conductor` 上报的是元数据、指纹和端点,不是原始凭证值
24 
25+## 空壳页定义
26+
27+- 空壳页必须是目标平台的一方页面,不能是 `about:blank` 或扩展自定义页
28+- 目标是同时满足:
29+  - 继承平台登录态
30+  - 能注入页面内 fetch/SSE 执行环境
31+  - 不承载真实对话 UI 作为主能力
32+- 首版每个平台最多维护一个空壳页
33+- 空壳页是否存活、是否需要恢复,由 Firefox 插件持续检测并向 `conductor` 上报
34+- 默认健康检查应至少覆盖:
35+  - tab 生命周期事件
36+  - `30s` 周期巡检
37+- 空壳页的控制和恢复语义,统一以控制方案文档为准
38+
39+## 凭证指纹规范
40+
41+- 指纹在 Firefox 插件侧生成,`conductor` 不接触原始凭证值
42+- 指纹输入是插件本地可见的认证材料规范化结果:
43+  - 参与认证的 cookie
44+  - 参与认证的 auth/header 值
45+  - 其他平台特有会话字段
46+- 规范化后按稳定顺序拼接,再做 `SHA-256`
47+- 上报给 `conductor` 的是十六进制摘要,不是原始值
48+- 指纹变化表示登录态已更新:
49+  - 更新 `captured_at`
50+  - 更新 `last_seen_at`
51+  - 状态保持 `fresh`
52+
53+## 首版执行标识
54+
55+- 首版浏览器代发和调度以 `client_id` 作为唯一执行者标识
56+- `host`、`browser`、`account` 继续持久化,但短期只用于:
57+  - 查询
58+  - 展示
59+  - 审计
60+- 多浏览器、多 client 的复杂调度留作后续扩展,不作为首版必做范围
61+
62 ## `conductor` 侧需求
63 
64 - 提供持久化的浏览器登录态记录
65@@ -90,6 +133,7 @@
66 - 完整的页面自动化
67 - 页面聊天 UI 编排
68 - 多标签并行对话管理
69+- 多 client 全局最优调度
70 - 把原始凭证迁移到 `conductor` 端直接发请求
71 
72 ## 当前优先级判断
A plans/FIREFOX_BRIDGE_CONTROL_REQUIREMENTS.md
+368, -0
  1@@ -0,0 +1,368 @@
  2+# Firefox 桥接控制与代发需求
  3+
  4+## 状态
  5+
  6+- `TODO`
  7+- 优先级:`high`
  8+- 记录时间:`2026-03-26`
  9+
 10+## 关联文档
 11+
 12+- [BROWSER_BRIDGE_PERSISTENCE_REQUIREMENTS.md](/Users/george/code/baa-conductor/plans/BROWSER_BRIDGE_PERSISTENCE_REQUIREMENTS.md)
 13+- [DISCUSS-FIREFOX-BRIDGE-CONTROL.md](/Users/george/code/baa-conductor/plans/discuss/DISCUSS-FIREFOX-BRIDGE-CONTROL.md)
 14+
 15+## 背景
 16+
 17+浏览器桥接持久化已经把登录态元数据、`account`、凭证指纹和 API 端点收口到 `conductor`。
 18+
 19+下一阶段需要把 Firefox 桥接正式分成两个模块:
 20+
 21+- `conductor`:控制平面和全局调度平面
 22+- Firefox 插件:本地执行平面和页面桥接平面
 23+
 24+目标是把“插件管理能力”和“浏览器代发能力”都定义成正式需求,而不是继续停留在诊断路径或页面对话能力上。
 25+
 26+## 核心结论
 27+
 28+- 浏览器桥接正式分为两个模块:`conductor` 和 Firefox 插件
 29+- AI 侧能力发现不再新增 `browser describe` 或 `plugin describe`
 30+- `conductor` 只保留两层正式 describe:
 31+  - `/describe/business`
 32+  - `/describe/control`
 33+- 首批正式能力必须同时覆盖:
 34+  - 管理类
 35+  - 功能类
 36+- `SSE` 必须是首批正式能力,不是后续增强项
 37+- 原始凭证始终只留在浏览器本地
 38+- 抖动、限流、并发控制、失败退避等主策略放在 `conductor`
 39+- Firefox 插件只负责本地执行和最后一道保护,不承担全局调度职责
 40+- 首版以 `client_id` 作为唯一执行侧标识,不把多 client 最优调度当作首版交付目标
 41+
 42+## 首版范围
 43+
 44+- 首版主要面向单 Firefox client 场景
 45+- 首版每个平台最多维护一个空壳页
 46+- 首版以 `client_id` 作为执行目标选择键
 47+- `host` / `browser` / `account` 先保留为元数据,不进入复杂调度决策
 48+- 多 client、多浏览器协调只做结构预留,不做首版强承诺
 49+
 50+## Describe 收口
 51+
 52+### 目标
 53+
 54+- 不再为浏览器桥接单独引入第三层 describe
 55+- 不让 AI 调用方额外理解“browser/plugin 是不是单独能力面”
 56+- 保持当前能力发现模型简单稳定:只有业务类和控制类
 57+
 58+### 正式结构
 59+
 60+- `GET /describe`
 61+  - 只作为入口索引
 62+  - 告诉调用方下一步应读 `business` 还是 `control`
 63+- `GET /describe/business`
 64+  - 承载业务查询和业务动作
 65+  - 也承载浏览器功能类能力
 66+- `GET /describe/control`
 67+  - 承载系统控制和本机控制动作
 68+  - 也承载插件管理类能力
 69+- `GET /v1/capabilities`
 70+  - 保留为机器可读摘要
 71+  - 不承担额外的分层解释职责
 72+
 73+### 归类原则
 74+
 75+#### 放进 `/describe/business`
 76+
 77+- 浏览器登录态读面
 78+- 浏览器可用平台和可用账户读面
 79+- 浏览器代发请求能力
 80+- SSE 流式能力
 81+- Claude 及后续平台的业务型浏览器调用
 82+- `codex` 会话与 turn 能力
 83+- tasks、controllers、业务查询能力
 84+
 85+#### 放进 `/describe/control`
 86+
 87+- 插件状态读面
 88+- WS 重连
 89+- 管理页重载
 90+- 平台页打开、聚焦、重载、恢复
 91+- 系统 `pause` / `resume` / `drain`
 92+- `exec`
 93+- `files/read`
 94+- `files/write`
 95+
 96+### 明确不做
 97+
 98+- 不新增 `/describe/browser`
 99+- 不新增 `/describe/plugin`
100+- 不要求 AI 直接理解 Firefox WS bridge 协议
101+- 不把底层 bridge message 暴露成 describe 主模型
102+
103+## 接口迁移策略
104+
105+### 现状
106+
107+- 当前正式浏览器业务接口仍以 Claude 专用路径为主:
108+  - `POST /v1/browser/claude/open`
109+  - `POST /v1/browser/claude/send`
110+  - `GET /v1/browser/claude/current`
111+  - `POST /v1/browser/claude/reload`
112+
113+### 目标
114+
115+- 新能力收口到平台无关的通用浏览器接口
116+- 过渡期允许 Claude 专用接口和新接口并存
117+- Claude 专用接口在新接口稳定后降为 legacy 包装层
118+
119+### 通用接口方向
120+
121+- `GET /v1/browser`
122+  - 统一读面
123+- `POST /v1/browser/actions`
124+  - 管理类动作入口
125+- `POST /v1/browser/request`
126+  - 通用浏览器请求入口
127+- `POST /v1/browser/request/cancel`
128+  - 请求或流取消入口
129+
130+### 兼容策略
131+
132+- `POST /v1/browser/claude/open`
133+  - 等价包装到 `POST /v1/browser/actions`
134+- `POST /v1/browser/claude/send`
135+  - 等价包装到 `POST /v1/browser/request`
136+- `POST /v1/browser/claude/reload`
137+  - 等价包装到 `POST /v1/browser/actions`
138+- `GET /v1/browser/claude/current`
139+  - 首版继续保留为 Claude 辅助读接口
140+  - 不再作为未来通用模型的核心入口
141+
142+### 迁移完成条件
143+
144+- 通用接口覆盖现有 Claude 主路径
145+- smoke 和文档改为默认引用通用接口
146+- Claude 专用接口全部标记为 legacy 后,再进入后续清理
147+
148+## 模块一:`conductor`
149+
150+### 目标
151+
152+- 作为 Firefox 桥接的统一控制面
153+- 作为浏览器请求代发的全局调度面
154+- 作为浏览器登录态和端点元数据的持久化读写面
155+
156+### 管理类需求
157+
158+- 查询插件状态:
159+  - 在线/离线
160+  - WS 是否连接
161+  - 管理页是否在线
162+  - 各平台 shell 页是否存在
163+  - 最近错误和最近重连时间
164+- 支持远程控制动作:
165+  - 重连 WS
166+  - 重载管理页
167+  - 打开或聚焦平台 shell 页
168+  - 重载平台 shell 页
169+  - 恢复缺失的平台 shell 页
170+- 支持浏览器断连后的状态保留和重连后的状态恢复
171+
172+### Tab 状态模型
173+
174+- `conductor` 维护平台级期望状态 `desired`
175+- Firefox 插件持续上报实际状态 `actual`
176+- 首版期望状态粒度是“每个平台一个空壳页”
177+- `tab_restore` 的含义是:
178+  - 重建 `desired` 中存在但 `actual` 中缺失的空壳页
179+- `actual` tab 状态首版保留内存态,不做长期持久化
180+- 浏览器重连后由插件重新上报 `actual`,`conductor` 再做调和
181+
182+### 功能类需求
183+
184+- 下发 API 请求,由浏览器侧代发
185+- 接收结构化普通响应:
186+  - 成功
187+  - 失败
188+  - 超时
189+  - 取消
190+- 接收结构化 SSE 响应:
191+  - `stream_open`
192+  - `stream_event`
193+  - `stream_end`
194+  - `stream_error`
195+- 支持请求取消
196+- 支持按平台、浏览器 client、`account` 选择代发目标
197+
198+### SSE 可靠性设计
199+
200+- 每条流都有稳定 `stream_id`
201+- 每个 `stream_event` 都带递增 `seq`
202+- 首版不做跨 WS 断连的 event 重传
203+- 如果流过程中断连、超时或本地执行失败:
204+  - `conductor` 向调用方返回 `stream_error`
205+  - 已成功收到的 partial events 仍然有效
206+- 默认超时建议:
207+  - `stream_open` 超时:`10s`
208+  - `stream_open` 后空闲超时:`30s`
209+- 默认缓冲上限建议:
210+  - `256` 个 events
211+  - 或 `512KB` 累积流数据
212+- 超时阈值和缓冲上限应可配置
213+- 如果本地缓冲溢出或回传跟不上,优先失败并返回 `stream_error`,不 silently drop
214+
215+### 调度与风控需求
216+
217+- 统一做平台级限流
218+- 统一做账号级限流
219+- 统一做并发控制
220+- 统一做失败退避
221+- 统一做熔断和恢复
222+- 统一做人类化抖动,例如高斯延迟
223+- 保留请求和流事件日志,便于审计和排障
224+
225+### 默认策略参数
226+
227+- 参数都应由 `conductor` 配置驱动,不写死在插件里
228+- 首版默认值建议:
229+  - 抖动:高斯延迟,`mu=2s`、`sigma=0.5s`、夹到 `[1s, 5s]`
230+  - 平台限流:`10 req/min/platform`
231+  - 平台并发:`1 in-flight/client/platform`
232+  - 失败退避:指数退避,`base=1s`、`max=60s`
233+  - 熔断:连续 `5` 次失败后打开,`60s` 后半开试探
234+- 当前有效策略摘要应能通过 `/describe/control` 或等价控制读面读取
235+
236+### 明确不做
237+
238+- 不保存原始 `cookie`、`token`、header 值
239+- 不直接脱离浏览器持凭证调用上游 API
240+- 不把页面对话 UI 自动化当主能力
241+
242+## 模块二:Firefox 插件
243+
244+### 目标
245+
246+- 作为浏览器本地 runtime
247+- 作为页面环境和真实登录态的持有者
248+- 作为 API 请求和 SSE 的本地执行器
249+
250+### 管理类需求
251+
252+- 常驻管理页可自恢复
253+- 能建立、保持和重建与 `conductor` 的 WS 连接
254+- 能打开、聚焦、重载和恢复平台 shell 页
255+- 能回报本地页面真实状态,而不是只回报期望状态
256+
257+### 空壳页定义
258+
259+- 空壳页必须是目标平台的一方页面,不能用 `about:blank`
260+- 空壳页需要同时满足:
261+  - 共享目标平台 cookie 和登录态
262+  - 允许插件注入 fetch/SSE 执行环境
263+  - 不把真实对话 UI 当作主能力
264+- 首版每个平台只维持一个空壳页
265+- 插件需要持续检测空壳页是否仍存在、是否已失效,并及时上报
266+- 默认健康检查应至少覆盖:
267+  - tab 生命周期事件
268+  - `30s` 周期巡检
269+
270+### 功能类需求
271+
272+- 使用浏览器本地登录态代发 API 请求
273+- 在页面内拦截并转发 SSE 流
274+- 回传结构化请求结果和流事件
275+- 支持本地超时和本地取消
276+- 支持空壳平台页,不依赖真实对话 UI
277+
278+### 本地保护需求
279+
280+- 页面未就绪时拒绝执行请求
281+- 缺失 shell 页时先恢复再执行
282+- 单页或单平台可串行化执行
283+- 保留最小发送间隔
284+- 连续失败时进入短暂自我保护
285+
286+### 明确不做
287+
288+- 不承载全局限流策略
289+- 不承载全局抖动策略
290+- 不承载跨浏览器或跨账号调度
291+- 不要求实现真正的“浏览器扩展重启”
292+
293+## 管理类正式能力
294+
295+- `plugin_status`
296+- `ws_reconnect`
297+- `controller_reload`
298+- `tab_open`
299+- `tab_focus`
300+- `tab_reload`
301+- `tab_restore`
302+
303+说明:
304+
305+- “重启插件”在正式需求里改写为“软重启 runtime”
306+- 软重启 runtime 的含义是:
307+  - 重载管理页
308+  - 重建 WS
309+  - 重新扫描和恢复平台页
310+  - 重新上报状态
311+
312+## 功能类正式能力
313+
314+- `api_request`
315+- `api_response`
316+- `stream_open`
317+- `stream_event`
318+- `stream_end`
319+- `stream_error`
320+- `request_cancel`
321+
322+说明:
323+
324+- 普通请求和 SSE 请求使用同一条正式代发链路
325+- SSE 不要求透传原始字节流,但要求稳定回传事件流语义
326+
327+## 职责划分结论
328+
329+### 应放在 `conductor`
330+
331+- 抖动策略
332+- 限流策略
333+- 并发控制
334+- 队列调度
335+- 失败退避
336+- 熔断恢复
337+- 跨浏览器、跨平台、跨账号协调
338+
339+### 应放在 Firefox 插件
340+
341+- 页面真实执行
342+- 页面就绪检查
343+- 本地超时
344+- 本地取消
345+- 最小安全发送间隔
346+- 连续失败后的短暂本地保护
347+
348+## 执行链路选择原则
349+
350+- `codexd`
351+  - 用于代码、文件系统、工作区相关任务
352+- browser bridge
353+  - 用于依赖真实网站登录态和浏览器页面环境的任务
354+- 首版不要求两条链路自动互相替代
355+- task 或 step 应显式声明执行后端,由 `conductor` 按声明选择链路
356+
357+## 一句话方案
358+
359+`conductor` 负责“怎么调度、怎么控风险、怎么选执行目标”,Firefox 插件负责“是否已就绪、如何在真实浏览器环境里把请求发出去并把 SSE 带回来”。
360+
361+## 对现有 describe 的改造判断
362+
363+- 这次优化重点是“重组现有 describe”,不是“新增第三层 describe”
364+- 如果只调整 `/describe`、`/describe/business`、`/describe/control` 的文案和返回结构,复杂度较低
365+- 真正复杂的部分不在 describe,而在后续正式浏览器管理接口和通用 SSE 接口实现
366+- 推荐顺序:
367+  1. 先收口 describe 分层
368+  2. 再逐步把新的浏览器管理能力挂进 `control`
369+  3. 再把新的浏览器代发和 SSE 能力挂进 `business`
A plans/discuss/DISCUSS-FIREFOX-BRIDGE-CONTROL.md
+211, -0
  1@@ -0,0 +1,211 @@
  2+# DISCUSS: FIREFOX_BRIDGE_CONTROL_REQUIREMENTS 核对与改进
  3+
  4+日期:2026-03-26
  5+来源:Claude 交叉审查 FIREFOX_BRIDGE_CONTROL_REQUIREMENTS.md + BROWSER_BRIDGE_PERSISTENCE_REQUIREMENTS.md + 现有代码 + handoff
  6+
  7+---
  8+
  9+## 1. 现有接口与需求文档的迁移缺口
 10+
 11+### 现状
 12+
 13+当前 `/describe/business` 里浏览器接口是 claude-specific 的:
 14+
 15+```
 16+/v1/browser                    # bridge 状态
 17+/v1/browser/claude/open        # 打开 Claude 标签页
 18+/v1/browser/claude/send        # 发消息(页面对话模式)
 19+/v1/browser/claude/current     # 当前对话
 20+/v1/browser/claude/reload      # 重载
 21+```
 22+
 23+### 问题
 24+
 25+需求文档定义了通用能力模型(`api_request`、`stream_open` 等,按平台和账号选择代发目标),但没有说明:
 26+
 27+- 现有 `/v1/browser/claude/*` 系列接口的**迁移路径**:是废弃重建还是渐进改造?
 28+- 过渡期是否需要两套接口并存?兼容性承诺是什么?
 29+- 新的通用接口 URL 结构是什么?例如 `POST /v1/browser/request` + body 里选平台/账号?还是 `POST /v1/browser/:platform/request`?
 30+
 31+### 建议
 32+
 33+在需求文档中增加「迁移策略」章节,明确:
 34+1. 新接口路径命名规范
 35+2. 旧接口废弃时间表(或标记为 legacy)
 36+3. 灰度切换方式
 37+
 38+---
 39+
 40+## 2. SSE 链路的断连补偿机制
 41+
 42+### 问题
 43+
 44+需求文档把 SSE 列为首批正式能力,但 SSE 回传链路很长:
 45+
 46+```
 47+conductor → WS → Firefox 插件 → 页面 fetch(SSE) → 拦截 → WS 回传 → conductor
 48+```
 49+
 50+每一跳都可能断,但文档只定义了事件类型(`stream_open/event/end/error`),没有定义:
 51+
 52+- **断连重传**:WS 断了再连上后,丢失的 SSE event 怎么办?需要 sequence number 吗?
 53+- **背压控制**:上游 SSE 速率 > WS 回传速率时怎么处理?缓冲?丢弃?
 54+- **超时判定**:stream_open 后多久没收到 event 算超时?和 stream_error 的区别?
 55+- **部分成功**:收到一半 SSE 后断了,已收到的数据如何交付给调用方?
 56+
 57+### 建议
 58+
 59+增加「SSE 可靠性设计」子章节,至少定义:
 60+- 每个 stream_event 带递增 seq
 61+- 断连后 conductor 向调用方发 stream_error + 已收到的 partial_events
 62+- 超时阈值可配置(建议默认 30s 无 event = timeout)
 63+
 64+---
 65+
 66+## 3. 空壳页(Shell Page)定义不清
 67+
 68+### 问题
 69+
 70+两份需求文档都提到「空壳标签页」,这是关键概念但缺乏定义:
 71+
 72+- 空壳页的 URL 是什么?需要在目标平台同域才能携带 cookie 发起 fetch
 73+- 如果用 `about:blank` 或自定义页面,cookie 不会自动附加
 74+- 如果用目标平台的某个轻量页面,上游 CSP/CORS 变更可能导致 fetch 失败
 75+- 空壳页 crash 或被用户手动关闭后的检测和恢复机制
 76+
 77+### 建议
 78+
 79+明确定义空壳页的实现方案,例如:
 80+- 打开目标平台的最小页面(如 claude.ai 的某个静态端点)
 81+- 插件通过 content_script 注入 fetch 执行环境
 82+- 定义 tab 健康检查周期(如每 30s 检测一次 tab 是否存活)
 83+
 84+---
 85+
 86+## 4. 调度策略参数缺失
 87+
 88+### 问题
 89+
 90+需求文档列出了调度与风控的能力清单(限流、抖动、退避、熔断),但没有定义任何参数:
 91+
 92+- 人类化抖动的高斯分布 μ 和 σ 范围?
 93+- 平台级限流的窗口和阈值?(例如 claude.ai 每分钟最多 N 次?)
 94+- 失败退避的公式?(指数退避?基数和上限?)
 95+- 熔断的触发条件?(连续 N 次失败?错误率超 X%?)
 96+- 熔断恢复的半开探测策略?
 97+
 98+### 建议
 99+
100+不需要在需求文档里定死数字,但应该定义:
101+1. 每个策略的**配置接口**(至少可以通过 conductor config 调整)
102+2. **默认值**(可以先用保守值:抖动 μ=2s σ=0.5s,限流 10req/min/platform,退避 base=1s max=60s)
103+3. 策略参数是否纳入 `/describe/control` 的可读可写范围
104+
105+---
106+
107+## 5. 多浏览器/多 client 是否过度设计
108+
109+### 现状
110+
111+当前只有一个 Firefox 实例(一个 client_id)。DB schema 设计了 `(platform, host, browser, client_id, account)` 五级键。
112+
113+### 问题
114+
115+- 五级键的调度逻辑复杂度高,但短期内不会有多浏览器场景
116+- 如果过度设计调度层,首版实现的复杂度会大幅上升,拖慢交付
117+
118+### 建议
119+
120+- 首版调度以 `client_id` 为唯一执行者标识,`host`/`browser` 作为元数据记录但不参与调度决策
121+- 在需求文档中标注哪些是「首版必须」vs「多 client 扩展预留」
122+- 多 client 调度作为独立需求文档,不混在首版里
123+
124+---
125+
126+## 6. tab 管理能力的状态同步问题
127+
128+### 问题
129+
130+需求文档定义了 `tab_open/focus/reload/restore` 四个管理能力,但缺少:
131+
132+- conductor 侧用什么标识一个 tab?`platform + shell_id`?
133+- 如果 Firefox 侧用户手动关了 tab,conductor 怎么得知?(插件需要监听 `tabs.onRemoved` 并主动上报)
134+- tab 状态在 conductor 侧是纯内存态还是也要持久化?
135+- `tab_restore` 和初始 `tab_open` 的区别是什么?(restore 是否暗示有「期望 tab 列表」的概念?)
136+
137+### 建议
138+
139+增加「Tab 状态模型」子章节:
140+- 定义 conductor 侧维护的 tab 期望状态(desired)和 Firefox 上报的实际状态(actual)
141+- 定义 actual ≠ desired 时的自动调和策略
142+- 明确 `tab_restore` = "重建所有 desired 中存在但 actual 中缺失的 tab"
143+
144+---
145+
146+## 7. codexd 链路与 browser 链路的关系
147+
148+### 问题
149+
150+handoff 文档里 codexd 和 browser 是并列的两条执行链路。本需求只定义 browser 链路,但没说明:
151+
152+- codexd(走 OpenAI 直连 API)和 browser(走 claude.ai 代发)在 task scheduler 里如何选择?
153+- 是否需要统一的「执行后端」抽象层?task step 定义 `executor: codexd | browser`?
154+- 如果两条链路都能完成同一件事,调度优先级是什么?
155+
156+### 建议
157+
158+在需求文档或 handoff 里增加一段「执行链路选择原则」,例如:
159+- codexd = 用于代码任务(有文件系统访问)
160+- browser/claude = 用于对话任务(无文件系统访问)
161+- 两者不互相替代,由 task 定义决定
162+
163+---
164+
165+## 8. 凭证指纹的生成规范
166+
167+### 问题
168+
169+持久化需求说存「凭证指纹」用于判断变更,DB 里有 `credential_fingerprint TEXT`,但没定义:
170+
171+- 指纹的输入是什么?(哪些 header 字段?cookie name?token 前缀?)
172+- 哈希算法是什么?(SHA-256?)
173+- 指纹在哪一侧生成?如果在插件侧生成,conductor 无法验证一致性
174+- 指纹变更是否触发 `status` 从 `fresh` 降级到 `stale`?
175+
176+### 建议
177+
178+在持久化需求文档中增加指纹规范:
179+- 输入 = 排序后的 `cookie names + auth header type + token prefix(8 chars)`
180+- 算法 = SHA-256
181+- 生成侧 = 插件(conductor 不接触原始值)
182+- 变更 = 触发 `captured_at` 更新,status 保持 `fresh`(指纹变了说明重新登录了,是好事)
183+
184+---
185+
186+## 9. 两份需求文档缺乏交叉引用
187+
188+### 问题
189+
190+`BROWSER_BRIDGE_PERSISTENCE_REQUIREMENTS.md` 和 `FIREFOX_BRIDGE_CONTROL_REQUIREMENTS.md` 有大量概念重叠(空壳页、凭证不持久化、账号发现等),但各自独立,没有引用关系。
191+
192+### 建议
193+
194+- 在两份文档开头加「关联文档」章节,互相引用
195+- 共享概念(如空壳页、凭证指纹、状态三态 fresh/stale/lost)抽到一份共享定义文档或 glossary
196+- 避免后续 codex 实现时两边对同一概念的理解不一致
197+
198+---
199+
200+## 总结:建议改进优先级
201+
202+| # | 问题 | 严重度 | 改动量 |
203+|---|---|---|---|
204+| 1 | 现有接口迁移路径缺失 | High | 在需求文档加一章 |
205+| 2 | SSE 断连补偿未定义 | High | 加子章节 |
206+| 3 | 空壳页定义不清 | High | 加定义 + 补到两份文档 |
207+| 4 | 调度参数缺失 | Medium | 加默认值和配置接口定义 |
208+| 5 | 多 client 过度设计风险 | Medium | 标注首版 vs 扩展 |
209+| 6 | tab 状态同步缺失 | Medium | 加状态模型章节 |
210+| 7 | codexd 与 browser 选择原则 | Medium | 加一段说明 |
211+| 8 | 凭证指纹规范缺失 | Low | 加到持久化文档 |
212+| 9 | 文档缺交叉引用 | Low | 加关联章节 |