baa-conductor

git clone 

commit
57a6bba
parent
3f5e0e4
author
codex@macbookpro
date
2026-03-30 14:15:06 +0800 CST
docs: align renewal discuss after code review
1 files changed,  +226, -0
M plans/discuss/DISCUSS-TIMED-JOBS-RENEWAL-REQUIREMENTS.md
+226, -0
  1@@ -324,3 +324,229 @@ function buildRenewalPayload(message: ArtifactMessage): string {
  2 5. 在 `ingestAssistantFinalMessage` 流程末尾挂钩:摄入成功 → shouldRenew → 写 renewal_jobs
  3 6. 加通道暂停/恢复 API 端点
  4 7. 端到端验证
  5+
  6+## 当前对齐结论 — 2026-03-30
  7+
  8+以下结论优先级高于上文中的早期草案,作为当前版本的讨论共识。
  9+
 10+### 1. 首版范围
 11+
 12+- 首版只做 API 代理路径
 13+- 不做 GUI 自动化
 14+- 不做操作系统辅助功能发送
 15+- 插件继续负责 SSE final-message 上报
 16+- `conductor` 负责消息落库、任务生成、任务分发、状态回写
 17+
 18+### 2. 定时任务模块
 19+
 20+定时任务模块继续作为独立后台模块存在,负责:
 21+
 22+1. 消息同步任务
 23+2. 续命任务
 24+3. 后续扩展的执行类任务
 25+
 26+它本质上仍然是系统内部的轻量消息队列和兜底执行层。
 27+
 28+### 3. 扫描周期与批量限制
 29+
 30+扫描周期需要做成可配置项,不追求高频。
 31+
 32+当前共识:
 33+
 34+- 默认扫描周期可以设在 `5-10 秒`
 35+- 周期再长一些也可以接受
 36+- 每轮只扫描小批量数据
 37+- 每轮消息同步最多处理约 `10` 条旧消息
 38+- 每轮续命分发最多处理约 `10` 个到期任务
 39+
 40+这里的“旧消息”和“到期任务”也要有明确约束:
 41+
 42+- 消息需要经过一个可配置的 settle delay,再参与同步
 43+- 任务只处理已到执行时间的记录
 44+
 45+周期、批量、settle delay 都应作为配置项。
 46+
 47+### 4. 本地对话模型
 48+
 49+在本地消息表之外,增加一张本地对话表,并再增加一张对话关联表。
 50+
 51+对话表负责:
 52+
 53+- 表达本地对话身份
 54+- 保存当前对话的自动化状态
 55+- 作为未来 `baa` 指令系统的统一控制锚点
 56+
 57+对话关联表负责:
 58+
 59+- 建立本地对话与平台对话的映射
 60+- 保存平台、client、页面、路由等关联信息
 61+- 支撑续命任务在执行时定位目标
 62+
 63+### 5. 对话自动化状态
 64+
 65+每个对话需要有一个自动化状态,当前先按三态理解:
 66+
 67+- `manual`
 68+- `auto`
 69+- `paused`
 70+
 71+语义是:
 72+
 73+- `manual`:该对话不自动续命
 74+- `auto`:该对话允许自动续命
 75+- `paused`:该对话自动化已暂停,可后续恢复
 76+
 77+这个状态需要同时支持两个入口:
 78+
 79+- 当前 Firefox 插件右下角控制面板
 80+- 后续 `baa` 指令系统
 81+
 82+插件面板只是第一阶段控制入口,后端保存的是统一状态。
 83+
 84+### 6. 续命规则
 85+
 86+当前共识是不采用“所有 final-message 一律续命”的策略,而是由对话状态决定是否生成续命任务。
 87+
 88+只有在满足下面条件时,final-message 才会被同步为续命任务:
 89+
 90+- 消息是 assistant final-message
 91+- 所属对话当前为 `auto`
 92+- 所属对话不是 `paused`
 93+- 通过冷却时间判断
 94+- 不是重复消息
 95+- 当前目标路由可用
 96+
 97+暂停语义也先收敛为:
 98+
 99+- `paused` 后不再生成新的续命任务
100+- 已经待执行但尚未发送的任务不再继续推进
101+- 已经进入执行中的任务可以自然结束
102+
103+### 7. 续命任务状态
104+
105+续命任务首版状态从之前的六态收敛为四态:
106+
107+- `pending`
108+- `running`
109+- `done`
110+- `failed`
111+
112+重试不再单独建状态,而是通过任务上的重试字段表达,例如:
113+
114+- 尝试次数
115+- 下次执行时间
116+- 最近错误
117+
118+如果未来需要“已发送但待确认”的中间态,再追加扩展。
119+
120+### 8. 续命任务表
121+
122+续命任务继续单独建模,但第一版不再扩太多表,只在续命任务表上增加必要列即可。
123+
124+这张表至少需要表达:
125+
126+- 来源消息
127+- 来源对话
128+- 当前状态
129+- 重试次数
130+- 下次执行时间
131+- 最近错误
132+- 目标快照
133+- 外部日志文件位置
134+
135+当前倾向是不额外拆出订阅表和 attempt 明细表,先用最小模型跑通。
136+
137+### 9. 外部日志
138+
139+定时任务模块需要将执行过程写入外部日志文件,这是正式需求,不是可选增强。
140+
141+数据库只保留摘要状态,完整执行细节进入外部日志。
142+
143+日志至少需要能表达:
144+
145+- 时间
146+- runner 类型
147+- tick 或批次标识
148+- 消息 ID / 对话 ID / 任务 ID
149+- 当前阶段
150+- 执行结果
151+- 耗时
152+- 错误信息
153+
154+第一版优先满足“可排障、可回看、可 tail”的目标。
155+
156+### 10. 当前最小对象集合
157+
158+当前讨论已经收敛到下面这组最小对象:
159+
160+- 本地消息表
161+- 本地对话表
162+- 对话关联表
163+- 续命任务表
164+- 外部日志目录
165+
166+首版先不做:
167+
168+- GUI / a11y 执行器
169+- 订阅表
170+- attempt 明细表
171+- 与现有 `tasks/runs` 的直接复用
172+
173+## 对 `main@3f5e0e4` 的逐条核对结论 — 2026-03-30
174+
175+下面这组结论,基于对当前代码和本地工作树的再次核对。
176+
177+### 可以直接采纳的部分
178+
179+- 可以复用 `artifact.db + SyncQueue + D1SyncWorker` 这套本地落盘和 D1 同步机制,不需要重造同步队列
180+- 可以复用现有消息去重机制,尤其是 `message_dedupe_key`
181+- 可以复用插件侧 final-message 拦截,不再把它当作前置工作
182+- 可以复用现有浏览器 API 代理发送能力
183+- 可以复用 `attempts + backoff + maxAttempts` 这一套重试思路
184+- 续命内部执行仍然建议设置单次超时,建议 20 秒左右
185+
186+### 只能部分采纳的部分
187+
188+- “续命任务表直接加到 artifact.db”这件事技术上可行,但它只解决持久化,不解决对话自动化状态和目标定位
189+- “续命任务去重以 message_dedupe_key 为锚点即可”首版可用,但不应当作长期唯一约束
190+- “摘要 + 公开链接基础字段已有”成立,但续命 payload 不应写死为单一模板,首版应保留模板化空间
191+- `renewal_jobs` 表必须存在,但 `3f5e0e4` 里的字段还不够,至少还缺 `next_attempt_at`、目标快照、外部日志路径,以及更稳定的对话锚点
192+- `D1SyncWorker` 可以提供重试骨架,但它不是完整的业务状态机;续命任务仍然需要自己的 `pending / running / done / failed` 语义
193+- 扫描周期可以参考现有 worker,但最终仍以“可配置、默认 5-10 秒、小批量扫描”为准
194+
195+### 当前不采纳的部分
196+
197+- 不采纳“只建 renewal_jobs,不建本地对话表和对话关联表”
198+- 不采纳“所有 final-message 一律续命”
199+- 不采纳“用 channel_key = platform|conversation_id 直接替代本地对话身份”
200+- 不采纳“把通道暂停只做成任务查询逻辑或 system_state 临时键”
201+- 不采纳“首版新建范围只收敛为三件事”
202+
203+### 需要修正的事实表述
204+
205+- `artifact.db` 与 `d1_sync_queue` 的接线机制在代码里是成立的,但这属于运行时能力,不应直接表述为当前工作树里已经存在稳定数据
206+- 当前仓库里的本地 [artifact.db](/Users/george/code/baa-conductor/state/artifact.db) 是空文件,因此“messages 31 条 / sync_queue pending 0”这类数字不能直接作为当前 checkout 的事实依据
207+- `messages.summary` 不是天然大部分为空;按现有 `ArtifactStore` 实现,未显式传入时会自动从 `raw_text` 截断生成摘要
208+
209+### 当前最终采纳清单
210+
211+当前正式采纳的方向是:
212+
213+- 复用现有 `artifact.db`、`SyncQueue`、`D1SyncWorker`
214+- 复用现有消息去重
215+- 复用现有插件 final-message 拦截
216+- 复用现有浏览器 API 代理发送
217+- 新建本地对话表
218+- 新建对话关联表
219+- 新建续命任务表
220+- 新增外部日志文件记录
221+- 以对话自动化状态 `manual / auto / paused` 作为续命生成规则核心
222+
223+### 当前最终不采纳清单
224+
225+当前明确不采纳的方向是:
226+
227+- 用 `platform|conversation_id` 直接替代本地对话身份
228+- 所有 final-message 自动生成续命任务
229+- 仅凭 `renewal_jobs` 一张表承载全部对话控制语义
230+- 把暂停/恢复能力寄存在临时推断逻辑中,而不是正式模型中