跳到主要内容

架构决策记录 — 2026-07-23

本文记录今日的架构调研结论、设计决策和实现产出。


事件:deepseek-lhh API key governor 故障

现象:今日 1092 个任务失败(过去1小时813失败、0完成),错误签名 "error result: success"

根因:deepseek-lhh API key 被 DeepSeek 侧 governor 拒绝(认证失败)。

处置

  1. 确认新 key 写入 DB(sk-8cb106e6...),直连 DeepSeek 测通
  2. 批量 reset:排除3条真实内容问题(iteration-limit / corpus-qc),reset 1004 条为 queued,81条超大书回 paused
  3. 验证:重排后3分钟内零新增 governor 失败,系统恢复

教训:模型层故障需要更快熔断——参考 litellm-thinking-400 事故(thinking-400 incident),1338 任务失败19小时无熔断的教训。


调研:grow 阶段上下文与 token 消耗

阶段执行机制确认

每个 grow phase 是独立 Claude Agent SDK 会话,上下文不跨 phase 共享。跨 phase 的状态桥是磁盘文件(GROW.md / grow_state.json / 页面文件)。

2026-08-01 更新

下面是当时旧 grow 流程的事实记录。Service 现已统一使用 Life step:不设置默认 max_turns,step 内按上下文窗口自动 compact,step checkpoint 后开启新 session, 不再用“600 turns + 同会话 resume”管理长任务。详见 生命周期执行、模型路由与并发

同一旧 phase 内曾有两种续跑机制(均延续同一会话,上下文累积):

  • max_turns 续跑(已废弃):跑满600轮未收尾 → resume=session_id 续同一会话
  • verify-at-exit 补写(旧流程):phase 收尾验收发现缺产物 → resume 补写一次

语料加载:已经是按需检索,非预加载

结论doc_final.md(可达 13MB+)不会被整份读入上下文

引擎通过 corpus_search.py + pn-source.json 实现按需检索:

  • NEW1 建页时调 corpus_search.py "{实体名}" --max 10,只返回10段命中文本(~1K)
  • pn-source.json 是预建的段落索引,查找速度快
  • 建页 max=10(不是 20,20 是选页阶段用的)

影响:语料侧已优化到位,"语料读取是 token 黑洞"的假设错误,无需继续在此方向优化。

真正的 token 消耗来源

来源量级可优化
GROW.spec 当前 phase 段(phase 2 约950行)Sub-stage 化可降
pages.json 反复加载(全量719K,1442页)改用 pages.lite.json 可省350K/轮
多轮 resume 上下文累积大书最痛Sub-stage 化切断
corpus_search 多次调用已优化

优化机会:pages.json → pages.lite.json(未实施)

调研发现 pages.lite.json(347K)已经存在且含查重/wikilink 所需全部字段(type/label/aliases/path),但 spec 里所有查重调用都用 pages.json(719K)。

切换收益:1442页大书 phase 2 后期,每轮 pre-flight + 查重调用省约350K,几百轮累计巨大。

决策:未实施,待后续 RFC 推入引擎层。


调研:多 agent 架构现状

三层 agent 架构(均已存在)

层1 — job 级并行:调度器同时运行多个 wiki job,互不干扰。

层2 — 会话内 Task fan-out

  • 每个 grow/butler 会话 allowed_toolsTask
  • MEMEX_MAX_SUBAGENTS=4 控制并发上限
  • subagent_model 支持子 agent 使用不同(cheaper)模型
  • 当前 spec 主动选择串行(NEW1 spec 明确"禁止并行"),Task 工具虽开放但未 fan-out

层3 — 监工 supervisor:独立 LLM 判定层,带防抖和审计的护栏执行。

grow 串行建页的原因(推测)

grow spec 选择串行建页(非 Task fan-out)可能的原因:

  1. 质量可控:逐页串行便于保持"每句有据"铁律一致性
  2. 写冲突:并行写 pages.json 可能导致注册表冲突
  3. 历史决策,尚未有 RFC 评估 fan-out 的可行性

决策:fan-out 建页是潜在优化方向,但需 RFC 论证,本次不实施。


设计与实现:幻觉检测模块

背景

引擎 W7 幻觉控制框架(H1-H5)设计完整,但执法工作散落:

  • H1 出处核验(W7)已实现但只在 butler 会话内手动触发
  • H2-H5 全部未实现
  • Harness 侧的确定性检测器(HCK14/20/9)没和 W7 分层对齐
  • 没有自动触发机制

关键设计决策

决策1:Harness 侧执法,引擎零改动

信号来源:引擎已写的 logs/butler/actions.jsonl(每次 NEW1/RCH 建页后记录)。 Harness 通过 watermark 机制增量读取,不依赖引擎推送通知。

决策2:异步队列,不阻塞主流程

NEW1 建页完成后立刻继续建下一页,幻觉检测异步处理。队列攒批(默认5页),由 scheduler_ticksweep_hallucin_queue 后台线程触发。

决策3:确定性优先,LLM 仅处理灰色地带

coverage < 0.1   → 确定性错误,直接标红(0 token)
0.1~0.3 → UNCERTAIN,进 LLM deep queue(按需)
coverage ≥ 0.3 → 通过(0 token)

大量明显幻觉(coverage 极低)被免费抓住,LLM 只处理真正模糊的案例,节省90%+ 以上的检测 token。

决策4:修复任务直接用引擎 gene 代码

RepairWriter 写入 queue.md P2 时使用引擎认识的 gene 代码(FIX9-quote-attribution-auditCOR9-offline-citation-integrity 等),butler 直接执行,无需额外映射层。

实现产出

新增文件:

src/memex/hallucin/
├─ __init__.py
├─ models.py # PendingItem / ScanFinding / DeepPendingItem / SweepResult
├─ queue.py # HallucinQueue + HallucinDeepQueue
├─ scanners.py # CitationScanner + PnScanner + Quo23Scanner + ScannerRegistry
├─ sweep.py # HallucinSweep(run / run_deep / verify_repaired)
└─ repair.py # RepairWriter

src/memex/agent/hallucin.py
config/harness/hallucin-sweep/SKILL.md

集成改动:

  • api/scheduler.py:新增 sweep_hallucin_queue(),挂入 scheduler_tick

后续待办

事项优先级
真实 wiki 上跑第一次扫描,验证 coverage 阈值是否合理(0.1 / 0.3 可能需调参)P0
H2-H5 gene 补全(引擎侧 RFC)P1
pages.json → pages.lite.json 切换(引擎侧 RFC)P1
grow sub-stage 化(大书 phase 2 context 优化)P2
fan-out 建页 RFC(Task 工具并行评估)P3