# 2026-05-23 Agent健身房复盘
一句话概括:**这次发现的不是已经自动修复的问题,而是 5 类以后会反复浪费时间的操作摩擦 / 工具缺口。**
| 优先级 | 发现的问题 | 真实含义 | 计划怎么解决 |
| --- | --- | --- | --- |
| 1 | OpenRouter 图片生成排障还靠现场长等 | 同一把 key 下,一个图片模型 150/180 秒不返回,另一个 48.7 秒出图;没有预检器就会在 key、模型路由和解析器之间反复猜。 | 做 `openrouter_image_route_smoke.py`:先查 key/account,再逐模型测延迟和返回字段,输出 fallback 建议。 |
| 2 | 扩展预加载缺真实运行时 smoke | 单测和 build 都绿,但定时器曾挂在 popup 生命周期上,导致网页停留 60 秒也不会提前缓存。 | 给 Quiet Web Collector 加 Chrome runtime smoke:加载 unpacked extension,等 65 秒,不开 popup 也要看到 background pending/ready。 |
| 3 | Viva helper 源码、运行时和缓存契约容易漂移 | 源码测试通过不代表 17331 端口跑的是新代码;字段 prompt、LaunchAgent、旧缓存任一处漂移都会让 tooltip/Anki 字段退化。 | 做 `check_runtime_contract.py`:校验源码/runtime hash、plist 指向、旧进程、health、prompt 三字段和 refresh 缓存策略。 |
| 4 | Anki live deck 批量操作重复且风险高 | 昨天既删红旗卡、删整首歌,又批量升级两首歌的 Translation;每次都要手写查询、备份、复核和报告。 | 做 Anki batch runner:plan 驱动 dry-run/apply,强制 expected_count、exportPackage、postcheck 和 report。 |
| 5 | Electron 应用黑屏排障缺标准顺序 | KanBots 安装里出现 postinstall 慢下载、open folder 回退、黑屏、recent workspace 不自动恢复;需要区分依赖、主进程、renderer、bridge、业务 bootstrap。 | 沉淀 Electron bootstrap smoke:remote debugging + CDP 查 `#root`、preload bridge、bootstrap promise 和 openWorkspace。 |
## 下一步
| 顺序 | 先做什么 | 为什么 |
| --- | --- | --- |
| 1 | 先做 OpenRouter 图片链路预检器 | 它来自明确的 agent reflection,且昨天同一问题连续消耗 150/180 秒等待。 |
| 2 | 再做扩展后台预加载 smoke | 它能挡住 build 绿但真实 extension 生命周期错误的问题。 |
| 3 | 补 Viva helper 运行时契约检查 | Viva/Anki helper 当天多次暴露源码、运行时、缓存和字段契约漂移。 |
| 4 | 把 Anki live deck 批处理 runner 做成 plan 驱动 | 删除和批量更新都涉及真实学习资产,越早固化越能降低误删风险。 |
| 5 | 把 Electron bootstrap 诊断沉淀成 workflow | 价值高但频率略低,适合先写 checklist,再在下一次桌面 app 安装时验证。 |
## 一、候选详情
### 1.1 OpenRouter图片链路预检器
- 类型:`diagnostic-tool`
- 风险:`low`
- 摘要:该主题有效,片段显示问题不在本地前端同步卡死,而是在 OpenRouter 图片模型路由、provider 等待和响应解析之间缺少分层诊断。一次真实排障中,同一扩展 key 对不同图片模型表现完全不同,说明需要一个能先验证 key/account、再分模型探测图片生成、最后检查返回字段解析的预检器。
- 关键证据:
- `019e555c-b3b3-70e2-a5f3-92e723c5d73f`:真实图片请求已经发出超过 30 秒,还没返回。这说明至少不是本地前端卡死在同步代码里,当前瓶颈大概率在 OpenRouter/上游图片模型等待返回;我继续等到 150 秒超时,看它最终是成功还是 provider 超时。
- `019e555c-b3b3-70e2-a5f3-92e723c5d73f`:扩展 key 的 GPT Image 2 请求到 150 秒超时,没拿到任何 HTTP 错误体。为了把“key 不通”和“图片模型慢/卡住”拆开,我再用同一个扩展 key 做一个轻量 OpenRouter key/account 检查。
- 拟议改动:
- 新增工具入口:在 `/Users/bytedance/Documents/product-bu/scripts/openrouter_image_route_smoke.py` 增加 CLI,支持 `--key-source env|extension-config|literal`、`--models openai/gpt-5-image-mini,openai/gpt-5.4-image-2`、`--timeout-seconds 180`、`--prompt`,输出每个检查项的 JSON 结果和耗时。
- 明确输入来源:读取 `OPENROUTER_API_KEY` 或扩展本地配置中的 OpenRouter key;模型列表优先来自产品/扩展的 provider 配置,允许命令行覆盖;测试 prompt 使用固定小图请求,避免业务 prompt 干扰诊断。
### 1.2 扩展后台预加载运行时smoke
- 类型:`diagnostic-tool`
- 风险:`low`
- 摘要:这个主题有效:它暴露的是单元测试和构建都可能放过的浏览器扩展生命周期问题,页面已经停留 60 秒并不等于 popup 打开后一定有缓存。需要一个真实 Chrome extension runtime smoke,验证 content script、background service worker、popup 三者之间的预加载状态流转,避免再次把定时器挂到错误生命周期上。
- 关键证据:
- `019e53ea-b87d-79b0-bafa-080dc5b35f4c`:用户问:为什么我点开这,没看到已经缓存好的图片呢?截图里出现“正在生成”,说明点击时没有命中已完成缓存,或者预加载还没成功结束。
- `019e53ea-b87d-79b0-bafa-080dc5b35f4c`:根因倾向已经出来了:当前实现把“1 分钟后预加载”的定时器放在 popup/side-panel 打开后才启动。网页虽然已经开了一分钟,但如果刚点开扩展,缓存不可能提前存在。
- 拟议改动:
- 新增 `~/Documents/product-bu/obsidian/obsidian-clipper/scripts/smoke-scholar-preload.mjs`,复用现有 `scripts/smoke-auto-collector.mjs` 的 CDP 启动方式。工具入口:`npm run smoke:scholar-preload -- --wait-ms 65000 --mock-delay-ms 300`。输入来源:`dist/` unpacked extension、脚本内本地 HTML smoke page、脚本内 mock OpenRouter endpoint、写入 `chrome.storage.local` 的 `interpreter_settings.providers`。
- 核心检查步骤写进 `scripts/smoke-scholar-preload.mjs`:先 `npm run build:chrome`,启动带 `--load-extension=dist` 的临时 Chrome profile,打开 smoke page 但不打开 popup,等待超过 `SCHOLAR_NOTE_PRELOAD_DELAY_MS`,通过 service worker CDP 调 `chrome.runtime.sendMessage({action:'getScholarNotePreloadStatus', tabId})`,再打开 popup/触发 `getScholarNoteImage`。成功信号:popup 打开前状态已是 `pending` 或 `ready`,mock OpenRouter 请求数为 1,点击后复用同一个 `pageKey`;失败信号:70 秒后仍 `idle`、popup 点击才出现第一条请求、请求数变 2、或按钮长时间停在“正在生成”。
### 1.3 Viva helper运行时契约检查
- 类型:`diagnostic-tool`
- 风险:`low`
- 摘要:这个主题有效,不是噪音。片段显示 Viva helper 的异常反复出现在同一条链路:仓库源码、运行时副本、LaunchAgent 常驻进程、前端字段契约和缓存复用策略之间发生漂移。它适合沉淀成一键诊断工具,让 tooltip 或制卡结果异常时先确认“当前跑的代码”和“客户端复用逻辑”是否符合预期。
- 关键证据:
- `019e5410-efdf-7320-91e0-57366d2a4e0b`:helper 测试已全过,源码和运行时副本确实不一致。接下来把同一处提示词改动补到运行时 helper 文件,并重启/验证本机 helper 服务。
- `019e556b-9698-7e10-af1e-1b2ce6d76cd5`:监听进程确实是旧进程:它 6 小时前启动,命令指向运行时 helper,但 Python 已把旧代码载入内存。需要恢复并重启 LaunchAgent,验证 17331。
- 拟议改动:
- 新增诊断工具 `20-products/viva/30-rd/anki-local-extension/helper/tools/check_runtime_contract.py`。工具入口:`python helper/tools/check_runtime_contract.py --port 17331 --source helper/anki_concept_helper.py --runtime ~/Library/Application\ Support/VivaAnkiHelper/anki_concept_helper.py`。输入来源:仓库 helper 源码、运行时副本、`helper/launchd/com.bytedance.viva-anki-concept-helper.plist`、`~/Library/LaunchAgents/Anki导入助手.plist`、`lsof -nP -iTCP:17331 -sTCP:LISTEN`/`ps`、`GET /health`、可选 `POST /explain` fixture。核心检查:源码/runtime sha256 是否一致,LaunchAgent ProgramArguments 是否指向 runtime helper,监听进程启动时间是否早于 runtime 文件 mtime,17331 health 是否可用,`build_prompt` 是否同时包含 `conceptMeaningZh`/`tooltipExplanationZh`/`usageHintZh`,可选 live fixture 是否返回三字段。成功信号:所有 hash/path/process/health/schema 检查 PASS。失败信号:hash drift、old pid、plist path drift、health fail、缺字段或 live response 缺字段。落地路径:先只读诊断,输出明确修复命令;后续再加 `--fix-copy` 和 `--restart-launchagent` 显式参数。
- 补一份运行时契约文档 `20-products/viva/30-rd/anki-local-extension/helper/RUNTIME_CONTRACT.md`,写清源文件 `helper/anki_concept_helper.py`、运行时文件 `~/Library/Application Support/VivaAnkiHelper/anki_concept_helper.py`、端口 `127.0.0.1:17331`、LaunchAgent plist、日志路径和重启验收命令。把“源码测试通过不代表运行时已更新”作为固定排障检查项。
### 1.4 Anki live deck批处理助手
- 类型:`tool-upgrade`
- 风险:`medium`
- 摘要:这个主题有效:多个片段都在对 live Anki deck 做真实删除或批量字段升级,重复依赖实时查询、备份、精确过滤和复核归零。它不是噪音,而是一个已经跨 flag 删除、歌曲 tag 删除、歌词翻译升级复现的高风险高价值 workflow,适合沉淀成批处理 runner。
- 关键证据:
- `019e540b-7bbf-7482-9b71-448aedefeef1`:用户先问 flag1 红色卡有哪些,随后要求都删掉;执行流程是 live AnkiConnect 查询 8 张、导出两个受影响 deck 备份、删除 8 个 note、复核 flag:1 为 0。
- `019e5445-fe39-7973-9f28-6ec1c18b08be`:Run Wild 删除前实时确认英文歌词里有 37 张卡 / 37 个 note,导出英文歌词备份,只按 tag:run_wild 删除,并复核多个查询口径都为 0。
- 拟议改动:
- 在 /Users/bytedance/Documents/learning-bu/tools/anki_live_deck_batch_runner.py 新增批处理入口,支持 dry-run/apply 两阶段;输入为 YAML/JSON plan,字段包含 deck、query/tag、expected_note_count、backup_decks、operation(delete_notes/update_fields)、postcheck_queries。
- 在 /Users/bytedance/Documents/learning-bu/english/04-projects/anki-batches/templates/ 新增 delete_by_query.yaml 和 update_translation_by_tag.yaml,把 flag:1 删除、tag:run_wild 删除、mood/Someone You Loved 翻译升级沉淀成模板,并要求 expected_count 不匹配时失败退出。
### 1.5 Electron应用启动诊断流程
- 类型:`workflow-pattern`
- 风险:`low`
- 摘要:这个主题有明确价值:同一个 KanBots 安装/启动问题覆盖了 postinstall 下载、主进程状态、渲染层空白、bootstrap 行为和 workspace 打开验证。它适合沉淀成 Electron 应用启动 smoke 的标准流程,避免把慢下载误判成死锁,或把黑屏直接误判成 bundle/IPC 损坏。
- 关键证据:
- `019e554c-218d-7911-9dcc-4ab814978013`:安装 KanBots 时依赖下载后卡在 Electron postinstall,后续确认不是死锁,而是 Electron 正在下载 darwin-arm64 zip,链路较慢。
- `019e554c-218d-7911-9dcc-4ab814978013`:选择文件夹后 UI 回到 Open folder,没有进入看板;进入 workspace 后窗口变成空黑屏,主进程已创建 .kanbots 和 recents,但渲染层没有正常绘制。
- 拟议改动:
- 新增技能文件 `/Users/bytedance/.codex/skills/electron-app-bootstrap-smoke/SKILL.md`:记录 Electron postinstall 下载识别、主进程/renderer/preload 分层诊断、remote debugging port + CDP smoke、recent workspace/open folder 验证顺序。
- 在目标 Electron 仓库新增 `scripts/electron-bootstrap-smoke.mjs`:输入 app 启动命令、workspace 路径、remote debugging port;检查窗口 URL、`#root` 是否有子节点、preload bridge 是否存在、bootstrap promise 返回值、调用 openRecent/openWorkspace 后是否进入主界面。
## 二、输出文件
| 文件 | 用途 |
| --- | --- |
| `manifest.json` | 候选清单和审批状态 |
| `examples/` | 每个候选的 before/after 或诊断样例 |
| `approve.sh` | 本地标记某个候选 approved |