baa-conductor

git clone 

commit
9b1a54c
parent
e267385
author
im_wower
date
2026-03-22 17:22:10 +0800 CST
docs: unify local api cutover guidance
13 files changed,  +484, -332
M DESIGN.md
+87, -54
  1@@ -2,72 +2,86 @@
  2 
  3 ## 1. 当前目标
  4 
  5-`baa-conductor` 现在只维护一条最小可运行路径:
  6+`baa-conductor` 当前只维护一条最小可运行路径:
  7 
  8 - `mini` 是唯一长期运行节点
  9-- `mini` 负责 conductor、status-api、自启动与本地日志
 10-- `control-api.makefile.so` 负责 Cloudflare Worker + D1 控制面
 11-- `conductor.makefile.so` 作为公网入口,经 VPS Nginx 回源到 `mini`
 12-- 浏览器控制面来自 [`plugins/baa-firefox`](./plugins/baa-firefox)
 13+- `mini` 本地接口 `http://100.71.210.78:4317` 是唯一主接口
 14+- `https://conductor.makefile.so` 是唯一 canonical 公网入口,并回源到同一个 `mini` 接口
 15+- `control-api.makefile.so`、Cloudflare Worker、D1 只作为迁移期兼容件保留
 16+- `baa-hand` / `baa-shell` 只保留为接口语义参考,不再继续维护为主系统
 17 
 18 历史的主备切换、failover、switchback、多节点公网入口已经从当前主线删除。需要回看旧设计时,使用 tag `ha-failover-archive-2026-03-22`。
 19 
 20-## 2. 当前拓扑
 21+## 2. Canonical 拓扑
 22 
 23-### 控制面
 24+### 主控制面
 25 
 26-- `control-api.makefile.so`
 27-- Cloudflare Worker
 28-- D1 作为控制平面数据库
 29-
 30-控制面承担:
 31-
 32-- 系统模式读写
 33-- controller heartbeat
 34-- 任务、step、run 的元数据存储
 35-- 浏览器面板和 CLI 的统一接口
 36+- node: `mini`
 37+- Tailscale IP: `100.71.210.78`
 38+- canonical local base: `http://100.71.210.78:4317`
 39+- 当前 conductor 已暴露:
 40+  - `/healthz`
 41+  - `/readyz`
 42+  - `/rolez`
 43+  - `/v1/runtime`
 44 
 45-### 执行面
 46+后续要继续并到同一接口面的能力:
 47 
 48-- `mini`
 49-- Tailscale IP: `100.71.210.78`
 50-- 本地 conductor: `http://100.71.210.78:4317`
 51-- 本地 status-api: `http://100.71.210.78:4318`
 52+- `/describe`
 53+- `/version`
 54+- `/health`
 55+- `/v1/capabilities`
 56+- `/v1/system/state`
 57+- `/v1/controllers`
 58+- `/v1/tasks`
 59+- `/v1/runs`
 60+- `pause / resume / drain`
 61+- 来自 `baa-shell` 语义的小型本机能力
 62 
 63 ### 公网入口
 64 
 65 - `https://conductor.makefile.so`
 66 - VPS Nginx 反向代理到 `100.71.210.78:4317`
 67+- 所有新的公网文档和调用方都应收口到这个域名
 68+
 69+### 迁移期兼容面
 70+
 71+- `https://control-api.makefile.so`
 72+- Cloudflare Worker + D1
 73+- 只为尚未 cutover 到 `4317` 的旧调用方兜底
 74+- 不再作为默认控制面,不接受新的主路径依赖
 75+
 76+### 本地只读观察面
 77+
 78+- `http://100.71.210.78:4318`
 79+- 由 `apps/status-api` 提供
 80+- 只用于本地调试和过渡观察,不再作为默认对外业务接口
 81 
 82 ### 浏览器控制面
 83 
 84 - Firefox 插件代码位于 [`plugins/baa-firefox`](./plugins/baa-firefox)
 85-- 浏览器通过 `control-api` 读取系统状态
 86-- 浏览器通过 `pause / resume / drain` 接口控制自动化
 87+- 浏览器默认目标也应收口到 `conductor.makefile.so`
 88+- 在 cutover 完成前,如仍需依赖 legacy control plane,需要在任务卡里明确记录
 89 
 90 ## 3. 组件职责
 91 
 92-### `apps/control-api-worker`
 93-
 94-- Cloudflare Worker 入口
 95-- 负责 D1 读写
 96-- 对浏览器、CLI 和 conductor 暴露统一 HTTP API
 97-
 98 ### `apps/conductor-daemon`
 99 
