baa-conductor

git clone 

commit
693b8af
parent
6ea34e2
author
im_wower
date
2026-03-28 17:40:23 +0800 CST
docs: add artifact static service task cards T-S039 through T-S042

- T-S039: Foundation (DB + static file gen + /artifact/ route)
- T-S040: Pipeline integration (ingest/executor write + truncation)
- T-S041: Query routes (/v1/messages, /v1/executions, /v1/sessions)
- T-S042: D1 async adapter and sync queue
- Update TASK_OVERVIEW with execution order and dependencies

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
5 files changed,  +689, -6
A tasks/T-S039.md
+174, -0
  1@@ -0,0 +1,174 @@
  2+# Task T-S039:Artifact 静态服务基础层
  3+
  4+## 状态
  5+
  6+- 当前状态:`待开始`
  7+- 规模预估:`M`
  8+- 依赖任务:无
  9+
 10+## 直接给对话的提示词
 11+
 12+读 `/Users/george/code/baa-conductor/tasks/T-S039.md` 任务文档,完成开发任务。
 13+
 14+如需补背景,再读:
 15+
 16+- `/Users/george/code/baa-conductor/plans/ARTIFACT_STATIC_SERVICE.md`
 17+
 18+## 当前基线
 19+
 20+- 仓库:`/Users/george/code/baa-conductor`
 21+- 分支基线:`main`
 22+- 提交:`6ea34e2`
 23+
 24+## 分支与 worktree(强制)
 25+
 26+每个任务必须使用独立的分支和 worktree,禁止直接在 main 上修改,禁止多个任务共用同一个 worktree。
 27+
 28+- 分支名:`feat/artifact-foundation`
 29+- worktree 路径:`/Users/george/code/baa-conductor-artifact-foundation`
 30+
 31+开工步骤:
 32+
 33+1. `cd /Users/george/code/baa-conductor`
 34+2. `git worktree add ../baa-conductor-artifact-foundation -b feat/artifact-foundation main`
 35+3. `cd ../baa-conductor-artifact-foundation`
 36+4. 在这个 worktree 目录里开发,不要回到主仓库目录
 37+
 38+完成后合并步骤:
 39+
 40+1. 在 worktree 里提交所有变更
 41+2. `cd /Users/george/code/baa-conductor`
 42+3. `git merge feat/artifact-foundation`
 43+4. `git worktree remove ../baa-conductor-artifact-foundation`
 44+
 45+合并冲突处理:
 46+
 47+1. 如果 `git merge` 报冲突,先 `git diff` 查看冲突文件
 48+2. 手动解决冲突后 `git add` 冲突文件
 49+3. `git merge --continue` 完成合并
 50+4. 不要用 `git merge --abort` 然后 force 覆盖
 51+
 52+## 目标
 53+
 54+新建 artifact 数据库(SQLite),建表,实现静态文件生成模块,在 conductor HTTP server 上挂载 `/artifact/` 路由和 `/robots.txt`。
 55+
 56+## 背景
 57+
 58+当前执行结果只能文本回送,大结果截断丢失,跨会话无法接续。需要把消息和执行结果持久化到数据库,同时生成可通过 HTTP GET 访问的静态文件。本任务是整个 Artifact 静态服务的基础层,后续任务依赖本任务的数据库和文件生成能力。
 59+
 60+## 涉及仓库
 61+
 62+- `/Users/george/code/baa-conductor`
 63+
 64+## 范围
 65+
 66+- 新建 artifact SQLite 数据库(独立于现有 packages/db)
 67+- 建 messages、executions、sessions 三张表
 68+- 实现静态文件生成模块(.txt + .json 双格式)
 69+- conductor HTTP server 挂载 `/artifact/` 路由 serve 静态文件
 70+- 挂载 `/robots.txt` 路由
 71+
 72+## 路径约束
 73+
 74+- 新数据库文件放在 `state/artifact.db`
 75+- 静态文件目录放在 `state/artifacts/`
 76+- 静态文件子目录:`state/artifacts/msg/`、`state/artifacts/exec/`、`state/artifacts/session/`
 77+
 78+## 推荐实现边界
 79+
 80+建议新增:
 81+
 82+- `packages/artifact-db/` — 新 package,artifact 数据库层
 83+  - `src/schema.ts` — 建表 SQL
 84+  - `src/store.ts` — CRUD 操作
 85+  - `src/static-gen.ts` — 静态文件生成(.txt + .json)
 86+  - `src/types.ts` — 类型定义
 87+
 88+建议修改:
 89+
 90+- `apps/conductor-daemon/src/local-api.ts` — 新增 `/artifact/` 和 `/robots.txt` 路由
 91+
 92+## 允许修改的目录
 93+
 94+- `/Users/george/code/baa-conductor/packages/` (新建 artifact-db)
 95+- `/Users/george/code/baa-conductor/apps/conductor-daemon/src/local-api.ts` (加路由)
 96+- `/Users/george/code/baa-conductor/apps/conductor-daemon/src/index.ts` (初始化数据库)
 97+
 98+## 尽量不要修改
 99+
