baa-conductor

git clone 

im_wower  ·  2026-03-26

DESIGN.md

  1# BAA Conductor 实施设计说明
  2
  3## 1. 当前目标
  4
  5`baa-conductor` 当前只维护一条最小可运行路径:
  6
  7- `mini` 是唯一长期运行节点
  8- `mini` 本地接口 `http://100.71.210.78:4317` 是唯一主接口
  9- `https://conductor.makefile.so` 是唯一 canonical 公网入口,并回源到同一个 `mini` 接口
 10- `control-api.makefile.so`、Cloudflare Worker、D1 只作为迁移期兼容件保留
 11- `baa-hand` / `baa-shell` 只保留为接口语义参考,不再继续维护为主系统
 12
 13历史的主备切换、failover、switchback、多节点公网入口已经从当前主线删除。需要回看旧设计时,使用 tag `ha-failover-archive-2026-03-22` 14
 15## 2. Canonical 拓扑
 16
 17### 主控制面
 18
 19- node: `mini`
 20- Tailscale IP: `100.71.210.78`
 21- canonical local base: `http://100.71.210.78:4317`
 22- 当前 conductor 已暴露:
 23  - `/describe`
 24  - `/health`
 25  - `/version`
 26  - `/healthz`
 27  - `/readyz`
 28  - `/rolez`
 29  - `/v1/runtime`
 30  - `/v1/capabilities`
 31  - `/v1/system/state`
 32  - `/v1/controllers`
 33  - `/v1/tasks`
 34  - `/v1/runs`
 35  - `pause / resume / drain`
 36  - `/v1/exec`
 37  - `/v1/files/read`
 38  - `/v1/files/write`
 39  - `/v1/browser/*`
 40  - `/v1/codex*`(配置了 `codexd` 时)
 41
 42后续如还要扩展,默认继续往这同一个接口面收口,不再回到 legacy control plane。
 43
 44### 公网入口
 45
 46- `https://conductor.makefile.so`
 47- VPS Nginx 反向代理到 `100.71.210.78:4317`
 48- 所有新的公网文档和调用方都应收口到这个域名
 49
 50### 迁移期兼容面
 51
 52- `https://control-api.makefile.so`
 53- Cloudflare Worker + D1
 54- 只为尚未 cutover 到 `4317` 的旧调用方兜底
 55- 不再作为默认控制面,不接受新的主路径依赖
 56
 57### 本地只读观察面
 58
 59- 推荐入口已经收口到 `conductor``http://100.71.210.78:4317/v1/status``/v1/status/ui`
 60- `http://100.71.210.78:4318` 仍由 `apps/status-api` 提供兼容包装层
 61- 只用于本地调试、过渡观察和 legacy 路径兼容,不再作为默认对外业务接口
 62
 63### 浏览器控制面
 64
 65- Firefox 插件代码位于 [`plugins/baa-firefox`](./plugins/baa-firefox)
 66- 浏览器默认目标也应收口到 `conductor.makefile.so`
 67- 在 cutover 完成前,如仍需依赖 legacy control plane,需要在任务卡里明确记录
 68
 69## 3. 组件职责
 70
 71### `apps/conductor-daemon`
 72
 73- `mini` 本地常驻进程
 74- 负责 heartbeat、租约续约、最小调度循环和 runtime 探针
 75- 是后续统一 discovery / control / status-view / task / run 接口的目标承载面
 76
 77### legacy `control-api` surface(已移出当前仓库)
 78
 79- `control-api.makefile.so`、Cloudflare Worker、D1 仍可能在线上或旧文档中出现
 80- 但它们已经不再是当前仓库中的实现组件
 81- 当前只把它们当作删旧阶段需要盘点的历史兼容面
 82
 83### `apps/status-api`
 84
 85- `mini` 本地状态兼容包装层
 86- 默认读取 `BAA_CONDUCTOR_LOCAL_API` 对应的 conductor `/v1/system/state`
 87- `BAA_CONTROL_API_BASE` 只剩手工兼容回退语义
 88- 继续保留 `/describe`、`/v1/status`、`/v1/status/ui`、`/ui` 等 legacy 本地观察合同,不是主控制面
 89
 90### `codexd`(已实现独立 daemon,仍在继续收口)
 91
 92- `mini` 本地常驻的独立 Codex 代理/执行组件
 93- 不是 TUI,不要求人工盯界面
 94- 负责把 Codex 作为双工工作组件来使用:
 95  - 执行 worker step
 96  - 完成异步任务
 97  - 参与 AI 对话
 98  - 持续记录日志
 99- 公开接口结论已经明确:
100  - 主接口:`codex app-server`
101  - 不实现 `codex exec` 式无交互正式模式
102  - `conductor-daemon` 对外只保留 `/v1/codex`、`/v1/codex/sessions`、`/v1/codex/sessions/:session_id`、`POST /v1/codex/sessions`、`POST /v1/codex/turn`
103  - 不驱动 TUI
104- 负责 Codex 特有的会话、子进程、重试、超时和恢复语义
105- 必须作为独立进程运行,不接受长期内嵌在 `conductor-daemon` 里的方案
106
107和现有组件的边界:
108
109- `conductor-daemon`:系统真相源、编排器、HTTP/WS 主接口
110- `worker-runner`:通用 step 执行与落盘框架
111- `codexd`:Codex 专用执行代理,负责把 Codex 从“手工 TUI”变成“可被本地系统调用的长期能力”
112
113当前状态:
114
115- 仓库里已经有 `codex` step kind、planner 和 step template 抽象
116- `apps/codexd` 已有独立 daemon、本地 HTTP 面、event stream、session / turn 状态与最近事件缓存
117- `conductor-daemon` 已能通过本地 `/v1/codex*` 代理到 `codexd`
118- transport 尾包冲刷和“未收到合法 completed 就提前断流”的 failure classification 已落地
119-`codexd` 仍不是已上线、已承诺稳定性的组件
120- 正式产品口径只保留 session / turn / status,不把 `runs` / `exec` 当作 Codex 能力面
121- 后续实现时,不再把 `exec` 当作主双工方案,也不再把它做成正式接口
122- 原因:`codex exec` 卡顿明显且容易假死,不符合 `codexd` 的常驻双工目标
123- 后续实现时,`conductor-daemon` 只能通过本地接口调用 `codexd`,不能自己长期维护一套并行 bridge
124
125### `apps/worker-runner`
126
127- 本地 step 执行器
128- 负责本地目录、日志、checkpoint 落盘
129
130## 4. 部署约束
131
132- 只保留 `mini` 单节点
133- 不依赖 MagicDNS
134- 内网地址统一写 `100.71.210.78:4317`
135- 外网默认只暴露 `conductor.makefile.so`
136- Cloudflare Worker / D1 不再被描述为默认控制面
137
138## 5. Runtime 目录
139
140默认仓库路径建议:
141
142- `/Users/george/code/baa-conductor`
143
144默认 runtime 目录:
145
146- `state/`
147- `runs/`
148- `worktrees/`
149- `logs/`
150- `tmp/`
151
152这些目录由 [`scripts/runtime/bootstrap.sh`](./scripts/runtime/bootstrap.sh) 初始化。
153
154## 6. 自启动
155
156当前只维护 `mini` 的 launchd 安装:
157
158- 必选 `so.makefile.baa-conductor`
159- 迁移期可选 `so.makefile.baa-status-api`
160- 可选 `so.makefile.baa-worker-runner`
161
162脚本:
163
164- [`scripts/runtime/install-launchd.sh`](./scripts/runtime/install-launchd.sh)
165- [`scripts/runtime/check-launchd.sh`](./scripts/runtime/check-launchd.sh)
166- [`scripts/runtime/check-node.sh`](./scripts/runtime/check-node.sh)
167- [`scripts/runtime/reload-launchd.sh`](./scripts/runtime/reload-launchd.sh)
168
169说明:
170
171- 当前脚本仍保留 legacy 参数名 `--control-api-base` / `BAA_CONTROL_API_BASE`
172- 这套名字现在只影响 `conductor` 自己的 upstream/public API base,不再用于 `status-api`
173- 这不是 canonical 主路径,只是删旧前尚未改名的过渡残留
174
175## 7. Nginx 与 DNS
176
177当前只维护一个公网入口:
178
179- `conductor.makefile.so`
180
181回源关系:
182
183- `conductor.makefile.so` -> VPS Nginx -> `100.71.210.78:4317`
184
185相关文件:
186
187- [`ops/nginx/baa-conductor.conf`](./ops/nginx/baa-conductor.conf)
188- [`scripts/ops/baa-conductor.env.example`](./scripts/ops/baa-conductor.env.example)
189- [`scripts/ops/cloudflare-dns-plan.mjs`](./scripts/ops/cloudflare-dns-plan.mjs)
190- [`scripts/ops/nginx-sync-plan.mjs`](./scripts/ops/nginx-sync-plan.mjs)
191
192## 8. 迁移顺序
193
1941. 把 discovery、只读查询和控制动作并到 `4317` 这一个接口面。
1952.`conductor.makefile.so` 对公网暴露和 `4317` 同一套 canonical 路由。
1963. 重定向浏览器、CLI、AI 和运维文档,不再把 `control-api.makefile.so` 写成主路径。
1974.`status-api` 退回本地辅助观察,或直接并入 `conductor-daemon`1985. 删除 `apps/control-api-worker`、Cloudflare Worker / D1、旧域名和 hand/shell 主系统口径。
199
200## 9. 删旧范围
201
202完成 local-api cutover 后,优先删除或归档:
203
204- `control-api.makefile.so` 的 DNS / 部署 / 文档主路径角色
205- Cloudflare Worker / D1 作为默认控制面的说明
206- `status-api` 的公网职责
207- `baa-hand` / `baa-shell` 作为业务主系统的表述
208- 运行脚本与 launchd 模板中对 `BAA_CONTROL_API_BASE` 的默认依赖
209
210## 10. 当前真正关心的事情
211
212- `mini` 本地服务可持续启动
213- `conductor.makefile.so -> 100.71.210.78:4317` 可持续对外提供入口
214- 浏览器插件和后续调用方默认走新的 canonical host
215- legacy control plane 依赖被逐步盘点并删除
216- 为后续 `codexd` 预留清晰边界:`conductor` 管真相,`codexd` 管 Codex 会话和执行
217- `launchd` 负责自启动和硬重启,`conductor-daemon` 与 `codexd` 负责健康感知、重连和降级
218
219## 11. 当前已知残留
220
221- `conductor-daemon` 和 runtime 脚本已经有 canonical 名字 `BAA_CONDUCTOR_PUBLIC_API_BASE` / `--public-api-base`,但仍保留 legacy 别名 `BAA_CONTROL_API_BASE` / `--control-api-base`
222- `conductor-daemon` 已承接 `/v1/status``/v1/status/ui`;`status-api` 退到显式 opt-in 的本地兼容包装层
223- 根验证入口已经落到 `pnpm lint` / `pnpm test` / `pnpm smoke`,on-node `mini` 检查也已收口到 `pnpm verify:mini`
224- runtime 默认服务集合已经收口到 `conductor` + `codexd`;`status-api` 改成显式 opt-in 观察服务
225- `conductor-daemon` 当前仍通过 `status-api` 构建产物复用 snapshot/render 逻辑;删除 `status-api` 前需要先提共享模块
226- `conductor.makefile.so` 目前只回源 `conductor-daemon` 已有路由,尚未承接完整业务 API
227- 线上和历史文档里仍可能残留 `control-api.makefile.so`、Cloudflare / D1 相关资产或表述
228- 如果后续再次出现 app-server 未发出合法 `turn/completed` 就提前断流,应视为新的 child / transport 故障,而不是 reopen 已修复的 BUG-008 / BUG-010
229
230## 12. 历史回溯
231
232需要查看旧的主备设计、切换脚本和历史文档时:
233
234- git tag: `ha-failover-archive-2026-03-22`
235
236当前主线不再保留这些内容。