100 - `mini` 本地常驻进程
101-- 负责 heartbeat、租约续约、最小调度循环和只读探针
102-- 对外暴露:
103-  - `/healthz`
104-  - `/readyz`
105-  - `/rolez`
106-  - `/v1/runtime`
107+- 负责 heartbeat、租约续约、最小调度循环和 runtime 探针
108+- 是后续统一 discovery / control / task / run 接口的目标承载面
109+
110+### `apps/control-api-worker`
111+
112+- Cloudflare Worker 入口
113+- 当前仍负责一部分 legacy control-plane HTTP 能力
114+- 只作为 cutover 兼容层保留,完成迁移后进入删旧范围
115 
116 ### `apps/status-api`
117 
118 - `mini` 本地状态读取面
119-- 面向浏览器或人类查看
120-- 默认监听本地或显式指定的 `100.x`
121+- 当前仍依赖 `BAA_CONTROL_API_BASE`
122+- 定位是迁移期本地只读观察服务,不是主控制面
123 
124 ### `apps/worker-runner`
125 
126@@ -78,9 +92,9 @@
127 
128 - 只保留 `mini` 单节点
129 - 不依赖 MagicDNS
130-- 内网地址直接写 Tailscale `100.x`
131-- 外网只暴露 `control-api.makefile.so` 与 `conductor.makefile.so`
132-- 当前不要求 Cloudflare proxy;DNS-only 也可接受
133+- 内网地址统一写 `100.71.210.78:4317`
134+- 外网默认只暴露 `conductor.makefile.so`
135+- Cloudflare Worker / D1 不再被描述为默认控制面
136 
137 ## 5. Runtime 目录
138 
139@@ -102,8 +116,8 @@
140 
141 当前只维护 `mini` 的 launchd 安装:
142 
143-- `so.makefile.baa-conductor`
144-- 可选 `so.makefile.baa-status-api`
145+- 必选 `so.makefile.baa-conductor`
146+- 迁移期可选 `so.makefile.baa-status-api`
147 - 可选 `so.makefile.baa-worker-runner`
148 
149 脚本:
150@@ -113,6 +127,11 @@
151 - [`scripts/runtime/check-node.sh`](./scripts/runtime/check-node.sh)
152 - [`scripts/runtime/reload-launchd.sh`](./scripts/runtime/reload-launchd.sh)
153 
154+说明:
155+
156+- 当前脚本仍保留 `BAA_CONTROL_API_BASE` 参数以兼容 `status-api`
157+- 这不是 canonical 主路径,只是删旧前的过渡残留
158+
159 ## 7. Nginx 与 DNS
160 
161 当前只维护一个公网入口:
162@@ -130,24 +149,38 @@
163 - [`scripts/ops/cloudflare-dns-plan.mjs`](./scripts/ops/cloudflare-dns-plan.mjs)
164 - [`scripts/ops/nginx-sync-plan.mjs`](./scripts/ops/nginx-sync-plan.mjs)
165 
166-## 8. 保留的内部复杂度
167+## 8. 迁移顺序
168 
169-当前主线仍保留一部分内部 `leader` / `lease` 语义,因为:
170+1. 把 discovery、只读查询和控制动作并到 `4317` 这一个接口面。
171+2. 让 `conductor.makefile.so` 对公网暴露和 `4317` 同一套 canonical 路由。
172+3. 重定向浏览器、CLI、AI 和运维文档,不再把 `control-api.makefile.so` 写成主路径。
173+4. 让 `status-api` 退回本地辅助观察,或直接并入 `conductor-daemon`。
174+5. 删除 `apps/control-api-worker`、Cloudflare Worker / D1、旧域名和 hand/shell 主系统口径。
175 
176-- control plane 已经围绕该模型实现
177-- 单节点下它仍能正常工作
178-- 现在不值得为替代项目到来前再做一次大规模重构
179+## 9. 删旧范围
180 
181-但这些内部语义不再代表“主备切换能力是当前目标”。
182+完成 local-api cutover 后,优先删除或归档:
183 
184-## 9. 当前真正关心的事情
185+- `control-api.makefile.so` 的 DNS / 部署 / 文档主路径角色
186+- Cloudflare Worker / D1 作为默认控制面的说明
187+- `status-api` 的公网职责
188+- `baa-hand` / `baa-shell` 作为业务主系统的表述
189+- 运行脚本与 launchd 模板中对 `BAA_CONTROL_API_BASE` 的默认依赖
190+
191+## 10. 当前真正关心的事情
192 
193 - `mini` 本地服务可持续启动
194-- `control-api` 与 `conductor` 对外可达
195-- 浏览器插件可以控制系统模式
196-- `status-api` 的真相来源逐步收口
197+- `conductor.makefile.so -> 100.71.210.78:4317` 可持续对外提供入口
198+- 浏览器插件和后续调用方默认走新的 canonical host
199+- legacy control plane 依赖被逐步盘点并删除
200+
201+## 11. 当前已知残留
202+
203+- `status-api` 仍通过 `BAA_CONTROL_API_BASE` 读取 legacy truth source
204+- `conductor.makefile.so` 目前只回源 `conductor-daemon` 已有路由,尚未承接完整业务 API
205+- 仓库中仍保留 `apps/control-api-worker`、Cloudflare / D1 相关脚手架
206 
207-## 10. 历史回溯
208+## 12. 历史回溯
209 
210 需要查看旧的主备设计、切换脚本和历史文档时:
211 
M README.md
+31, -36
  1@@ -1,23 +1,23 @@
  2 # baa-conductor
  3 
  4-`baa-conductor` 现在是一个收口后的单节点执行控制仓库。
  5+`baa-conductor` 当前主线只为一件事服务:把 `mini` 本地接口收口成唯一主接口,并把对外入口统一到 `conductor.makefile.so`。
  6 
  7-当前目标只有一个:
  8+当前主线口径:
  9 
 10-- `mini` 作为唯一中控长期运行
 11-- `mini` 负责自启动、控制面、状态面和浏览器插件配合
 12-- 对外公网入口保留 `control-api.makefile.so` 与 `conductor.makefile.so`
 13-- 内网回源固定走 `mini` 的 Tailscale `100.x`
 14+- canonical local API: `http://100.71.210.78:4317`
 15+- canonical public host: `https://conductor.makefile.so`
 16+- `control-api.makefile.so`、Cloudflare Worker、D1 只算迁移期兼容件,不再作为默认控制面
 17+- `baa-hand` / `baa-shell` 只保留为接口参考,不再继续维护为主系统
 18 
 19 主备切换、failover、switchback 和其它历史方案已经从当前主线移除;如需回溯,直接查看 tag `ha-failover-archive-2026-03-22`。
 20 
 21 ## 先读什么
 22 
 23 1. [`DESIGN.md`](./DESIGN.md)
 24-2. [`coordination/TASK_OVERVIEW.md`](./coordination/TASK_OVERVIEW.md)
 25+2. [`docs/api/README.md`](./docs/api/README.md)
 26 3. [`docs/runtime/README.md`](./docs/runtime/README.md)
 27 4. [`docs/ops/README.md`](./docs/ops/README.md)
 28-5. [`docs/api/README.md`](./docs/api/README.md)
 29+5. [`coordination/TASK_OVERVIEW.md`](./coordination/TASK_OVERVIEW.md)
 30 
 31 ## 当前目录结构
 32 
 33@@ -50,6 +50,7 @@ coordination/
 34   TASK_OVERVIEW.md
 35   WORKFLOW.md
 36 docs/
 37+  api/
 38   auth/
 39   decisions/
 40   firefox/
 41@@ -59,45 +60,39 @@ docs/
 42 
 43 ## 当前约定
 44 
 45-- 当前只维护 `mini` 单节点运行路径
 46+- 所有新接口设计默认先落 `mini` 本地 `4317`
 47+- 所有新公网说明统一写 `conductor.makefile.so`
 48+- `status-api` 只作为本地只读观察面,不再作为默认对外业务接口
 49+- `apps/control-api-worker` 只承担迁移期兼容职责,不再扩成主路径
 50 - 运行中的浏览器插件代码以 [`plugins/baa-firefox`](./plugins/baa-firefox) 为准
 51-- 历史主备资料不再在主线保留,靠 tag 回溯
 52-- 当前仓库优先做运维、修补和最小必要的控制面维护
 53 
 54-## HTTP 入口
 55+## Canonical 入口
 56 
 57-当前公开 HTTP 入口只有两类:
 58-
 59-| 入口 | 地址 | 职责 | 首个请求 |
 60+| 面 | 地址 | 定位 | 说明 |
 61 | --- | --- | --- | --- |
 62-| control-api | `https://control-api.makefile.so` | AI / 浏览器 / 运维的控制面与只读查询面 | `GET /describe` |
 63-| status-api | `https://conductor.makefile.so` | 只读状态视图与 HTML 状态页 | `GET /describe` |
 64-
 65-推荐工作流:
 66+| local API | `http://100.71.210.78:4317` | 唯一主接口、内网真相源 | 当前已提供 `healthz` / `readyz` / `rolez` / `v1/runtime`,后续业务接口继续并到这里 |
 67+| public host | `https://conductor.makefile.so` | 唯一公网域名 | 由 VPS Nginx 回源到 `100.71.210.78:4317` |
 68+| local status view | `http://100.71.210.78:4318` | 本地只读观察面 | 迁移期保留,不是主控制面 |
 69 
 70-1. 先请求 `GET /describe`
 71-2. 再看 `endpoints` / `capabilities` / `examples`
 72-3. 先用只读接口,再决定是否调用写接口
 73+legacy 兼容说明:
 74 
 75-control-api 当前新增的可发现性与只读接口包括:
 76+- `https://control-api.makefile.so` 只用于迁移期间兜底和识别残留依赖
 77+- Cloudflare Worker / D1 以及 `apps/control-api-worker` 在 cutover 完成后进入删旧范围
 78 
 79-- `GET /describe`
 80-- `GET /version`
 81-- `GET /health`
 82-- `GET /v1/capabilities`
 83-- `GET /v1/controllers`
 84-- `GET /v1/tasks`
 85-- `GET /v1/runs`
 86+## 迁移顺序
 87 
 88-更完整的接口说明和 curl 示例见 [`docs/api/README.md`](./docs/api/README.md)。
 89+1. 把 `/describe`、能力发现、状态/任务/运行查询与控制动作并到 `mini` 本地 API,并保持 `conductor.makefile.so` 同步暴露。
 90+2. 让浏览器、CLI、AI、运维文档全部默认走 `conductor.makefile.so` / `100.71.210.78:4317`。
 91+3. 让 `status-api` 退回本地辅助视图,或并入 `conductor` 主接口。
 92+4. 删除 `control-api.makefile.so`、Cloudflare Worker、D1 和 hand/shell 的主系统角色。
 93 
 94 ## 当前最重要的事
 95 
 96 - 保持 `mini` launchd、自启动和本地探针稳定
 97-- 保持 `control-api.makefile.so` 与 `conductor.makefile.so` 可用
 98-- 继续收口 `status-api` 的真实状态来源
 99+- 保持 `conductor.makefile.so -> 100.71.210.78:4317` 的链路稳定