100+- `/Users/george/code/baa-conductor/packages/db/` (现有数据库,不动)
101+- `/Users/george/code/baa-conductor/plugins/` (插件不动)
102+- `/Users/george/code/baa-conductor/apps/conductor-daemon/src/instructions/` (T-S040 的范围)
103+- `/Users/george/code/baa-conductor/apps/conductor-daemon/src/artifacts/` (T-S040 的范围)
104+
105+## 必须完成
106+
107+### 1. 新建 artifact 数据库和表
108+
109+- 新建 `packages/artifact-db/` package
110+- 建 `messages` 表:id, platform, conversation_id, role, raw_text, summary, observed_at, static_path, page_url, page_title, organization_id, created_at
111+- 建 `executions` 表:instruction_id, message_id, target, tool, params, params_kind, result_ok, result_data, result_summary, result_error, http_status, executed_at, static_path, created_at
112+- 建 `sessions` 表:id, platform, conversation_id, started_at, last_activity_at, message_count, execution_count, summary, created_at
113+- 提供 CRUD 方法:insertMessage, insertExecution, upsertSession, getMessage, getExecution, listMessages, listExecutions, listSessions, getLatestSessions
114+- 表结构参见 `plans/ARTIFACT_STATIC_SERVICE.md` 第 4 节
115+
116+### 2. 实现静态文件生成
117+
118+- 写入数据库时同步生成 `.txt` + `.json` 两个文件
119+- `.txt` 格式:frontmatter 元数据 + `---` 分隔 + 正文(参见方案文档第 6 节)
120+- `.json` 格式:完整 JSON 对象(参见方案文档第 6 节)
121+- 文件路径用 ID 命名:`state/artifacts/msg/{id}.txt`、`state/artifacts/exec/{id}.txt`
122+- Content-Type:`.txt` 返回 `text/plain; charset=utf-8`,`.json` 返回 `application/json; charset=utf-8`
123+
124+### 3. 挂载 HTTP 路由
125+
126+- `/artifact/**` — 从 `state/artifacts/` 目录 serve 静态文件
127+- `/robots.txt` — 返回 `User-agent: *\nAllow: /artifact/\n`
128+- 不需要鉴权(当前公开访问)
129+- 文件不存在时返回 404
130+
131+## 需要特别注意
132+
133+- 新数据库是独立的 `state/artifact.db`,不要动现有的 `packages/db` 和相关 migration
134+- 静态文件生成必须是同步的(写库 → 写文件一起完成),不能异步延迟
135+- URL 中的 ID 使用 hash/UUID 格式,不用递增数字
136+- 本任务只建基础能力,不接入指令执行主链路(那是 T-S040 的事)
137+- 所有开发必须在 worktree 中进行,不要在主仓库目录修改代码
138+
139+## 验收标准
140+
141+- `packages/artifact-db/` 可以独立编译通过
142+- 调用 `insertMessage()` 后,`state/artifacts/msg/{id}.txt` 和 `.json` 文件存在且内容正确
143+- 调用 `insertExecution()` 后,`state/artifacts/exec/{id}.txt` 和 `.json` 文件存在且内容正确
144+- `curl http://100.71.210.78:4317/artifact/msg/{id}.txt` 返回 200 + 正确内容
145+- `curl http://100.71.210.78:4317/artifact/msg/{id}.json` 返回 200 + 正确 JSON
146+- `curl http://100.71.210.78:4317/robots.txt` 返回正确的 robots 内容
147+- 访问不存在的文件返回 404
148+
149+## 推荐验证命令
150+
151+- `cd /Users/george/code/baa-conductor-artifact-foundation && pnpm build`
152+- `cd /Users/george/code/baa-conductor-artifact-foundation && pnpm test`
153+- `curl http://100.71.210.78:4317/robots.txt`
154+- `curl http://100.71.210.78:4317/artifact/msg/test.txt`
155+
156+## 执行记录
157+
158+> 以下内容由执行任务的 AI 填写,创建任务时留空。
159+
160+### 开始执行
161+
162+- 执行者:
163+- 开始时间:
164+- 状态变更:`待开始` → `进行中`
165+
166+### 完成摘要
167+
168+- 完成时间:
169+- 状态变更:`进行中` → `已完成`
170+- 修改了哪些文件:
171+- 核心实现思路:
172+- 跑了哪些测试:
173+
174+### 剩余风险
175+
A tasks/T-S040.md
+162, -0
  1@@ -0,0 +1,162 @@
  2+# Task T-S040:Artifact 接入指令执行主链路
  3+
  4+## 状态
  5+
  6+- 当前状态:`待开始`
  7+- 规模预估:`M`
  8+- 依赖任务:`T-S039`
  9+
 10+## 直接给对话的提示词
 11+
 12+读 `/Users/george/code/baa-conductor/tasks/T-S040.md` 任务文档,完成开发任务。
 13+
 14+如需补背景,再读:
 15+
 16+- `/Users/george/code/baa-conductor/plans/ARTIFACT_STATIC_SERVICE.md`
 17+
 18+## 当前基线
 19+
 20+- 仓库:`/Users/george/code/baa-conductor`
 21+- 分支基线:`main`(T-S039 合并后)
 22+- 提交:`<T-S039 合并后的提交>`
 23+
 24+## 分支与 worktree(强制)
 25+
 26+每个任务必须使用独立的分支和 worktree,禁止直接在 main 上修改,禁止多个任务共用同一个 worktree。
 27+
 28+- 分支名:`feat/artifact-pipeline`
 29+- worktree 路径:`/Users/george/code/baa-conductor-artifact-pipeline`
 30+
 31+开工步骤:
 32+
 33+1. `cd /Users/george/code/baa-conductor`
 34+2. `git worktree add ../baa-conductor-artifact-pipeline -b feat/artifact-pipeline main`
 35+3. `cd ../baa-conductor-artifact-pipeline`
 36+4. 在这个 worktree 目录里开发,不要回到主仓库目录
 37+
 38+完成后合并步骤:
 39+
 40+1. 在 worktree 里提交所有变更
 41+2. `cd /Users/george/code/baa-conductor`
 42+3. `git merge feat/artifact-pipeline`
 43+4. `git worktree remove ../baa-conductor-artifact-pipeline`
 44+
 45+合并冲突处理:
 46+
 47+1. 如果 `git merge` 报冲突,先 `git diff` 查看冲突文件
 48+2. 手动解决冲突后 `git add` 冲突文件
 49+3. `git merge --continue` 完成合并
 50+4. 不要用 `git merge --abort` 然后 force 覆盖
 51+
 52+## 目标
 53+
 54+将 artifact 数据库和静态文件生成接入 BAA 指令执行主链路:browser.final_message 到达时写入 messages 表,指令执行完成时写入 executions 表,回送 AI 时超长结果截断并附带 artifact URL。
 55+
 56+## 背景
 57+
 58+T-S039 建好了数据库和静态文件生成能力,但还没有接入实际的消息和指令流水线。本任务把这些能力串进 ingest → executor → delivery 主链路,让每条消息和每次执行都自动入库并生成可访问的 URL。
 59+
 60+## 涉及仓库
 61+
 62+- `/Users/george/code/baa-conductor`
 63+
 64+## 范围
 65+
 66+- ingest 收到 browser.final_message 时写入 messages 表 + 生成静态文件
 67+- executor 执行完成后写入 executions 表 + 生成静态文件
 68+- delivery 回送时:短结果内联全文 + URL,长结果截断前 500 字符 + URL
 69+- 阈值和摘要长度可配置
 70+- session 索引在写入时自动更新
 71+
 72+## 允许修改的目录
 73+
 74+- `/Users/george/code/baa-conductor/apps/conductor-daemon/src/instructions/` (ingest, executor, loop)
 75+- `/Users/george/code/baa-conductor/apps/conductor-daemon/src/artifacts/` (upload-session, delivery)
 76+- `/Users/george/code/baa-conductor/apps/conductor-daemon/src/index.ts` (注入 artifact store)
 77+- `/Users/george/code/baa-conductor/packages/artifact-db/` (如需补方法)
 78+
 79+## 尽量不要修改
 80+
 81+- `/Users/george/code/baa-conductor/packages/db/` (现有数据库不动)
 82+- `/Users/george/code/baa-conductor/plugins/` (插件不动)
 83+- `/Users/george/code/baa-conductor/apps/conductor-daemon/src/local-api.ts` (T-S039 已加路由)
 84+- `/Users/george/code/baa-conductor/apps/conductor-daemon/src/firefox-ws.ts` (尽量不动 WS 层)
 85+
 86+## 必须完成
 87+
 88+### 1. ingest 写入 messages 表
 89+
 90+- `browser.final_message` 到达 → 调用 `artifactStore.insertMessage()`
 91+- 全量保存 raw_text(永不截断)
 92+- 自动生成 summary(取前 500 字符)
 93+- 自动生成静态文件
 94+- 不阻塞现有 ingest 流程,写入失败只 log 不中断
 95+
 96+### 2. executor 写入 executions 表
 97+
 98+- 指令执行完成 → 调用 `artifactStore.insertExecution()`
 99+- 全量保存 result_data(永不截断)
