baa-conductor

git clone 

baa-conductor / tasks
codex@macbookpro  ·  2026-03-30

T-S059.md

  1# Task T-S059:续命执行任务与运维接口
  2
  3## 状态
  4
  5- 当前状态:`已完成`
  6- 规模预估:`M`
  7- 依赖任务:`T-S055`、`T-S056`、`T-S057`、`T-S058`
  8- 建议执行者:`Codex`
  9
 10## 直接给对话的提示词
 11
 12`/Users/george/code/baa-conductor/tasks/T-S059.md` 任务文档,完成开发任务。
 13
 14如需补背景,再读:
 15
 16- `/Users/george/code/baa-conductor/plans/discuss/DISCUSS-TIMED-JOBS-RENEWAL-REQUIREMENTS.md`
 17- `/Users/george/code/baa-conductor/tasks/T-S058.md`
 18
 19## 当前基线
 20
 21- 仓库:`/Users/george/code/baa-conductor`
 22- 分支基线:`main`
 23- 提交:`071abbf`
 24
 25## 分支与 worktree(强制)
 26
 27- 分支名:`feat/renewal-dispatcher-ops`
 28- worktree 路径:`/Users/george/code/baa-conductor-renewal-dispatcher-ops`
 29
 30开工步骤:
 31
 321. `cd /Users/george/code/baa-conductor`
 332. `git worktree add ../baa-conductor-renewal-dispatcher-ops -b feat/renewal-dispatcher-ops main`
 343. `cd ../baa-conductor-renewal-dispatcher-ops`
 354. 在这个 worktree 目录里开发,不要回到主仓库目录
 36
 37完成后提交与推送:
 38
 391. 在 worktree 里提交所有变更(包括更新后的任务文档)
 402. `git push -u origin feat/renewal-dispatcher-ops`
 41
 42合并步骤(由合并者执行):
 43
 441. `cd /Users/george/code/baa-conductor`
 452. `git fetch origin`
 463. `git merge origin/feat/renewal-dispatcher-ops`
 474. `git push`
 485. `git worktree remove ../baa-conductor-renewal-dispatcher-ops`(如果 worktree 还在)
 49
 50合并冲突处理:
 51
 521. 如果 `git merge` 报冲突,先 `git diff` 查看冲突文件
 532. 手动解决冲突后 `git add` 冲突文件
 543. `git merge --continue` 完成合并
 554. 不要用 `git merge --abort` 然后 force 覆盖
 56
 57命名规则:
 58
 59- 功能任务分支名以 `feat/` 开头
 60- 缺陷任务分支名以 `bug/` 开头
 61
 62## 目标
 63
 64实现“续命执行任务”:扫描待执行续命任务,通过浏览器 API 代理发送,并补齐最小运维读接口。
 65
 66## 背景
 67
 68在消息已经投影为 `renewal_jobs` 之后,还需要独立 dispatcher 完成:
 69
 70- 扫描到期任务
 71- 执行发送
 72- 更新状态
 73- 写外部日志
 74- 提供最小可排障的读接口
 75
 76## 涉及仓库
 77
 78- `/Users/george/code/baa-conductor`
 79
 80## 范围
 81
 82- 实现 dispatcher runner
 83- 调用现有浏览器 API 代理发送
 84- 实现超时、重试、退避和最终失败
 85- 提供最小查询接口查看对话和续命任务状态
 86
 87## 路径约束
 88
 89- 首版只走 API 代理,不做 GUI / a11y
 90- 不直接复用现有 `tasks/runs`
 91- 仍然通过 timed-jobs 框架运行
 92
 93## 推荐实现边界
 94
 95建议优先做:
 96
 97- `apps/conductor-daemon/src/timed-jobs/`
 98- `apps/conductor-daemon/src/renewal/`
 99- `apps/conductor-daemon/src/local-api.ts`
