baa-conductor

git clone 

commit
6a3d654
parent
9bad42f
author
im_wower
date
2026-03-29 20:52:33 +0800 CST
docs: add BUG-026 and BUG-027 reports
3 files changed,  +221, -0
A bugs/BUG-026-artifact-repo-root-fallback-broken.md
+110, -0
  1@@ -0,0 +1,110 @@
  2+# BUG-026: `/artifact/repo/:repo_name` 根路径不会落到默认 `log.html`
  3+
  4+> 提交者:代码核对 + 公网实测
  5+> 日期:2026-03-29
  6+
  7+## 现象
  8+
  9+当前 stagit 仓库静态页的显式文件路径可正常访问,但 repo 根路径不会按设计落到默认 `log.html`:
 10+
 11+- `GET /artifact/repo/baa-conductor/log.html` 返回 `200 text/html`
 12+- `GET /artifact/repo/baa-conductor` 返回 `404 application/json`
 13+
 14+这意味着用户或 AI 只拿到 repo 根 URL 时,不能直接进入仓库首页,必须显式补上 `/log.html`。
 15+
 16+## 触发路径
 17+
 18+```text
 19+GET /artifact/repo/:repo_name
 20+-> route matcher 先命中 /artifact/:artifact_scope/:artifact_file
 21+-> 走通用 artifact read
 22+-> 读取 artifacts/repo/:repo_name 普通文件
 23+-> 文件不存在
 24+-> 404
 25+```
 26+
 27+而不是:
 28+
 29+```text
 30+GET /artifact/repo/:repo_name
 31+-> 命中 /artifact/repo/:repo_name/*
 32+-> repo handler 把空 wildcard fallback 为 log.html
 33+-> 返回 stagit 首页
 34+```
 35+
 36+## 根因
 37+
 38+根因已经明确:
 39+
 40+- `LOCAL_API_ROUTES` 里通用路由 `/artifact/:artifact_scope/:artifact_file` 定义在 repo 专用路由 `/artifact/repo/:repo_name/*` 之前
 41+- `matchRoute()` 按声明顺序返回第一个匹配项
 42+- 对三段路径 `/artifact/repo/<repo>` 来说,前者已经完全匹配,后者根本没有机会执行
 43+- 因此 repo handler 中的默认值 `context.params["*"] || "log.html"` 只对 `/artifact/repo/<repo>/...` 生效,对根路径不生效
 44+
 45+这不是 stagit 生成问题,也不是公网部署问题,而是本地 API 路由分派顺序问题。
 46+
 47+## 复现步骤
 48+
 49+公网最小复现:
 50+
 51+```bash
 52+curl -sS -o /dev/null -w '%{http_code} %{content_type}\n' \
 53+  https://conductor.makefile.so/artifact/repo/baa-conductor/log.html
 54+
 55+curl -sS -o /dev/null -w '%{http_code} %{content_type}\n' \
 56+  https://conductor.makefile.so/artifact/repo/baa-conductor
 57+```
 58+
 59+2026-03-29 实测结果:
 60+
 61+- 第一条返回:`200 text/html; charset=utf-8`
 62+- 第二条返回:`404 application/json; charset=utf-8`
 63+
 64+本地代码最小核对点:
 65+
 66+- `apps/conductor-daemon/src/local-api.ts`
 67+- 通用 artifact 路由先于 repo 路由定义
 68+- `matchRoute()` 采用 first-match 行为
 69+- `handleArtifactRepoRead()` 里虽然实现了 `log.html` fallback,但根路径走不到这里
 70+
 71+## 当前影响
 72+
 73+- repo 静态页不是完全不可用,因为显式 `/log.html` 可正常访问
 74+- 但“repo 根路径可作为稳定入口”这个语义当前不成立
 75+- 任何只拼出 `/artifact/repo/<repo>` 的调用方都会得到 404
 76+- 会影响 AI/脚本/人工直接把 repo 根 URL 当作首页入口的体验和可发现性
 77+
 78+## 修复建议
 79+
 80+### 方案 A(推荐)
 81+
 82+调整路由优先级,让 `/artifact/repo/:repo_name/*` 在通用 artifact 路由之前匹配。
 83+
 84+这样最直接,也与现有 fallback 设计一致。
 85+
 86+### 方案 B
 87+
 88+保留当前顺序,但让 `matchRoute()` 对“更具体的静态段更多”的路由优先。
 89+
 90+这更通用,但复杂度高于当前问题本身。
 91+
 92+### 方案 C
 93+
 94+单独增加一个显式根路径路由 `/artifact/repo/:repo_name`,直接映射到 `log.html`。
 95+
 96+可以修问题,但会让 repo 路由定义分裂成两条。
 97+
 98+## 严重程度
 99+