100+- 自动生成 result_summary
101+- 自动生成静态文件
102+- 不阻塞现有执行流程,写入失败只 log 不中断
103+
104+### 3. 回送截断 + URL 拼接
105+
106+- 配置项:`inlineThreshold`(默认 2000 字符)、`summaryLength`(默认 500 字符)
107+- 结果 ≤ 阈值:内联全文 + 末尾附 artifact URL
108+- 结果 > 阈值:前 N 字符 + `\n\n完整结果:{artifact_url}`
109+- URL 格式:`https://conductor.makefile.so/artifact/exec/{id}.txt`
110+- 配置通过环境变量或 conductor config 注入
111+
112+### 4. session 索引自动更新
113+
114+- 每次写入 message 或 execution 时,自动 upsert 对应 session
115+- session 按 (platform, conversation_id) 去重
116+- 更新 last_activity_at、message_count、execution_count
117+- 生成 `state/artifacts/session/latest.txt`(最近 20 个活跃 session)
118+
119+## 需要特别注意
120+
121+- 写入 artifact 数据库和生成静态文件不能阻塞指令执行主链路
122+- 如果 artifact 写入失败(磁盘满、权限问题),只 log 错误,不影响正常执行和 delivery
123+- 截断阈值和摘要长度必须可配置
124+- 回送给 AI 的 URL 必须是 exact URL(完整路径),不能让 AI 自己拼
125+- 所有开发必须在 worktree 中进行,不要在主仓库目录修改代码
126+
127+## 验收标准
128+
129+- AI 发送含 baa 指令的消息 → messages 表有记录 + 静态文件存在
130+- 指令执行完成 → executions 表有记录 + 静态文件存在
131+- 短结果(< 2000 字符)回送时包含完整内容 + artifact URL
132+- 长结果(> 2000 字符)回送时只有前 500 字符 + artifact URL
133+- `curl https://conductor.makefile.so/artifact/exec/{id}.txt` 返回完整执行结果
134+- sessions 表自动更新,`latest.txt` 包含最近活跃会话
135+- artifact 写入失败时不影响正常指令执行
136+
137+## 推荐验证命令
138+
139+- `cd /Users/george/code/baa-conductor-artifact-pipeline && pnpm build`
140+- `cd /Users/george/code/baa-conductor-artifact-pipeline && pnpm test`
141+- 实际跑一轮 BAA 指令闭环,检查 `state/artifacts/` 目录下是否生成了文件
142+- `curl https://conductor.makefile.so/artifact/session/latest.txt`
143+
144+## 执行记录
145+
146+> 以下内容由执行任务的 AI 填写,创建任务时留空。
147+
148+### 开始执行
149+
150+- 执行者:
151+- 开始时间:
152+- 状态变更:`待开始` → `进行中`
153+
154+### 完成摘要
155+
156+- 完成时间:
157+- 状态变更:`进行中` → `已完成`
158+- 修改了哪些文件:
159+- 核心实现思路:
160+- 跑了哪些测试:
161+
162+### 剩余风险
163+
A tasks/T-S041.md
+158, -0
  1@@ -0,0 +1,158 @@
  2+# Task T-S041:Artifact 查询路由与会话索引
  3+
  4+## 状态
  5+
  6+- 当前状态:`待开始`
  7+- 规模预估:`S`
  8+- 依赖任务:`T-S039`
  9+
 10+## 直接给对话的提示词
 11+
 12+读 `/Users/george/code/baa-conductor/tasks/T-S041.md` 任务文档,完成开发任务。
 13+
 14+如需补背景,再读:
 15+
 16+- `/Users/george/code/baa-conductor/plans/ARTIFACT_STATIC_SERVICE.md`
 17+
 18+## 当前基线
 19+
 20+- 仓库:`/Users/george/code/baa-conductor`
 21+- 分支基线:`main`(T-S039 合并后)
 22+- 提交:`<T-S039 合并后的提交>`
 23+
 24+## 分支与 worktree(强制)
 25+
 26+每个任务必须使用独立的分支和 worktree,禁止直接在 main 上修改,禁止多个任务共用同一个 worktree。
 27+
 28+- 分支名:`feat/artifact-query-routes`
 29+- worktree 路径:`/Users/george/code/baa-conductor-artifact-query-routes`
 30+
 31+开工步骤:
 32+
 33+1. `cd /Users/george/code/baa-conductor`
 34+2. `git worktree add ../baa-conductor-artifact-query-routes -b feat/artifact-query-routes main`
 35+3. `cd ../baa-conductor-artifact-query-routes`
 36+4. 在这个 worktree 目录里开发,不要回到主仓库目录
 37+
 38+完成后合并步骤:
 39+
 40+1. 在 worktree 里提交所有变更
 41+2. `cd /Users/george/code/baa-conductor`
 42+3. `git merge feat/artifact-query-routes`
 43+4. `git worktree remove ../baa-conductor-artifact-query-routes`
 44+
 45+合并冲突处理:
 46+
 47+1. 如果 `git merge` 报冲突,先 `git diff` 查看冲突文件
 48+2. 手动解决冲突后 `git add` 冲突文件
 49+3. `git merge --continue` 完成合并
 50+4. 不要用 `git merge --abort` 然后 force 覆盖
 51+
 52+## 目标
 53+
 54+在 conductor HTTP server 上新增消息、执行记录和会话的查询路由,供管理用途和内部调用。
 55+
 56+## 背景
 57+
 58+T-S039 建了数据库,T-S040 接入了写入。但目前只能通过静态文件访问单条记录,还缺少列表查询、筛选和分页能力。本任务补齐查询路由。
 59+
 60+## 涉及仓库
 61+
 62+- `/Users/george/code/baa-conductor`
 63+
 64+## 范围
 65+
 66+- 新增 6 个查询路由
 67+- 支持分页和筛选
 68+- 注册到 `/describe` 和 `/v1/capabilities`
 69+
 70+## 允许修改的目录
 71+
 72+- `/Users/george/code/baa-conductor/apps/conductor-daemon/src/local-api.ts` (加路由)
 73+- `/Users/george/code/baa-conductor/packages/artifact-db/` (如需补查询方法)
 74+
 75+## 尽量不要修改
 76+
 77+- `/Users/george/code/baa-conductor/apps/conductor-daemon/src/instructions/` (T-S040 的范围)
 78+- `/Users/george/code/baa-conductor/plugins/`
 79+- `/Users/george/code/baa-conductor/packages/db/`
 80+
 81+## 必须完成
 82+
 83+### 1. 消息查询路由
 84+
 85+- `GET /v1/messages` — 消息列表
 86+  - 查询参数:`platform`、`conversation_id`、`limit`(默认 50)、`offset`(默认 0)
 87+  - 按 `observed_at` 倒序
 88+  - 返回 JSON 数组,每条包含 id, platform, conversation_id, role, summary, observed_at, artifact_url
 89+- `GET /v1/messages/{id}` — 单条消息详情
 90+  - 返回完整 JSON(含 raw_text)
 91+
 92+### 2. 执行记录查询路由
 93+
 94+- `GET /v1/executions` — 执行记录列表
 95+  - 查询参数:`message_id`、`target`、`tool`、`limit`(默认 50)、`offset`(默认 0)
 96+  - 按 `executed_at` 倒序
 97+  - 返回 JSON 数组,每条包含 instruction_id, message_id, target, tool, result_ok, result_summary, executed_at, artifact_url
 98+- `GET /v1/executions/{id}` — 单条执行详情
 99+  - 返回完整 JSON(含 result_data)