100+- 推进 local-api cutover,清掉 legacy control plane 依赖
101 
102-## 当前已知问题
103+## 当前已知 gap
104 
105-- live `status-api` 仍可能和 control plane 真相漂移
106-- runtime 目录和部署路径还需要继续 canonicalize
107+- `status-api`、launchd 模板和部分运行脚本仍引用 `BAA_CONTROL_API_BASE`
108+- `conductor.makefile.so` 当前只直通 `4317` 的既有接口,业务 API 还需要后续任务并入口
M coordination/STATUS_SUMMARY.md
+10, -9
 1@@ -7,27 +7,28 @@
 2 ## 当前状态
 3 
 4 - 部署目标:`mini` 单节点
 5-- 当前没有活动开发任务
 6+- canonical 主接口:`http://100.71.210.78:4317`
 7+- canonical 公网入口:`https://conductor.makefile.so`
 8 - 历史主备资料已从主线移除
 9 - 回溯 tag:`ha-failover-archive-2026-03-22`
10 
11 ## 当前在线面
12 
13-- `https://control-api.makefile.so`
14-- `https://conductor.makefile.so`
15+- `https://conductor.makefile.so` -> VPS Nginx -> `100.71.210.78:4317`
16 - `mini` 本地 conductor:`http://100.71.210.78:4317`
17-- `mini` 本地 status-api:`http://100.71.210.78:4318`
18+- `mini` 本地 status-api:`http://100.71.210.78:4318`,仅用于本地只读观察
19+- `https://control-api.makefile.so`,仅用于迁移期兼容与残留依赖盘点
20 
21 ## 当前保留内容
22 
23-- Cloudflare Worker + D1 控制面
24-- `mini` 的 conductor / status-api / worker-runner
25+- `mini` 的 conductor / worker-runner
26 - launchd 安装与检查脚本
27 - Firefox 插件子目录 `plugins/baa-firefox`
28 - 单节点的 Nginx / DNS 计划脚本
29+- 迁移期兼容件:`apps/control-api-worker`、`apps/status-api`、Cloudflare / D1 相关脚手架
30 
31 ## 当前仍需关注
32 
33-- live `status-api` 可能和 control plane 真相漂移
34-- runtime 路径仍值得继续 canonicalize
35-- 若继续维护,只做小范围修补,不再恢复主备方案
36+- `status-api` 和 launchd 模板仍通过 `BAA_CONTROL_API_BASE` 指向 legacy control plane
37+- `conductor.makefile.so` 当前只直通 `4317` 的现有接口,尚未承接完整业务 API
38+- 若继续维护,后续任务应优先做 local-api cutover 和删旧,不再恢复主备方案
M coordination/TASK_OVERVIEW.md
+17, -13
 1@@ -1,30 +1,34 @@
 2 # 任务总览
 3 
 4-当前主线已经不再按波次推进,也不再保留历史任务板。
 5+当前主线围绕一件事推进:把 `mini` 本地接口收口成唯一主接口,并把对外入口统一到 `conductor.makefile.so`。
 6 
 7 ## 当前状态
 8 
 9-- 没有活动开发任务
10-- 当前仓库只维护 `mini` 单节点路径
11-- 历史主备与并行开发资料已由 tag `ha-failover-archive-2026-03-22` 承担回溯职责
12+- canonical local API: `http://100.71.210.78:4317`
13+- canonical public host: `https://conductor.makefile.so`
14+- `control-api.makefile.so`、Cloudflare Worker、D1 仍在仓库里,但只算迁移期兼容残留
15+- `baa-hand` / `baa-shell` 只保留为接口语义参考,不再作为主系统维护
16+- 活动任务见 [`tasks/`](./tasks/)
17 
18 ## 当前建议
19 
20-如果还要继续维护这个仓库,优先顺序只有三件事:
21+如果还要继续维护这个仓库,优先顺序是:
22 
23-1. 修 `status-api` 与 control plane 真相不一致的问题
24-2. 收口 `mini` 的 runtime 路径和自启动安装路径
25-3. 只在必要时做最小运维修补
26+1. 把 discovery / state / task / run / control 接口并到 `mini` 本地 `4317`
27+2. 去掉 `status-api`、launchd 模板和运行文档对 `BAA_CONTROL_API_BASE` 的主路径依赖
28+3. 删除 `control-api.makefile.so`、Cloudflare Worker、D1 和其它旧文档口径
29 
30 ## 现在该读什么
31 
32 1. [`../DESIGN.md`](../DESIGN.md)
33-2. [`../docs/runtime/README.md`](../docs/runtime/README.md)
34-3. [`../docs/ops/README.md`](../docs/ops/README.md)
35-4. [`STATUS_SUMMARY.md`](./STATUS_SUMMARY.md)
36+2. [`../docs/api/README.md`](../docs/api/README.md)
37+3. [`../docs/runtime/README.md`](../docs/runtime/README.md)
38+4. [`../docs/ops/README.md`](../docs/ops/README.md)
39+5. [`STATUS_SUMMARY.md`](./STATUS_SUMMARY.md)
40 
41 ## 如需新任务
42 
43 - 直接在 `coordination/tasks/` 新建任务卡
44-- 不再恢复旧 wave 文档
45-- 历史任务内容靠 tag 回溯,不在当前主线保留
46+- 所有新任务默认以 `100.71.210.78:4317` 和 `conductor.makefile.so` 为 canonical 接口面
47+- `control-api.makefile.so` 只允许作为删旧前的兼容背景出现
48+- 不再恢复旧 wave 文档;历史内容继续靠 tag `ha-failover-archive-2026-03-22` 回溯
M coordination/WORKFLOW.md
+5, -2
 1@@ -7,8 +7,9 @@
 2 按顺序阅读:
 3 
 4 1. [`../DESIGN.md`](../DESIGN.md)
 5-2. [`TASK_OVERVIEW.md`](./TASK_OVERVIEW.md)
 6-3. 自己的活动任务卡
 7+2. [`../docs/api/README.md`](../docs/api/README.md)
 8+3. [`TASK_OVERVIEW.md`](./TASK_OVERVIEW.md)
 9+4. 自己的活动任务卡