100+**Medium**
101+
102+repo 静态浏览功能本身可通过显式 `/log.html` 使用,不是全量不可用;但默认首页入口失效,且与当前代码中的 fallback 意图不一致。
103+
104+## 发现时间
105+
106+`2026-03-29 by Codex`
107+
108+## 备注
109+
110+- 同一时间点公网已确认 `https://conductor.makefile.so/artifact/repo/baa-conductor/log.html` 正常
111+- 本 bug 只指向 repo 根路径 fallback 失效,不指向 stagit 内容生成失败
A bugs/BUG-027-startup-plugin-diagnostic-events-lost-before-ws-open.md
+109, -0
  1@@ -0,0 +1,109 @@
  2+# BUG-027: 插件启动期诊断事件会在 WS 建立前丢失,阻塞 `logs/baa-plugin` 排障链路
  3+
  4+> 提交者:代码核对
  5+> 日期:2026-03-29
  6+
  7+## 现象
  8+
  9+当前 `logs/baa-plugin/YYYY-MM-DD.jsonl` 被设计成 Firefox 插件诊断的统一落点,但插件冷启动、插件重载或页面首次注入时,最早一批关键事件可能完全不会进入 conductor:
 10+
 11+- `page_bridge_ready`
 12+- `interceptor_active`
 13+- 其他依赖页面刚加载时立即发送的诊断事件
 14+
 15+结果是:
 16+
 17+- 插件后续若成功连上 WS,后面的诊断日志能看到
 18+- 但最关键的“页面桥接是否成功注入”“page-interceptor 是否已激活”这批启动期证据会静默缺失
 19+- 当当前排障路径依赖 `logs/baa-plugin/` 判断注入链路时,会出现“没有日志,不知道是没注入还是只是太早发了”的盲区
 20+
 21+## 触发路径
 22+
 23+```text
 24+刷新 ChatGPT / Claude / Gemini 页面
 25+-> content-script / page-interceptor 刚加载即发送 page_bridge_ready / interceptor_active
 26+-> controller 这时尚未 connectWs() 或 WS 仍未 open
 27+-> wsSend() 直接返回 false
 28+-> 事件无重试、无排队、无本地缓冲
 29+-> conductor 侧 logs/baa-plugin/ 看不到这批启动期日志
 30+```
 31+
 32+## 根因
 33+
 34+根因基本确认:
 35+
 36+- content-script 会在加载后立即发送 `page_bridge_ready`
 37+- page-interceptor 会在激活后立即发送 `interceptor_active`
 38+- controller 直到初始化尾部才调用 `connectWs()`
 39+- `wsSend()` 在 socket 未连接时直接返回 `false`
 40+- `plugin_diagnostic_log` 没有补发、排队或本地缓存机制
 41+
 42+因此,所有发生在 WS 建立之前的诊断事件都会被静默丢弃。
 43+
 44+## 复现步骤
 45+
 46+这是一个很短的时序问题,最小复现依赖真实 Firefox 插件环境:
 47+
 48+1. 启动 conductor,确保会写 `logs/baa-plugin/`
 49+2. 重载 Firefox 插件或冷启动浏览器
 50+3. 刷新一个 AI 页面,例如 ChatGPT
 51+4. 观察页面控制台可看到 `content_script_loaded` / `interceptor_active`
 52+5. 再查看 conductor 的 `logs/baa-plugin/YYYY-MM-DD.jsonl`
 53+
 54+预期:
 55+
 56+- 应能看到 `page_bridge_ready`
 57+- 应能看到 `interceptor_active`
 58+
 59+当前高概率实际情况:
 60+
 61+- 若事件发生在 WS `open` 之前,这两条日志不会出现在 `logs/baa-plugin/`
 62+- 后续较晚产生的日志可能正常出现,造成“部分有日志、最早证据缺失”的假象
 63+
 64+## 当前影响
 65+
 66+- 直接影响当前依赖 `logs/baa-plugin/` 排查插件注入、桥接就绪、SSE 拦截起点的问题
 67+- 当问题恰好发生在页面刚加载或插件刚重载阶段时,conductor 侧日志失去最关键证据
 68+- 这不是普通信息缺失,而是会阻塞“确认 page-interceptor / content-script 是否启动成功”这条诊断路径
 69+- 对正常业务请求不一定构成功能性故障,但对当前诊断主流程是阻塞性的
 70+
 71+## 修复建议
 72+
 73+### 方案 A(推荐)
 74+
 75+在 controller 侧为 `plugin_diagnostic_log` 增加一个很小的启动缓冲队列:
 76+
 77+- WS 未 open 时先暂存在内存
 78+- `onopen` 后立即 flush
 79+- 队列限制条数,避免无上限积累
 80+
 81+### 方案 B
 82+
 83+在 content-script/page-interceptor 侧延迟发送首批诊断事件,等 controller 与 WS 建立后再发。
 84+
 85+这个方案实现简单,但会把可靠性依赖到更多时序假设上。
 86+
 87+### 方案 C
 88+
 89+保留现有链路,但在 controller 与页面握手成功后主动补发一轮启动状态摘要。
 90+
 91+这样能补证据,但语义上不如真实事件直观。
 92+
 93+## 严重程度
 94+
 95+**High**
 96+
 97+这会直接阻塞当前 `logs/baa-plugin/` 诊断链路最重要的一段:页面启动与注入时序。功能本身不一定坏,但排障会失真。
 98+
 99+## 发现时间