100+
101+### 3. 会话查询路由
102+
103+- `GET /v1/sessions` — 会话索引
104+  - 查询参数:`platform`、`limit`(默认 20)、`offset`(默认 0)
105+  - 按 `last_activity_at` 倒序
106+- `GET /v1/sessions/latest` — 最近活跃会话
107+  - 返回最近 10 个活跃 session + 每个 session 的最近消息和执行 URL
108+
109+### 4. 注册到 describe 和 capabilities
110+
111+- 所有新路由在 `/describe/business` 中可发现
112+- 在 `/v1/capabilities` 中注册为 `kind: "read"`
113+
114+## 需要特别注意
115+
116+- 这些路由是只读查询,不需要 auth token
117+- 返回的 artifact_url 必须是 exact URL(包含完整域名和路径)
118+- `publicBaseUrl` 从 conductor 配置中获取
119+- 列表查询不返回 raw_text / result_data 完整内容(太大),只返回 summary + artifact_url
120+- 所有开发必须在 worktree 中进行,不要在主仓库目录修改代码
121+
122+## 验收标准
123+
124+- `curl http://100.71.210.78:4317/v1/messages` 返回 JSON 数组
125+- `curl http://100.71.210.78:4317/v1/messages?platform=claude&limit=10` 筛选正常
126+- `curl http://100.71.210.78:4317/v1/messages/{id}` 返回完整消息
127+- `curl http://100.71.210.78:4317/v1/executions` 返回 JSON 数组
128+- `curl http://100.71.210.78:4317/v1/sessions/latest` 返回最近会话索引
129+- `/describe/business` 包含新路由
130+- `/v1/capabilities` 包含新路由
131+
132+## 推荐验证命令
133+
134+- `cd /Users/george/code/baa-conductor-artifact-query-routes && pnpm build`
135+- `cd /Users/george/code/baa-conductor-artifact-query-routes && pnpm test`
136+- `curl http://100.71.210.78:4317/v1/messages | jq .`
137+- `curl http://100.71.210.78:4317/v1/sessions/latest | jq .`
138+- `curl http://100.71.210.78:4317/describe/business | jq .`
139+
140+## 执行记录
141+
142+> 以下内容由执行任务的 AI 填写,创建任务时留空。
143+
144+### 开始执行
145+
146+- 执行者:
147+- 开始时间:
148+- 状态变更:`待开始` → `进行中`
149+
150+### 完成摘要
151+
152+- 完成时间:
153+- 状态变更:`进行中` → `已完成`
154+- 修改了哪些文件:
155+- 核心实现思路:
156+- 跑了哪些测试:
157+
158+### 剩余风险
159+
A tasks/T-S042.md
+184, -0
  1@@ -0,0 +1,184 @@
  2+# Task T-S042:D1 异步适配器与同步队列
  3+
  4+## 状态
  5+
  6+- 当前状态:`待开始`
  7+- 规模预估:`M`
  8+- 依赖任务:`T-S039`(需要表结构,但代码可并行开发)
  9+
 10+## 直接给对话的提示词
 11+
 12+读 `/Users/george/code/baa-conductor/tasks/T-S042.md` 任务文档,完成开发任务。
 13+
 14+如需补背景,再读:
 15+
 16+- `/Users/george/code/baa-conductor/plans/ARTIFACT_STATIC_SERVICE.md`
 17+- `/Users/george/code/baa-old-files/baa/baa-server/lib/d1-client.js`(旧版 D1 适配器参考)
 18+
 19+## 当前基线
 20+
 21+- 仓库:`/Users/george/code/baa-conductor`
 22+- 分支基线:`main`
 23+- 提交:`6ea34e2`
 24+
 25+## 分支与 worktree(强制)
 26+
 27+每个任务必须使用独立的分支和 worktree,禁止直接在 main 上修改,禁止多个任务共用同一个 worktree。
 28+
 29+- 分支名:`feat/d1-async-adapter`
 30+- worktree 路径:`/Users/george/code/baa-conductor-d1-async-adapter`
 31+
 32+开工步骤:
 33+
 34+1. `cd /Users/george/code/baa-conductor`
 35+2. `git worktree add ../baa-conductor-d1-async-adapter -b feat/d1-async-adapter main`
 36+3. `cd ../baa-conductor-d1-async-adapter`
 37+4. 在这个 worktree 目录里开发,不要回到主仓库目录
 38+
 39+完成后合并步骤:
 40+
 41+1. 在 worktree 里提交所有变更
 42+2. `cd /Users/george/code/baa-conductor`
 43+3. `git merge feat/d1-async-adapter`
 44+4. `git worktree remove ../baa-conductor-d1-async-adapter`
 45+
 46+合并冲突处理:
 47+
 48+1. 如果 `git merge` 报冲突,先 `git diff` 查看冲突文件
 49+2. 手动解决冲突后 `git add` 冲突文件
 50+3. `git merge --continue` 完成合并
 51+4. 不要用 `git merge --abort` 然后 force 覆盖
 52+
 53+## 目标
 54+
 55+实现 TypeScript async 版本的 Cloudflare D1 适配器,以及本地 SQLite → D1 的异步同步队列。新建 D1 数据库,不复用旧版。
 56+
 57+## 背景
 58+
 59+旧版 baa-server 用 curl 同步调 D1 API,conductor 是 TypeScript 需要 async 版本。D1 作为分布式备份和跨设备访问层,本地 SQLite 先写不阻塞,D1 后台异步推送。
 60+
 61+## 涉及仓库
 62+
 63+- `/Users/george/code/baa-conductor`
 64+- `/Users/george/code/baa-old-files/baa/baa-server/lib/d1-client.js`(只读参考)
 65+
 66+## 范围
 67+
 68+- TypeScript async D1 客户端
 69+- 同步队列表(本地 SQLite)
 70+- 后台同步 worker
 71+- 环境变量配置
 72+
 73+## 推荐实现边界
 74+
 75+建议新增:
 76+
 77+- `packages/d1-client/` — 新 package
 78+  - `src/client.ts` — async D1 HTTP API 客户端
 79+  - `src/sync-queue.ts` — 同步队列管理
 80+  - `src/sync-worker.ts` — 后台同步 worker
 81+  - `src/types.ts` — 类型定义
 82+
 83+## 允许修改的目录
 84+
 85+- `/Users/george/code/baa-conductor/packages/` (新建 d1-client)
 86+- `/Users/george/code/baa-conductor/apps/conductor-daemon/src/index.ts` (启动 sync worker)
 87+
 88+## 尽量不要修改
 89+
 90+- `/Users/george/code/baa-conductor/packages/db/`
 91+- `/Users/george/code/baa-conductor/packages/artifact-db/` (T-S039 的范围)
 92+- `/Users/george/code/baa-conductor/plugins/`
 93+- `/Users/george/code/baa-conductor/apps/conductor-daemon/src/instructions/`
 94+
 95+## 必须完成
 96+
 97+### 1. D1 async 客户端
 98+
 99+- 参考旧版 `/Users/george/code/baa-old-files/baa/baa-server/lib/d1-client.js`