100
101## 允许修改的目录
102
103- `/Users/george/code/baa-conductor/apps/conductor-daemon/src/timed-jobs/`
104- `/Users/george/code/baa-conductor/apps/conductor-daemon/src/renewal/`
105- `/Users/george/code/baa-conductor/apps/conductor-daemon/src/local-api.ts`
106- `/Users/george/code/baa-conductor/apps/conductor-daemon/src/index.ts`
107- `/Users/george/code/baa-conductor/packages/artifact-db/`
108
109## 尽量不要修改
110
111- `/Users/george/code/baa-conductor/plugins/`
112- `/Users/george/code/baa-conductor/packages/d1-client/`
113
114## 必须完成
115
116### 1. dispatcher
117
118- 扫描 `next_attempt_at <= now` 的到期任务
119- 每轮最多处理约 `10` 个任务
120- 调现有浏览器 API 代理发送
121- 成功推进到 `done`
122
123### 2. 超时与重试
124
125- 单次执行有内部超时
126- 失败后更新 `attempt_count`
127- 失败后写 `next_attempt_at`
128- 超过限制后进入 `failed`
129
130### 3. 运维接口与日志
131
132- 提供最小续命任务查询接口
133- 提供最小对话自动化状态查询接口
134- dispatcher 全流程写外部日志
135
136## 需要特别注意
137
138- `paused` 对话不应继续推进待执行任务
139- 执行中的任务允许自然结束,不要求强制中断
140- 发送接口应尽量复用现有内部 service,不要通过 HTTP 自己调自己
141- 所有开发必须在 worktree 中进行,不要在主仓库目录修改代码
142
143## 验收标准
144
145- `pending` 任务可以被 dispatcher 扫到并发送
146- 成功任务进入 `done`
147- 失败任务能重试并最终进入 `failed`
148- dispatcher 执行过程会写外部日志
149- 可以通过本地 API 读取任务和对话状态
150
151## 推荐验证命令
152
153- `cd /Users/george/code/baa-conductor-renewal-dispatcher-ops && pnpm build`
154- `cd /Users/george/code/baa-conductor-renewal-dispatcher-ops && pnpm -C apps/conductor-daemon test`
155
156## 执行记录
157
158> 以下内容由执行任务的 AI 填写,创建任务时留空。
159
160### 开始执行
161
162- 执行者:`Codex`
163- 开始时间:`2026-03-30 16:34:10 CST`
164- 状态变更:`待开始` → `进行中`
165
166### 完成摘要
167
168- 完成时间:`2026-03-30 16:57:56 CST`
169- 状态变更:`进行中` → `已完成`
170- 修改了哪些文件:
171  - `apps/conductor-daemon/src/renewal/dispatcher.ts`
172  - `apps/conductor-daemon/src/renewal/projector.ts`
173  - `apps/conductor-daemon/src/local-api.ts`
174  - `apps/conductor-daemon/src/index.ts`
175  - `apps/conductor-daemon/src/index.test.js`
176  - `docs/api/business-interfaces.md`
177  - `docs/api/control-interfaces.md`
178  - `tasks/T-S059.md`
179- 核心实现思路:
180  - 新增 `renewal.dispatcher` timed-job runner,扫描 `next_attempt_at <= now``pending` job,执行前重新读取对话自动化状态和 active link,只通过 `browser.proxy_delivery` 发送续命消息
181  - 为 dispatcher 补齐单次执行超时、失败重试、指数退避、最终失败和 `paused/manual` 对话延后重查逻辑,并把完整阶段写入 timed-jobs JSONL 外部日志
182  -`/v1/renewal/` 下补充 `jobs` 列表/详情读接口,保留现有 `conversations` / `links` 作为最小排障读面,同时把 renewal 读写接口写入 API 文档
183  - 顺手收紧 projector 的 route 可用性判断,只为具备真实 `browser.proxy_delivery` tab 目标的对话生成续命任务
184- 跑了哪些测试:
185  - `cd /Users/george/code/baa-conductor-renewal-dispatcher-ops && pnpm install`
186  - `cd /Users/george/code/baa-conductor-renewal-dispatcher-ops && pnpm -C apps/conductor-daemon test`
187  - `cd /Users/george/code/baa-conductor-renewal-dispatcher-ops && pnpm build`
188
189### 执行过程中遇到的问题
190
191- 新 worktree 初始没有安装依赖,第一次 `pnpm -C apps/conductor-daemon test` 失败于 `pnpm exec tsc` 找不到;补跑一次 `pnpm install` 后恢复正常构建和测试流程
192
193### 剩余风险
194
195- 当前 dispatcher 只处理 `pending -> running -> done/failed` 的首版闭环,还没有做“进程意外退出后回收陈旧 running 任务”的恢复逻辑;如果后续需要跨重启补偿,需要再补 stale-running reconcile