100+
101+`2026-03-29 by Codex`
102+
103+## 备注
104+
105+相关代码位置:
106+
107+- 启动期事件发送:[content-script.js](/Users/george/code/baa-conductor/plugins/baa-firefox/content-script.js#L888)
108+- 启动期事件发送:[page-interceptor.js](/Users/george/code/baa-conductor/plugins/baa-firefox/page-interceptor.js#L228)
109+- WS 未连通时直接丢弃:[controller.js](/Users/george/code/baa-conductor/plugins/baa-firefox/controller.js#L4003)
110+- controller 在初始化尾部才开始连 WS:[controller.js](/Users/george/code/baa-conductor/plugins/baa-firefox/controller.js#L7322)
M bugs/README.md
+2, -0
1@@ -13,6 +13,8 @@ bugs/
2 
3 ## 待修复
4 
5+- `BUG-026`:[`BUG-026-artifact-repo-root-fallback-broken.md`](./BUG-026-artifact-repo-root-fallback-broken.md)
6+- `BUG-027`:[`BUG-027-startup-plugin-diagnostic-events-lost-before-ws-open.md`](./BUG-027-startup-plugin-diagnostic-events-lost-before-ws-open.md)
7 - `OPT-002`:[`OPT-002-executor-timeout.md`](./OPT-002-executor-timeout.md)
8 - `OPT-003`:[`OPT-003-policy-configurable.md`](./OPT-003-policy-configurable.md)
9 - `OPT-004`:[`OPT-004-final-message-claude-sse-fallback.md`](./OPT-004-final-message-claude-sse-fallback.md)