10 
11 ## 2. 每个实例开始前要做什么
12 
13@@ -28,6 +29,8 @@
14 - 不把聊天内容当作任务真相
15 - 不和其他任务共用 worktree
16 - 不随手改超出 `write_scope` 的文件
17+- 所有新任务默认以 `100.71.210.78:4317` 和 `conductor.makefile.so` 为 canonical 接口面
18+- `control-api.makefile.so`、Cloudflare Worker、D1、`baa-hand` / `baa-shell` 只作为 legacy 背景,不再写成默认主路径
19 
20 如果确实需要越界:
21 
A coordination/tasks/T-L001.md
+105, -0
  1@@ -0,0 +1,105 @@
  2+---
  3+task_id: T-L001
  4+title: 文档与切换方案收口
  5+status: review
  6+branch: feat/local-api-cutover-docs
  7+repo: /Users/george/code/baa-conductor
  8+base_ref: main@c9e1441
  9+depends_on: []
 10+write_scope:
 11+  - README.md
 12+  - DESIGN.md
 13+  - docs/api/**
 14+  - docs/ops/**
 15+  - docs/runtime/**
 16+  - coordination/**
 17+updated_at: 2026-03-22
 18+---
 19+
 20+# T-L001 文档与切换方案收口
 21+
 22+## 目标
 23+
 24+把仓库文档统一收口为以下口径:
 25+
 26+- `mini` 本地接口 `http://100.71.210.78:4317` 是唯一主接口
 27+- 对外统一使用 `https://conductor.makefile.so`
 28+- `control-api.makefile.so`、Cloudflare Worker、D1 不再作为默认控制面
 29+- `baa-hand` / `baa-shell` 只保留为参考,不再继续维护为主系统
 30+
 31+## 本任务包含
 32+
 33+- 更新顶层设计与 README
 34+- 更新 `docs/api`、`docs/ops`、`docs/runtime`
 35+- 更新 `coordination` 里的协作和状态说明
 36+- 给后续 cutover 任务写清迁移顺序和删旧范围
 37+
 38+## 本任务不包含
 39+
 40+- 不修改 app 代码
 41+- 不修改 `plugins/baa-firefox/**`
 42+- 不实现新的 API 路由
 43+
 44+## 建议起始文件
 45+
 46+- `README.md`
 47+- `DESIGN.md`
 48+- `docs/api/README.md`
 49+- `docs/api/hand-shell-migration.md`
 50+- `docs/ops/README.md`
 51+- `docs/runtime/README.md`
 52+
 53+## 交付物
 54+
 55+- 一组自洽的 cutover 文档
 56+- 一张已回写状态的任务卡
 57+
 58+## 验收
 59+
 60+- 文档默认口径统一为 local API cutover
 61+- 明确 `conductor.makefile.so` / `100.71.210.78:4317`
 62+- 明确 legacy 兼容件与删旧范围
 63+- `git diff --check` 通过
 64+
 65+## files_changed
 66+
 67+- `README.md`
 68+- `DESIGN.md`
 69+- `docs/api/README.md`
 70+- `docs/api/hand-shell-migration.md`
 71+- `docs/ops/README.md`
 72+- `docs/runtime/README.md`
 73+- `docs/runtime/environment.md`
 74+- `docs/runtime/launchd.md`
 75+- `docs/runtime/node-verification.md`
 76+- `coordination/TASK_OVERVIEW.md`
 77+- `coordination/STATUS_SUMMARY.md`
 78+- `coordination/WORKFLOW.md`
 79+- `coordination/tasks/T-L001.md`
 80+
 81+## commands_run
 82+
 83+- `git status --short --branch`
 84+- `git rev-parse --short HEAD`
 85+- `sed -n '1,260p' ...` 读取顶层、API、ops、runtime、coordination 文档
 86+- `rg -n "control-api\\.makefile\\.so|Cloudflare Worker|D1|baa-hand|baa-shell|..." ...` 盘点旧口径
 87+- `git diff --stat`
 88+- `git diff --check`
 89+
 90+## result
 91+
 92+- 把仓库主文档统一收口为 `mini` 本地 `4317` 是唯一主接口、`conductor.makefile.so` 是唯一 canonical 公网入口
 93+- 明确把 `control-api.makefile.so`、Cloudflare Worker、D1 降级为迁移期兼容件
 94+- 明确把 `baa-hand` / `baa-shell` 降级为参考实现
 95+- 给后续任务写清了 cutover 顺序、删旧范围和 runtime 兼容残留
 96+
 97+## risks
 98+
 99+- app/runtime 代码仍保留 `BAA_CONTROL_API_BASE` 和 legacy control-plane 依赖,文档收口不等于代码已完成切换
100+- 仓库里存在与本任务无关的未提交代码改动,提交时必须只选中文档范围文件
101+
102+## next_handoff
103+
104+- 先把 discovery / control / task / run 路由并到 `4317`
105+- 再去掉 `status-api`、launchd 模板和运行脚本对 `BAA_CONTROL_API_BASE` 的默认依赖
106+- 最后删除 `control-api.makefile.so`、Cloudflare Worker、D1 和 public `status-api` 角色
M docs/api/README.md
+67, -62
  1@@ -1,102 +1,107 @@
  2-# HTTP API Surfaces
  3+# Local API Cutover
  4 
  5-`baa-conductor` 当前只维护单节点 `mini` 方案,因此 HTTP 面也按这个约束描述:
  6+`baa-conductor` 的 canonical 接口面已经收口为:
  7 
  8-- 不恢复主备切换
  9-- 不要求 token 的临时模式仍可工作
 10-- 推荐所有 AI 客户端先读 `/describe`
 11+- canonical local API: `http://100.71.210.78:4317`
 12+- canonical public host: `https://conductor.makefile.so`
 13+- `https://control-api.makefile.so` 只作为迁移期兼容入口,不再是默认业务接口
 14 
 15-## 入口
 16+## Canonical base URLs
 17 
 18-| 服务 | 公开地址 | 说明 |
 19+| 面 | 地址 | 用途 |
 20 | --- | --- | --- |
 21-| control-api | `https://control-api.makefile.so` | 控制面、能力发现、任务/run/controller 只读查询 |
 22-| status-api | `https://conductor.makefile.so` | 状态快照 JSON 和 HTML 面板 |
 23+| local primary | `http://100.71.210.78:4317` | 唯一主接口、内网真相源、后续完整 HTTP API 的承载面 |
 24+| public primary | `https://conductor.makefile.so` | 唯一对外域名,应与 local primary 暴露同一套 canonical 路由 |
 25+| local status view | `http://100.71.210.78:4318` | 本地只读观察面;迁移期保留,不是主控制面 |
 26 
 27-## Describe First
 28+## 当前已在主接口上的路由
 29 
 30-新对话建议顺序:
 31+当前 `4317` 已提供:
 32 
 33-1. `GET https://control-api.makefile.so/describe`
 34-2. 如需更窄的能力发现,再读 `GET https://control-api.makefile.so/v1/capabilities`
 35-3. 先用只读接口确认当前状态、最近任务和最近 run
 36-4. 只有在明确需要控制动作时,才调用 `pause` / `resume` / `drain` / `tasks.create`
 37+| 方法 | 路径 | 说明 |
 38+| --- | --- | --- |
 39+| `GET` | `/healthz` | 最小健康检查 |
 40+| `GET` | `/readyz` | 就绪检查 |
 41+| `GET` | `/rolez` | 当前角色信息 |
 42+| `GET` | `/v1/runtime` | 本地 runtime 摘要 |
 43 
 44-状态视图服务同样支持:
 45+这些路由已经通过 `conductor.makefile.so` 暴露给公网。
 46 
 47-1. `GET https://conductor.makefile.so/describe`
 48-2. `GET https://conductor.makefile.so/v1/status`
 49+## cutover 目标路由
 50 
 51-## Control API
 52+后续任务要把以下能力并到同一个接口面:
 53 
 54-### 可发现性接口
 55+### discovery
 56 
 57-| 方法 | 路径 | 说明 |
 58-| --- | --- | --- |
 59-| `GET` | `/describe` | 完整自描述 JSON,包含 `name`、`version`、`environment`、`endpoints`、`capabilities`、`examples`、`notes` |
 60-| `GET` | `/version` | 轻量版本查询 |
 61-| `GET` | `/health` | 健康摘要、部署模式、鉴权模式、repository 是否就绪 |
 62-| `GET` | `/v1/capabilities` | 更窄的能力发现接口,区分只读/写接口与当前模式 |
 63+- `GET /describe`
 64+- `GET /version`
 65+- `GET /health`
 66+- `GET /v1/capabilities`
 67 
 68-### 只读 / 功能型接口
 69+### control and query
 70 
 71-| 方法 | 路径 | 说明 |
 72-| --- | --- | --- |
 73-| `GET` | `/v1/system/state` | 当前 automation / leader / queue 摘要 |
 74-| `GET` | `/v1/controllers?limit=20` | 已注册 controller 摘要,带 active controller 线索 |
 75-| `GET` | `/v1/tasks?status=queued&limit=20` | 最近任务摘要,可按 `status` 过滤 |
 76-| `GET` | `/v1/tasks/:task_id` | 单个 task 详情 |
 77-| `GET` | `/v1/runs?limit=20` | 最近 run 摘要 |
 78-| `GET` | `/v1/runs/:run_id` | 单个 run 详情 |
 79+- `GET /v1/system/state`
 80+- `GET /v1/controllers`
 81+- `GET /v1/tasks`
 82+- `GET /v1/tasks/:task_id`
 83+- `GET /v1/tasks/:task_id/logs`
 84+- `GET /v1/runs`
 85+- `GET /v1/runs/:run_id`
 86+- `POST /v1/tasks`
 87+- `POST /v1/system/pause`
 88+- `POST /v1/system/resume`
 89+- `POST /v1/system/drain`
 90 
 91-### 控制型接口
 92+### 来自 hand / shell 语义的可选扩展
 93 
 94-| 方法 | 路径 | 说明 |
 95-| --- | --- | --- |
 96-| `POST` | `/v1/tasks` | 创建 task |
 97-| `POST` | `/v1/system/pause` | 切到 `paused` |
 98-| `POST` | `/v1/system/resume` | 切到 `running` |
 99-| `POST` | `/v1/system/drain` | 切到 `draining` |
100+- `POST /v1/exec`
101+- `POST /v1/files/read`
102+- `POST /v1/files/write`
103 
104-其它 controller / worker 写接口仍保留在 control-api 中,但部分还是占位合同;先读 `/describe` 里的 `implementation` 字段再决定是否调用。
105+这些路由在 cutover 完成前可能仍存在于 legacy control plane;但新的文档、调用方和设计说明不再把它写成默认事实。
106 
107-## Status API
108+## cutover 完成后的推荐调用顺序
109 
110-`status-api` 是只读视图服务,不拥有真相。
111+1. 先请求 `GET /describe`
112+2. 再读 `GET /v1/capabilities`
113+3. 先做只读确认:
114+   - `GET /v1/system/state`
115+   - `GET /v1/tasks`
116+   - `GET /v1/runs`
117+4. 只有在需要真实操作时,再调用写接口
118 
119-truth source:
120+## 迁移期兼容说明
121 
122-- 默认回源 `control-api /v1/system/state`
123-- 当前只负责把这个真相整理成 JSON 或 HTML
124+- `https://control-api.makefile.so` 仍可用于盘点旧调用方依赖
125+- `apps/control-api-worker`、Cloudflare Worker、D1 仍在仓库中,但只算迁移期兼容层
126+- `status-api` 当前仍从 `BAA_CONTROL_API_BASE` 读取 truth source,因此 `4318` 只能算本地观察面
127 
128-当前端点:
129+## Minimal Curl
130 
131-| 方法 | 路径 | 说明 |
132-| --- | --- | --- |
133-| `GET` | `/describe` | 说明 status-api 本身、truth source 和返回格式 |
134-| `GET` | `/healthz` | 纯健康检查,返回 `ok` |
135-| `GET` | `/v1/status` | JSON 状态快照 |
136-| `GET` | `/v1/status/ui` | HTML 状态面板 |
137-| `GET` | `/` / `/ui` | `/v1/status/ui` 别名 |
138+当前已稳定可用的 canonical 路径:
139 
140-## Minimal Curl
141+```bash
142+curl https://conductor.makefile.so/healthz
143+```
144 
145 ```bash
146-curl https://control-api.makefile.so/describe
147+curl https://conductor.makefile.so/readyz
148 ```
149 
150 ```bash
151-curl https://control-api.makefile.so/v1/capabilities
152+curl https://conductor.makefile.so/rolez
153 ```
154 
155 ```bash
156-curl 'https://control-api.makefile.so/v1/tasks?status=queued&limit=5'
157+curl https://conductor.makefile.so/v1/runtime
158 ```
159 
160 ```bash
161-curl 'https://control-api.makefile.so/v1/runs?limit=5'
162+curl http://100.71.210.78:4318/v1/status
163 ```
164 
165+legacy 盘点时才需要:
166+
167 ```bash
168-curl https://conductor.makefile.so/describe
169+curl https://control-api.makefile.so/describe
170 ```
M docs/api/hand-shell-migration.md
+62, -120
  1@@ -4,9 +4,12 @@
  2 
  3 ## 1. 目标
  4 
  5-把 `baa-hand` / `baa-shell` 已经验证可用的“HTTP 交互方式”整体迁移到 `baa-conductor`,由 `baa-conductor` 成为唯一对外服务面。
  6+把 `baa-hand` / `baa-shell` 已经验证可用的 HTTP 交互方式迁到 `baa-conductor`,但承载面统一改为:
  7 
  8-本次迁移的重点不是复用旧代码,而是复用旧系统已经被验证过的交互经验:
  9+- canonical local API: `http://100.71.210.78:4317`
 10+- canonical public host: `https://conductor.makefile.so`
 11+
 12+这次迁移的重点不是复用旧代码,而是复用旧系统已经被验证过的交互经验:
 13 
 14 - 先 `GET /describe`
 15 - 再决定调用哪个接口
 16@@ -24,9 +27,8 @@
 17 - `worker`
 18 - `checkpoint`
 19 - `logging`
 20-- `control-api`
 21-- `status-api`
 22 - `mini` 单节点自启动
 23+- `conductor-daemon` / `worker-runner` / `status-api`
 24 
 25 所以后续不再继续平行维护三套系统:
 26 
 27@@ -38,6 +40,7 @@
 28 
 29 - `baa-hand` / `baa-shell` 只作为参考实现
 30 - `baa-conductor` 成为唯一主项目
 31+- `control-api.makefile.so` 不再作为默认业务接口
 32 
 33 ## 3. 迁移边界
 34 
 35@@ -49,7 +52,7 @@
 36 - 本机执行能力
 37 - 文件访问能力
 38 - 异步任务接口
 39-- 任务 / run / log / report 查询
 40+- 任务 / run / log 查询
 41 
 42 ### 3.2 本次不迁
 43 
 44@@ -60,11 +63,11 @@
 45 
 46 说明:
 47 
 48-当前先把“本机访问能力”和“业务控制接口”统一进 `baa-conductor`,AI 代理后续如仍需要,再单独设计。
 49+当前先把“本机访问能力”和“业务控制接口”统一进 `baa-conductor`;AI 代理如仍有需要,后续再单独设计。
 50 
 51 ## 4. 设计原则
 52 
 53-### 4.1 不做兼容层
 54+### 4.1 不做兼容优先层
 55 
 56 不要为了兼容旧系统,把 `baa-hand` / `baa-shell` 的老实现直接搬进来。
 57 
 58@@ -80,16 +83,17 @@
 59 - 旧内存状态机
 60 - 旧散装 server
 61 
 62-### 4.2 新接口围绕 `baa-conductor` 真实内核设计
 63+### 4.2 新接口围绕 `mini` 本地接口设计
 64 
 65-底层必须直接接入:
 66+底层应直接接入:
 67 
 68-- `control-api-worker`
 69+- `apps/conductor-daemon`
 70 - `task/run/step`
 71-- `db`
 72 - `worker`
 73 - `logs/checkpoints`
 74 
 75+`apps/control-api-worker` 只保留为 cutover 期间的兼容层,不再是长期主架构。
 76+
 77 ### 4.3 先读后写
 78 
 79 和 `baa-hand` / `baa-shell` 一样,建议约定:
 80@@ -102,57 +106,24 @@
 81 
 82 当前项目已经收口为 `mini` 单节点,所以新接口文档和行为都以单节点为准,不再继续围绕主备切换设计。
 83 
 84-## 5. 新接口分层
 85-
 86-## 5.1 服务发现层
 87-
 88-### `GET /describe`
 89-
 90-用途:
 91-
 92-- 返回完整自描述 JSON
 93-- 给 Claude / 手机网页 / 浏览器工具“先发现能力,再调用”
 94-
 95-建议内容:
 96-
 97-- `name`
 98-- `version`
 99-- `description`
100-- `deployment_mode`
101-- `auth_mode`
102-- `endpoints`
103-- `capabilities`
104-- `examples`
105-- `notes`
106-
107-### `GET /health`
108+## 5. 目标接口分层
109 
110-用途:
111+### 5.1 服务发现层
112 
113-- 最小健康检查
114-
115-### `GET /version`
116-
117-用途:
118-
119-- 返回版本信息
120-
121-## 5.2 控制层
122+- `GET /describe`
123+- `GET /health`
124+- `GET /version`
125+- `GET /v1/capabilities`
126 
127-保留并继续使用:
128+### 5.2 控制层
129 
130 - `GET /v1/system/state`
131 - `POST /v1/system/pause`
132 - `POST /v1/system/resume`
133 - `POST /v1/system/drain`
134 
135-这是当前最稳定的公网控制入口。
136+### 5.3 查询层
137 
138-## 5.3 只读功能层
139-
140-建议统一成以下接口:
141-
142-- `GET /v1/capabilities`
143 - `GET /v1/controllers`
144 - `GET /v1/tasks`
145 - `GET /v1/tasks/:task_id`
146@@ -160,34 +131,18 @@
147 - `GET /v1/runs`
148 - `GET /v1/runs/:run_id`
149 
150-这些接口的目标不是控制,而是:
151-
152-- 看当前系统里有什么
153-- 看任务跑到哪里了
154-- 看最近执行过什么
155-- 看日志和结果
156-
157-## 5.4 本机能力层
158-
159-这层承接 `baa-shell` 的思路,但直接接入 `baa-conductor`:
160+### 5.4 本机能力层
161 
162 - `POST /v1/exec`
163 - `POST /v1/files/read`
164 - `POST /v1/files/write`
165 
166-建议行为:
167-
168-- 同步小操作
169-- 明确 cwd / timeout / path
170-- 返回结构化结果
171-
172-注意:
173-
174-这层属于“本机访问能力”,不是 control-plane 状态写入。
175+说明:
176 
177-## 5.5 异步任务层
178+- 这层承接 `baa-shell` 的“小而直接”的使用体验
179+- 它属于本机访问能力,不是 legacy control-plane 状态写入
180 
181-这层承接 `baa-shell /task` 的使用体验,但底层直接接 `baa-conductor` 的 task/run 模型:
182+### 5.5 异步任务层
183 
184 - `POST /v1/tasks`
185 - `GET /v1/tasks`
186@@ -198,8 +153,8 @@
187 
188 说明:
189 
190-- 同步 `exec/read/write` 适合小操作
191-- 真正的长活、worker 编排、日志跟踪,应该走 task/run
192+- `exec/read/write` 适合同步小操作
193+- 长活、worker 编排、日志跟踪应走 task/run
194 
195 ## 6. 旧接口到新接口的映射
196 
197@@ -216,7 +171,7 @@
198 | `POST /task` | `POST /v1/tasks` |
199 | `GET /task/:id` | `GET /v1/tasks/:task_id` |
200 | `GET /tasks` | `GET /v1/tasks` |
201-| `GET /reports` | 可拆成 `GET /v1/tasks/:task_id/logs` 或后续 `GET /v1/reports/:id` |
202+| `GET /reports` | 优先收口为 `GET /v1/tasks/:task_id/logs`,必要时再单独补 report 面 |
203 
204 ### 6.2 `baa-hand`
205 
206@@ -227,42 +182,14 @@
207 | `POST /chat` | 暂缓,不是当前优先级 |
208 | `POST /plan` | 长期可考虑转成 `POST /v1/tasks` + planner 策略 |
209 
210-## 7. 一次性迁移后的推荐接口面
211+## 7. 推荐接口面
212 
213 对外推荐只保留一套:
214 
215-### 服务发现
216-
217-- `GET /describe`
218-- `GET /health`
219-- `GET /version`
220-- `GET /v1/capabilities`
221-
222-### 控制
223+- local: `http://100.71.210.78:4317`
224+- public: `https://conductor.makefile.so`
225 
226-- `GET /v1/system/state`
227-- `POST /v1/system/pause`
228-- `POST /v1/system/resume`
229-- `POST /v1/system/drain`
230-
231-### 查询
232-
233-- `GET /v1/controllers`
234-- `GET /v1/tasks`
235-- `GET /v1/tasks/:task_id`
236-- `GET /v1/tasks/:task_id/logs`
237-- `GET /v1/runs`
238-- `GET /v1/runs/:run_id`
239-
240-### 本机能力
241-
242-- `POST /v1/exec`
243-- `POST /v1/files/read`
244-- `POST /v1/files/write`
245-
246-### 异步任务
247-
248-- `POST /v1/tasks`
249+`control-api.makefile.so` 在 cutover 完成前可继续兜底,但不再作为新文档和新调用方的默认目标。
250 
251 ## 8. 实施顺序
252 
253@@ -278,21 +205,25 @@
254 
255 目标:
256 
257-- 让 Claude 能先发现能力
258-- 让 Claude 能先读状态和列表
259+- 让 Claude、浏览器和 CLI 能先发现能力
260+- 让新调用方直接走 `4317` / `conductor.makefile.so`
261 
262 ### 第二批
263 
264-- `POST /v1/exec`
265-- `POST /v1/files/read`
266-- `POST /v1/files/write`
267+- `GET /v1/system/state`
268+- `POST /v1/system/pause`
269+- `POST /v1/system/resume`
270+- `POST /v1/system/drain`
271 
272 目标:
273 
274-- 把 `shell` 的本机能力迁进来
275+- 把当前 control-plane 的关键读写能力切到 canonical 接口面
276 
277 ### 第三批
278 
279+- `POST /v1/exec`
280+- `POST /v1/files/read`
281+- `POST /v1/files/write`
282 - `POST /v1/tasks`
283 - `GET /v1/tasks/:task_id`
284 - `GET /v1/tasks/:task_id/logs`
285@@ -300,13 +231,24 @@
286 
287 目标:
288 
289-- 把异步任务体验统一进 `baa-conductor`
290+- 把 hand / shell 的本机能力和异步任务体验统一进 `baa-conductor`
291 
292 ### 第四批
293 
294-- 如仍然有需要,再考虑 AI 代理接口
295+- 切浏览器、CLI、运维脚本和文档默认目标
296+- 删除 `control-api.makefile.so`、Cloudflare Worker、D1 与 public `status-api` 角色
297+
298+## 9. 删旧范围
299+
300+cutover 完成后,优先删除或归档:
301+
302+- `control-api.makefile.so` 作为主业务接口的所有描述
303+- Cloudflare Worker / D1 的默认控制面角色
304+- `status-api` 的公网职责
305+- `baa-hand` / `baa-shell` 作为主系统的维护承诺
306+- 运行文档和 launchd 模板中默认把 `BAA_CONTROL_API_BASE` 当真相源的口径
307 
308-## 9. 文档与使用方式
309+## 10. 文档与使用方式
310 
311 迁移完成后,所有新对话都应该遵循这个使用方式:
312 
313@@ -324,14 +266,14 @@
314    - `POST /v1/files/write`
315    - `POST /v1/tasks`
316 
317-## 10. 当前结论
318+## 11. 当前结论
319 
320 这次迁移的目标不是“把 hand/shell 保留成旧子系统”,而是:
321 
322 - 让 `baa-conductor` 成为唯一主项目
323 - 让外部 HTTP 交互方式继续保持简单
324-- 让 Claude / 手机网页 / 浏览器都能直接通过统一域名和统一接口工作
325+- 让 Claude / 手机网页 / 浏览器都直接通过 `conductor.makefile.so` 和 `100.71.210.78:4317` 工作
326 
327 一句话:
328 
329-`baa-hand` / `baa-shell` 继续保留为参考样例,但业务控制接口和本机访问能力应该整体收口到 `baa-conductor`。
330+`baa-hand` / `baa-shell` 继续保留为参考样例,但业务控制接口和本机访问能力应该整体收口到 `baa-conductor` 的 local API。
M docs/ops/README.md
+38, -21
 1@@ -1,10 +1,13 @@
 2-# VPS、Nginx 与 Cloudflare DNS 运维
 3+# VPS、Nginx 与 DNS 运维
 4 
 5-当前运维模型只保留一条路径:
 6+当前运维模型只保留一条 canonical 路径:
 7 
 8-- `control-api.makefile.so` 由 Cloudflare Worker / D1 提供
 9-- `conductor.makefile.so` 由 VPS Nginx 回源到 `mini`
10-- `mini` 内网固定地址:`100.71.210.78:4317`
11+- `conductor.makefile.so` 是唯一公网域名
12+- VPS Nginx 统一回源到 `mini` 的 `100.71.210.78:4317`
13+- `mini` 本地 `4317` 是唯一主接口
14+- `mini` 本地 `4318` 只作为迁移期的只读观察面
15+
16+`control-api.makefile.so`、Cloudflare Worker、D1 仍在仓库和线上资产里,但不再作为默认运维路径描述。
17 
18 主备切换、直连 `mac` 的公网域名和历史切换 runbook 已从当前主线移除。
19 
20@@ -19,7 +22,8 @@
21 - Cloudflare zone
22 - VPS 公网 IP
23 - `conductor.makefile.so`
24-- `mini` 的 Tailscale `100.x`
25+- `mini` 的 Tailscale `100.71.210.78:4317`
26+- 可选本地观察口 `100.71.210.78:4318`
27 - 证书与 Nginx 安装路径
28 
29 ## 当前公网关系
30@@ -30,27 +34,26 @@
31 
32 ## HTTP 面说明
33 
34-当前建议把两个公开入口分开理解:
35+默认只把一条主路径当真:
36 
37-| 入口 | 公开地址 | 当前用途 | 推荐首个请求 |
38+| 面 | 地址 | 当前用途 | 推荐首个请求 |
39 | --- | --- | --- | --- |
40-| control-api | `https://control-api.makefile.so` | 控制面、自描述、只读查询、任务创建 | `GET /describe` |
41-| status-api | `https://conductor.makefile.so` | 状态 JSON / HTML 视图 | `GET /describe` |
42+| public primary | `https://conductor.makefile.so` | 唯一公网入口 | `GET /healthz` |
43+| local primary | `http://100.71.210.78:4317` | 真相源、on-node 调试 | `GET /healthz` |
44+| local status view | `http://100.71.210.78:4318` | 本地状态快照 / HTML 观察面 | `GET /healthz` |
45 
46 最小排查顺序:
47 
48-1. `curl https://control-api.makefile.so/describe`
49-2. `curl https://control-api.makefile.so/health`
50-3. `curl https://control-api.makefile.so/v1/system/state`
51-4. `curl https://conductor.makefile.so/describe`
52-5. `curl https://conductor.makefile.so/v1/status`
53+1. `curl https://conductor.makefile.so/healthz`
54+2. `curl https://conductor.makefile.so/readyz`
55+3. `curl https://conductor.makefile.so/rolez`
56+4. `curl https://conductor.makefile.so/v1/runtime`
57+5. 如需 on-node 观察,再看 `curl http://100.71.210.78:4318/v1/status`
58 
59-control-api 当前新增的只读功能型接口:
60+legacy 兼容盘点时才需要:
61 
62-- `GET /v1/capabilities`
63-- `GET /v1/controllers`
64-- `GET /v1/tasks`
65-- `GET /v1/runs`
66+1. `curl https://control-api.makefile.so/describe`
67+2. `curl https://control-api.makefile.so/v1/system/state`
68 
69 ## 当前节点监听
70 
71@@ -123,10 +126,24 @@ ssh root@YOUR_VPS 'cd /tmp/baa-conductor-nginx && sudo ./deploy-on-vps.sh --relo
72 3. `conductor.makefile.so` 已有 DNS 记录
73 4. 证书路径与 inventory 一致
74 
75+## cutover 顺序
76+
77+1. 先把完整业务 API 并到 `4317`,并让 `conductor.makefile.so` 暴露同一套路由。
78+2. 再切浏览器、CLI、AI 和运维说明,停止把 `control-api.makefile.so` 当默认路径。
79+3. 最后删除 `control-api.makefile.so`、Cloudflare Worker、D1 和 public `status-api` 角色。
80+
81+## 删旧范围
82+
83+完成 local-api cutover 后,运维侧优先删除:
84+
85+- `control-api.makefile.so` 的 DNS / 部署主路径职责
86+- Cloudflare Worker / D1 的默认控制面说明
87+- 所有依赖 `control-api.makefile.so` 的默认 runbook
88+- `status-api` 的公网暴露假设
89+
90 ## 说明
91 
92 - 当前只维护 `conductor.makefile.so`
93 - 不依赖 MagicDNS
94 - 是否启用 Cloudflare proxy 由实际证书和 SSL mode 决定
95 - 历史多节点资料只通过 tag `ha-failover-archive-2026-03-22` 回溯
96-- control-api / status-api 都支持 `GET /describe`,建议先读它再做后续请求
M docs/runtime/README.md
+5, -1
 1@@ -1,6 +1,6 @@
 2 # runtime
 3 
 4-当前 runtime 只定义 `mini` 单节点的长期运行方式。
 5+当前 runtime 只定义 `mini` 单节点的长期运行方式,并默认以 local API cutover 为主线。
 6 
 7 ## 内容
 8 
 9@@ -12,6 +12,10 @@
10 ## 当前约定
11 
12 - 长期运行节点只有 `mini`
13+- canonical local API: `http://100.71.210.78:4317`
14+- canonical public host: `https://conductor.makefile.so`
15+- `status-api` `http://100.71.210.78:4318` 只作为本地只读观察面
16+- `BAA_CONTROL_API_BASE` 仍在当前脚本里保留,但只是兼容变量,不是 canonical 主路径
17 - 推荐仓库路径:`/Users/george/code/baa-conductor`
18 - repo 内的 plist 只作为模板;真正加载的是脚本渲染出来的安装副本
19 
M docs/runtime/environment.md
+15, -3
 1@@ -1,18 +1,25 @@
 2 # runtime environment
 3 
 4-当前只保留 `mini` 单节点变量。
 5+当前只保留 `mini` 单节点变量,默认口径如下:
 6+
 7+- canonical local API: `http://100.71.210.78:4317`
 8+- canonical public host: `https://conductor.makefile.so`
 9+- local status view: `http://100.71.210.78:4318`
10 
11 ## 共享变量
12 
13-- `BAA_CONTROL_API_BASE`
14 - `BAA_SHARED_TOKEN`
15 - `BAA_RUNS_DIR`
16 - `BAA_WORKTREES_DIR`
17 - `BAA_LOGS_DIR`
18 - `BAA_TMP_DIR`
19 - `BAA_STATE_DIR`
20+- `BAA_CONTROL_API_BASE`
21 
22-`status-api` 默认把 `BAA_CONTROL_API_BASE` 当成 live truth source,并读取 `${BAA_CONTROL_API_BASE}/v1/system/state`。
23+说明:
24+
25+- `BAA_CONTROL_API_BASE` 是兼容变量,当前主要给 `status-api` 和遗留脚本使用
26+- 它不代表 canonical 主接口,也不应该再被写成默认控制面
27 
28 ## 节点变量
29 
30@@ -26,13 +33,18 @@ BAA_STATUS_API_HOST=100.71.210.78
31 BAA_CONTROL_API_BASE=https://control-api.makefile.so
32 ```
33 
34+上面最后一项仍是当前兼容值;等 `status-api` 和 launchd 模板去掉 legacy 依赖后,应从默认运行路径删除。
35+
36 ## 最小例子
37 
38+当前脚本仍要求保留兼容参数时,可这样安装:
39+
40 ```bash
41 ./scripts/runtime/install-launchd.sh \
42   --repo-dir /Users/george/code/baa-conductor \
43   --node mini \
44   --shared-token-file /Users/george/.config/baa-conductor/shared-token.txt \
45+  --control-api-base https://control-api.makefile.so \
46   --local-api-base http://100.71.210.78:4317 \
47   --local-api-allowed-hosts 100.71.210.78 \
48   --status-api-host 100.71.210.78
M docs/runtime/launchd.md
+9, -1
 1@@ -4,7 +4,8 @@
 2 
 3 ## 当前目标状态
 4 
 5-- `conductor` 与 `status-api` 由 `launchd` 托管
 6+- `conductor` 由 `launchd` 托管,并承载 canonical local API `http://100.71.210.78:4317`
 7+- `status-api` 仍会随默认安装一起部署,但只作为本地只读观察面
 8 - 工作目录固定到 `/Users/george/code/baa-conductor`
 9 - 通过仓库内脚本统一安装、启动、停止、重启与验证
10 
11@@ -32,6 +33,11 @@
12 
13 里提取 `BAA_SHARED_TOKEN` 并生成它。
14 
15+说明:
16+
17+- 这里的 `control-api-worker.secrets.env` 只是当前兼容来源,不代表 canonical 控制面仍是 Worker
18+- 脚本里保留 `--control-api-base` 也是同样原因,只为兼容 `status-api`
19+
20 ## 日常管理
21 
22 查看状态:
23@@ -72,6 +78,8 @@ npx --yes pnpm -r build
24 
25 ## 3. 渲染安装副本
26 
27+保留 `--control-api-base`,只是为了让当前 `status-api` 继续工作:
28+
29 ```bash
30 ./scripts/runtime/install-launchd.sh \
31   --repo-dir /Users/george/code/baa-conductor \
M docs/runtime/node-verification.md
+33, -10
 1@@ -1,6 +1,6 @@
 2 # node verification
 3 
 4-当前只检查 `mini`。
 5+当前只检查 `mini`,并把 `4317` 视为主接口。
 6 
 7 ## 1. 构建与静态检查
 8 
 9@@ -19,6 +19,11 @@ npx --yes pnpm -r build
10   --status-api-host 100.71.210.78
11 ```
12 
13+说明:
14+
15+- `--control-api-base` 仍是当前静态检查参数,但只用于兼容 `status-api`
16+- 它不改变 `4317` 是 canonical local API 的事实
17+
18 ## 2. 运行态检查
19 
20 ```bash
21@@ -36,24 +41,42 @@ npx --yes pnpm -r build
22   --check-loaded
23 ```
24 
25-关键状态对齐可以直接再跑一组比对:
26+## 3. 主路径手工探针
27+
28+```bash
29+curl -fsSL https://conductor.makefile.so/healthz
30+curl -fsSL https://conductor.makefile.so/readyz
31+curl -fsSL https://conductor.makefile.so/rolez
32+curl -fsSL https://conductor.makefile.so/v1/runtime
33+```
34+
35+on-node 时也可以直接探:
36+
37+```bash
38+curl -fsSL http://100.71.210.78:4317/healthz
39+curl -fsSL http://100.71.210.78:4317/v1/runtime
40+```
41+
42+## 4. 兼容层检查
43+
44+如果 `status-api` 仍在本地保留,再检查:
45 
46 ```bash
47-curl -fsSL https://control-api.makefile.so/v1/system/state
48 curl -fsSL http://100.71.210.78:4318/v1/status
49 ```
50 
51-至少确认这些字段一致:
52+如果你在做删旧前盘点,才需要额外看 legacy control plane:
53+
54+```bash
55+curl -fsSL https://control-api.makefile.so/v1/system/state
56+```
57 
58-- `mode`
59-- `holder_id` vs `leaderId`
60-- `term`
61-- `lease_expires_at` vs `leaseExpiresAt`
62-- `source` 不再是 `empty`
63+这个调用只用于确认还有哪些字段或调用方尚未从 legacy control plane 迁出,不是新的默认验证口径。
64 
65 ## 常见失败点
66 
67 - `conductor /rolez` 不是 `leader`
68-- `status-api /v1/status` 与 control-api 不一致
69+- `conductor.makefile.so` 没有正确回源到 `100.71.210.78:4317`
70+- `status-api /v1/status` 仍依赖 legacy truth source,导致本地观察结果漂移
71 - `launchctl print` 失败
72 - `logs/launchd/*.log` 没有新内容