100+- 使用 `fetch`(不用 curl)调 Cloudflare D1 REST API
101+- 端点:`https://api.cloudflare.com/client/v4/accounts/{accountId}/d1/database/{databaseId}/query`
102+- 方法:`exec(sql)`, `prepare(sql).run(...params)`, `prepare(sql).get(...params)`, `prepare(sql).all(...params)`
103+- 所有方法返回 Promise
104+- 环境变量:`D1_DATABASE_ID`、`D1_ACCOUNT_ID`、`CLOUDFLARE_API_TOKEN`
105+- D1 未配置时,客户端返回 null(不报错),由调用方判断
106+
107+### 2. 同步队列
108+
109+- 本地 SQLite 新增 `d1_sync_queue` 表:
110+  ```sql
111+  CREATE TABLE IF NOT EXISTS d1_sync_queue (
112+    id INTEGER PRIMARY KEY AUTOINCREMENT,
113+    table_name TEXT NOT NULL,
114+    record_id TEXT NOT NULL,
115+    operation TEXT NOT NULL,      -- 'insert' | 'update' | 'delete'
116+    payload TEXT NOT NULL,        -- JSON
117+    created_at INTEGER NOT NULL,
118+    attempts INTEGER NOT NULL DEFAULT 0,
119+    last_attempt_at INTEGER,
120+    status TEXT NOT NULL DEFAULT 'pending'  -- 'pending' | 'synced' | 'failed'
121+  );
122+  ```
123+- 写入本地 artifact DB 后,自动往 sync_queue 插入一条待同步记录
124+- 提供 `enqueueSyncRecord()` 和 `dequeuePendingSyncRecords()` 方法
125+
126+### 3. 后台同步 worker
127+
128+- conductor 启动时启动 sync worker
129+- 定时扫描 `d1_sync_queue`,取 pending 记录批量推送到 D1
130+- 成功后标记 `status = 'synced'`
131+- 失败后增加 `attempts`,指数退避重试(1s → 2s → 4s → ... 最大 5 分钟)
132+- 连续失败 10 次后标记 `status = 'failed'`,不再重试
133+- D1 未配置时,worker 不启动(静默跳过)
134+- worker 异常不影响 conductor 主流程
135+
136+### 4. 建 D1 远程数据库
137+
138+- 提供建库脚本或说明文档
139+- 表结构与本地 artifact DB 完全一致(messages、executions、sessions)
140+- 不复用旧版 D1 数据库
141+
142+## 需要特别注意
143+
144+- D1 同步是可选的,D1 不可用时本地功能完全不受影响
145+- sync worker 不能阻塞 conductor 主线程
146+- 同步队列表放在本地 artifact.db 中(与 messages/executions 同库)
147+- 旧版 D1Client 用的是 `execSync`(curl),新版必须用 async fetch
148+- 所有开发必须在 worktree 中进行,不要在主仓库目录修改代码
149+
150+## 验收标准
151+
152+- D1 环境变量未设置时,conductor 正常启动,sync worker 不启动
153+- D1 环境变量设置后,sync worker 启动,定时扫描队列
154+- 本地写入 message 后,sync_queue 中出现 pending 记录
155+- sync worker 成功推送后,记录标记为 synced
156+- D1 不可达时,记录保持 pending,指数退避重试
157+- 连续失败超限后,记录标记为 failed
158+- sync worker 异常不影响 conductor 主进程
159+
160+## 推荐验证命令
161+
162+- `cd /Users/george/code/baa-conductor-d1-async-adapter && pnpm build`
163+- `cd /Users/george/code/baa-conductor-d1-async-adapter && pnpm test`
164+- 设置 D1 环境变量后启动 conductor,观察 sync worker 日志
165+
166+## 执行记录
167+
168+> 以下内容由执行任务的 AI 填写,创建任务时留空。
169+
170+### 开始执行
171+
172+- 执行者:
173+- 开始时间:
174+- 状态变更:`待开始` → `进行中`
175+
176+### 完成摘要
177+
178+- 完成时间:
179+- 状态变更:`进行中` → `已完成`
180+- 修改了哪些文件:
181+- 核心实现思路:
182+- 跑了哪些测试:
183+
184+### 剩余风险
185+
M tasks/TASK_OVERVIEW.md
+11, -6
 1@@ -33,13 +33,18 @@
 2 
 3 ## 当前活跃任务与优先级
 4 
 5-### P0(下一阶段主线)
 6+### P0(下一阶段主线:Artifact 静态服务)
 7 
 8-- **Artifact 静态服务**:[`../plans/ARTIFACT_STATIC_SERVICE.md`](../plans/ARTIFACT_STATIC_SERVICE.md)
 9-  - 所有消息和执行结果全量入库 + 生成静态 URL
10-  - AI 通过 fetch URL 获取完整内容
11-  - 跨会话接续
12-  - 分支:`feat/artifact-static-service`(待创建)
13+方案文档:[`../plans/ARTIFACT_STATIC_SERVICE.md`](../plans/ARTIFACT_STATIC_SERVICE.md)
14+
15+| 任务 | 标题 | 规模 | 依赖 | 状态 |
16+|---|---|---|---|---|
17+| [`T-S039`](./T-S039.md) | Artifact 基础层(DB + 静态文件 + HTTP 路由) | M | 无 | 待开始 |
18+| [`T-S040`](./T-S040.md) | Artifact 接入指令执行主链路 | M | T-S039 | 待开始 |
19+| [`T-S041`](./T-S041.md) | Artifact 查询路由与会话索引 | S | T-S039 | 待开始 |
20+| [`T-S042`](./T-S042.md) | D1 异步适配器与同步队列 | M | T-S039(可并行开发) | 待开始 |
21+
22+执行顺序:T-S039 先行 → T-S040 和 T-S041 可并行 → T-S042 独立
23 
24 ### P1(并行优化)
25