# 架构评审输入包 · dsh-auto-memory（三层记忆 / RAG 检索层 / Karpathy 式 wiki 白板）

> **本文件是给外部评审 Agent 的输入包。** 读者假定完全不了解本项目上下文，因此全文自包含、不引用「上文」「之前的讨论」。
> **建立**：2026-09-14。**作者口径**：如实陈述现状、已拍板的待改进项与固有缺陷；**不含架构建议**（建议由外部 Agent 给）。
> **证据等级标记**（每处数字/行号都带其一）：
> - 【已核实】= 本次实读代码/实跑测试确认；
> - 【据文档】= 来自仓库内规范文档（本次实读该文档，但未独立复核其结论）；
> - 【据日志】= 来自当日工作日志；
> - 【推测】= 推断，未验证。
> **脱敏**：本文件不含任何令牌、cookie、邮箱、私有服务器地址；用户主目录一律写作 `~`（如 `~/.dsh/memory`）。
> **图例**：`~` = 用户主目录。所有相对路径以仓库根为基准。

---

## 一、一页速读

**项目是什么。** dsh-auto-memory 是给 DSH（DeepSeek Harness）用的**记忆插件**：它把「用户级记忆 / 项目笔记 / 当日日志 / 反思 / 白板」等多来源文本，自动抽取、压缩、并在每一轮对话里**自动注入**回上下文，使模型跨会话记住用户的事实、决策与偏好。零第三方运行时依赖（Node ESM；另有一个 Python 端侧语义 worker，可选）。仓库名 dsh-auto-memory，许可证见 `LICENSE`。

**现在在哪一步。** 项目已把「三层记忆架构（Tier-0 常驻目录 / Tier-1 L0 摘要 / Tier-2 原文块，OpenViking 式）」做完并**自验收已过**（C1–C7 全部施工完成，详 §4）。当前处于最艰难的一步：**RAG 检索层 + Karpathy 式 wiki（白板自我维护）的算法改造**。截至本文件，**算法改造尚未开工**（C 线未启动），只完成了「立规」（`SEMANTIC-ARCHITECTURE-SPEC.md` **v2**）与「白板格式契约」（`WB-FORMAT-CONVENTION.md` v1）【据文档】。

**最想问外部 Agent 的 3 个问题（完整清单见 §9）：**
1. 这套「**push 为主 + pull 为辅 + 兼容档检索路径零 LLM**」的定位，在**两档用户**（最优档=作者自用 / 兼容档=普通用户）下分别对不对？**分档边界是否应该这样划？**
2. 正确的目标架构应该是什么形状？**相对现状的最小改动**是什么？
3. 我们已定的规范条款 S1–S10 / 契约项 C1–C7 里，**哪些定错了、哪些缺判据、哪些定得不可判定**？按什么顺序补才不返工？
4. **（补充）两档共用的最小契约**是什么？哪一层一旦分档就会破坏这个共用契约？

---

## 二、用户画像与不可谈判约束（**最重要的一节；不知道这节会给出违背约束的建议**）

### 2.1 分档口径（不要把它读成「按最省设计」）

| 档 | 是谁 | 设计目标 | 现状 |
| --- | --- | --- | --- |
| **最优档（首要用户，就是项目作者本人）** | 开发者本人，重度档 | **以最优为目标**：愿意承担更重的算法、更重的本地模型、更长的注入预算，换检索质量 | 正在使用 **Python 语义引擎（BGE-M3 档）**【据日志】 |
| **兼容档（第二目标，发布给普通用户）** | 轻度用户：弱设备、不愿多花 token、不想跑端侧大模型 | **优雅降级**：同一套架构必须能在弱设备上跑通 | 默认走 JS 端 `multilingual e5` 档【据日志】 |

**正确表述是「最优优先 + 分档兼容」，而不是「轻度用户优化」。**
「兼容」的准确含义是 **约束「降级路径必须存在」**，而**不是**「按最省的那条路来设计目标形态」。

### 2.2 不可谈判约束（逐条）

1. **两档共用同一套接口与判据。** 切换只换**引擎与预算**，**不改契约形状** —— 这正是三层接口已冻结（Tier-0 / Tier-1 / Tier-2）的原因。（规范条款 = S9.3）
2. **最优档（作者自用）**：可用 Python BGE-M3；可用更重的算法与更大的注入预算；**允许**「在检索路径引入 LLM」的方案被提出，但**每条必须同时给出**：成本（谁付费）+ 门控条件 + 无 LLM 时的降级路径（规范条款 = S9.2，三件套缺一不采纳）。
3. **兼容档（发布给普通用户）**：必须能在**弱设备 + 零额外 LLM token + 端侧小模型或纯词法**下工作；常驻目录（Tier-0）在这一档承担主要「免检索」价值（规范条款 = S9.1）。
4. **禁止把架构设计成只有最省的那一条路。** 任何「只能在轻档跑通」的设计都要标注为**降级形态**，不得当成目标形态（规范条款 = S9.4）。
5. **双引擎是 OR 关系**：JS `multilingual e5` **或** Python `BGE-M3`，**切换即整库重建**（两个向量空间混排即错误结果）。
6. **白板不建状态机**：白板是视图层，状态归记忆条目（`layer` + `status` 三值）；只在「写入」一个门设防。
7. **不搬第三方代码**（可借范式，不复制实现）。
8. **注入预算可配**：`injectBudgetChars` 是配置项，当前默认 **2000 字符**（`lib/index.js:217`）【已核实】。

> **给外部 Agent 的提示**：`injectBudgetChars` 默认值今天刚从 1600 调到 2000，原因是 Tier-0 常驻目录不能在原预算内「免费」塞入（原式会把证据段从约 275 字符挤到约 174）【已核实，`lib/index.js:213-217` 注释】。历史文档中出现的 `4800` 是**旧默认值**，本次实读代码是 **2000**。

---

## 三、成本模型：「谁付费」（**同步自 `SEMANTIC-ARCHITECTURE-SPEC.md` §7 v2**）

**判据不是「RAG vs 长上下文」，而是「谁付费」—— 而且必须分档回答。**

> **口径说明（重要，避免误读）**：SPEC §7 的 **v1** 版本是按「轻度用户」写的成本对照表，并把「检索路径零 LLM 调用」写成**全项目硬约束**（S9，MUST）。**v2 已更正为分档口径**（§7 重写 + S9 拆成 S9.1–S9.4），本节搬的是 **v2** 的内容。我们不再把「兼容档的约束」当作全项目的目标形态。

**两个替代方案都成立，但各带隐含前提**（均已核验，见 SPEC 附录 F）：

| 替代方案 | 真实主张 | 隐含前提 | 对最优档 | 对兼容档 |
| --- | --- | --- | --- | --- |
| **LLM Wiki**（Karpathy） | 传统 RAG 的病是**没有知识积累**：每次查询都从零重新发现。改为让 LLM 渐进维护一份持久 wiki（实体页/概念页/交叉引用/矛盾标注/综合结论），靠 `index.md` + `log.md` 导航 | 写入侧与维护侧**由 LLM 长期承担**；原文明确说在「约 100 份资料、数百页」规模下**可避开嵌入式 RAG 基础设施** | ✅ 可用：查询侧多花 token 换整合质量 | ⚠️ 写入侧 token 可接受（可模板化），但查询侧仍要 LLM 读页 → 只能作**可选增强** |
| **Grep agentic**（Claude Code） | 「早期版本用了 RAG + 本地向量库，很快发现 **agentic search 更好**」；「模型驱动的 glob 和 grep 打败了一切」；GrepTool 默认只回文件名（控信息量）、`head_limit` 250 防淹没 | **每轮多轮 LLM 工具调用**（token 乘数）+ 语料是**精确 token 可匹配**的（代码/路径/标识符） | ⚠️ 可作**补充臂**（多轮 token 付得起） | ❌ 多轮即乘数；且自然语言记忆**没有可 grep 的字面** |

**成本对照（结论表，v2 原文口径）：**

| 路线 | 谁付费 | 最优档（首要用户） | 兼容档（第二目标） |
| --- | --- | --- | --- |
| 长上下文 / 全灌 | **贵侧（token）**：每轮 token ∝ 语料规模 | ⚠️ 注入预算（`injectBudgetChars` 默认 **2000** 字符，可配）是硬约束 | ❌ 这一档正是 token 敏感 |
| Grep agentic | **贵侧（token）**：每轮多次 LLM 调用的乘数 | ⚠️ 可作补充臂 | ❌ 最贵的一档 |
| LLM Wiki | **贵侧（token）**：写入/维护侧 LLM token | ✅ 可上（写入已模板化） | ⚠️ 可用，但必须模板化写入 |
| **本地检索（本项目主线）** | **设备侧（算力）**：一次性索引 + 每轮端侧嵌入，0 token | ✅ 主线，**允许在检索路径叠加 LLM 增强**（按 S9.2 带三件套） | ✅ 唯一完全契合的一档 |

**本项目的选择（SPEC §7 v2 要点）**：吸收 LLM Wiki 的「索引即自然语言」（Tier-0 目录 + L0 摘要 = 该方案的 `index.md`）；吸收 agentic 的「要不要搜由智能判断」，**默认**判断交给本地线性分类器（fv2，0 token）；**成本按档分配** —— 兼容档拒绝路径上调用 LLM（S9.1），最优档不拒绝但每条重方案要付清三件套（S9.2）。

> 💡 **请外部 Agent 判断的设计问题（不是请它替我们裁判自我矛盾）**：
> 1. **分档边界应该这样划吗？** 我们是按「引擎档 + 预算」划的（最优档 = Python BGE-M3 + 可申请 LLM 重方案；兼容档 = 端侧 JS e5 + 零额外 LLM token），两档共用同一套接口与判据（S9.3）。**这条分界线划在引擎上对不对？还是应该划在别处（预算 / 用户显式开关 / 功能面）？**
> 2. **兼容档「降级路径必须存在」这一条硬含义够不够？** 还需要哪些可判定的硬要求（例如冷启动上限、单轮延迟上限、磁盘/内存占用上限），才能让「兼容」这个词可验收？
> 3. **S9.2 的三件套（成本 + 门控 + 降级路径）作为「允许更重方案」的准入条件，是不是正确的门槛形状？** 有没有更好的门槛（例如要求先有离线对照实验、或要求先证明降级路径等价）？

---

## 四、现状（已建成部分，带可核验证据）

### 4.1 三层结构 + 注入侧接线

| 层 | 内容 | 实现文件（实读） | 预算 |
| --- | --- | --- | --- |
| **Tier-0** | 常驻目录（每条约 1 行：标题 · 一句结论 · `layer` · `status` · 日期），**每轮都注入** | `lib/tier0-catalog-pre.js`（导出 `buildTier0CatalogPre`、`buildTier0CatalogFromTextPre`、`allocateTier0QuotaPre`、`renderCatalogLinePre`、`estimateTokensPre`）【已核实】 | ≤ `B0` = 800 token（上限硬编码）；实际默认 `tier0MaxTokens` = **400**（`lib/index.js:224`）【已核实】 |
| **Tier-1** | L0 摘要（每条 ≤ `L1` = 140 字，`K` = 8） | `lib/l0-extract-pre.js`（`buildL0IndexPre` / `classifyLayerPre` / `isCurrentPre`；`L0_LAYERS` 五值 / `L0_STATUSES` 三值）【已核实】 | ≤ 140 字 × 8 |
| **Tier-2** | 原文块（`chunkId = hash(记忆ID, 记录摘要, 序号)`） | `python/m7_embedding_pre_v1.py:75` `chunk_id_for`【已核实】 | 单块 ≤ `B2` = **2400** 字（代码真值 `TIER_BUDGET_PRE_V1.B2`，`lib/tier-layer-inject-pre.js:36`）。契约文内旧写法 `2000` 与实际不一致 → **本轮已统一到 2400**（SPEC §0.2）。 |

注入侧装配：`lib/tier-layer-inject-pre.js`（导出 `composeTieredInjectionPre` / `decideTierGatePre` / `collectDegradationsPre` / `buildTier1SectionPre` / `buildTier2SectionPre` / `tierLayerAccountLinePre` / `estimateTierTokensPre`；`TIER_BUDGET_PRE_V1` / `TIER_MARK_PRE_V1` / `TIER_LAYER_ORDER_PRE_V1` = `['project','whiteboard','user','reflection','log']`）【已核实】。

### 4.2 已建成的能力清单（含断言数与施工项号）

| 施工项 | 内容 | 断言数 | 证据等级 |
| --- | --- | --- | --- |
| **C1** | 抽取层补 `layer` + `status` | 21 | 据文档；**本次实跑 `smoke-test-l0-layer-pre.mjs` = pass 21 / fail 0** 【已核实】 |
| **C2** | 召回返回带 `layer/status` + 检索侧过滤（不变式 I5） | 21 | 据文档；**本次实跑 `smoke-test-layer-filter-pre.mjs` = pass 21 / fail 0** 【已核实】 |
| **C4** | Tier-0 目录生成器（每条 1 行，≤ `B0`，按优先级 + 配额裁剪） | 33 | 据文档；**本次实跑 `smoke-test-tier0-catalog-pre.mjs` = pass 33 / fail 0** 【已核实】 |
| **C7** | 注入块可见性：块内 `Score: 0.xx (rank n/m)` + reason 串带 `intent/dense/margin` | 29 | 据文档；**本次实跑 `smoke-test-tail-score-visible-pre.mjs` = pass 29 / fail 0** 【已核实】 |
| **C3** | 接线 `l0-index-pre.js`（L0 自己的向量索引，增量），显式落 layer/status 两列 | —— | 据文档 |
| **C5** | 注入层：Tier-0 常驻 + 闸门下探 + per-layer 配额 + I7 降级标注 | 83 | 据文档；**本次实跑 `smoke-test-c5-tier-inject-pre.mjs` = pass 83 / fail 0**【已核实】（该套件曾因 `tier0MaxTokens` 断言写 800 而报红 1 条，已按「400 = 默认值 / 800 = `B0` 硬上限」更正为 400） |
| **C6** | 三层验收套件（每条能力一个「能失败」的断言） | 122 | 据文档；**本次实跑 `smoke-test-three-layer-pre.mjs` = pass 122 / fail 0**【已核实】（该套件曾因断言 `l0IndexEnabled: false` 而报红 1 条，已随「默认开」口径更正为 `true`） |

**关于 C5/C6 曾经的那两条失败（已修正，留作口径漂移的案例）：** 两条**报红原因不同**，不是同源 ——
- **C6 的红** = `l0IndexEnabled` 口径漂移：`smoke-test-three-layer-pre.mjs:300` 断言源码里必须出现字面量 `l0IndexEnabled: false`，而 `lib/index.js:416` 现为 `l0IndexEnabled: true`（注释写明「2026-09-14 用户裁定：默认 true」）→ **测试断言没跟上代码**，已改断言。
- **C5 的红** = `tier0MaxTokens` 的「默认值 vs 上限」表述不清：`smoke-test-c5-tier-inject-pre.mjs:227` 断言源码里出现 `tier0MaxTokens: 800`，而实际默认是 **400**（800 是 `B0` 硬上限）→ **不是矛盾，是默认值与上限之别**，已改断言并补写口径。
两者**都属「代码/文档/测试断言三处口径漂移」**，都**不是**功能坏了。**本轮两条都已修正，两个套件现为全绿（83/0、122/0）**；并新增了机械守卫（`tests/smoke/smoke-test-doc-code-consistency-pre.mjs`：代码默认值 ↔ 文档「默认」标注，任一侧漂移即报红），防止同类漂移再次无人发现。【已核实】

### 4.3 真实环境注入实测样本（**这些是本项目最有说服力的证据**）

**样本 A（探针实测，来自当日工作日志）**【据日志】：
```
[Tier-0 常驻目录 · 指引层 · ≤B0=800 token(实计 234) · 9 条]
[层账] …
[降级] 空层：reflection、whiteboard
[闸门] 本轮无语义命中
```
位置确认：该段确实进 `<memory_system>` 块，且在日志段之前。

**样本 B（Tier-0 生成器对真实语料的实测）**【据日志】：
```
真实语料实测（用户级/项目笔记/当日日志/PLAN 四源全解析、0 跳过）：
候选 75 条、kept 13、tokens 788（保守口径）/ 398（仓库口径）≤ 800，
按优先级全落在 project 层（77 块吃满预算），同层日期倒序正确。
```

**样本 C（实时运行中的注入块，本次会话可见）**【已核实，直接摘录】：
```
[Tier-0 常驻目录 · 指引层 · ≤B0=800 token(实计 390) · 7 条]
[层账] project 4/14(裁10) · whiteboard 0(无数据) · user 3/36(裁33) ·
       reflection 0/1(裁1) · log 0/40(裁40) · 合计裁剪 84 条
[降级] log 层有 40 条候选但 0 条进目录（配额/预算裁剪）；需要时用 memory_search 下探该层
[降级] reflection 层有 1 条候选但 0 条进目录（配额/预算裁剪）
[降级] 空层：whiteboard（本轮该层无数据可注入，非静默丢弃）
[降级] 语义索引未就绪（sync-in-progress）· 本轮降级为词法命中 + 常驻目录，未静默丢弃注入
[闸门] 本轮无语义命中（no-hit）→ 仅目录层，未下探 Tier-1/Tier-2
```

**样本 C 的三点读数（重要）**：
1. **最有价值的一层反而被裁掉**：`log` 层 40 条候选**全部**被裁；`project` 只进 4/14。目录里剩的是「结论」，但**决策过程全在 log 层**。
2. **语义臂仍在降级中**：`语义索引未就绪（sync-in-progress）` —— 说明 miv 全量重嵌问题在实时环境**仍在发生**（§7-①）。
3. **降级标注确实在工作**：I7（不静默降级）已落地，这是本轮最实的收获之一。

**样本 D（C7 钉子：重启后实测）**【据日志】：
```
重启后第二轮实测：注入块 Score 行严格降序（C7 钉子通过）；
同批注入 reason 为 intent=1.00 dense=0.00，候选全部来自词法臂、稠密臂零贡献。
```
→ 即：**「看得见相似度」已达成，但「稠密分本身是 0」** —— 语义臂虽已恢复接线，实际未贡献候选（根因未定，§10 未确认项）。

### 4.4 「全量回归」这一门的真实状态（发布前置门）

- **开发树**：`node tools/run-smoke.mjs --timeout=60000`，**79 套件 PASS 79 / FAIL 0 / TIMEOUT 0，总耗时 ≈149s**【据实测，2026-09-14 收尾】。（更早的「77 套件 0 失败」引自工作日志；卡死套件已定案修复，见 §7-⑥。当晚套件数 78→79（新增 1 个解耦回归套件）并要求两个 15s 负例，故耗时高于上午的 117.5s。）
- **发布树（无 `-pre` 后缀）**：有**一条套件按设计恒失败** —— `smoke-test-water-hard-trigger-pre.mjs` 的守卫断言绑定开发树导入路径；此现象在纯净基线同样复现、非本次引入，且 `tests` 不入包【据日志】。
- **口径结论**：**「77 套件 0 失败」只对开发树成立**；不能写成「全部通过」。
- ✅ **开发树当前 0 条已知失败**：§4.2 里 C5/C6 曾经各红 1 条（口径漂移），本轮**已修正**，两个套件实测 **83/0、122/0**【已核实】。此外**本轮新增 1 个套件**（`smoke-test-doc-code-consistency-pre.mjs`，代码↔文档默认值一致性守卫），故套件总数为 **78**（§4.4 首条的"77 套件"是**新增之前**的口径）。

---

## 五、现状（薄弱 / 草台部分）

### 5.1 RAG 只有雏形（逐条现状）

| # | 雏形处 | 现状 | 证据等级 |
| --- | --- | --- | --- |
| 1 | **查询侧加工** | **三项全无**：无查询改写、无 multi-query、无 HyDE。现在直接把原始段文本送去检索 | 据文档（SPEC S2） |
| 2 | **精排** | **无独立精排级**。融合序直接当最终序；现有「精排」实为 fv2 决策承担「注不注入」，不负责排序 | 据文档（SPEC S4） |
| 3 | **Tier-2 实践形态** | 实际只是「**更长的摘录**」—— 受激活候选 20–480 字限制，取整篇原文仍走 `expand` / `memory_read_pre` | 据日志（C5 交付记录） |
| 4 | **Python 档闸门** | **Python 档激活帧不带 query**，故其闸门**只能开到 tier1**，开不到 tier2 | 据日志 |
| 5 | **索引身份** | 索引**按层各一份**（`l0-index-pre` 每次只接受单一 layer），**而非单份索引** | 据日志 |
| 6 | **概览层** | 从约 90 字的 L0 **一步跳到原文全文**，中间「概览层」不存在 | 据文档（契约 §4.4 判定「本数据下不需要」，条件是单块 > 5000 字符才需要） |
| 7 | **评估** | 只有**词法基线**（3 条样本：L0 top-1 命中 1/3、top-5 命中 2/3；命中原因全是词法、0 条带语义分；观察到单字母 token 污染 `词法×3(agent,检索,a)`）；正式实验（12 条样本）**待跑** | 据文档 |
| 8 | **增量与新鲜度** | 无块级增量、无差量同步、无写后防抖；写入即触发全量重嵌（§7-①） | 据文档 + 已核实 |

### 5.2 白板（Karpathy wiki 层）目前只有一份格式约定

**这就是作者所说的「草台班子白板版」目前的全部家当** —— `docs/internal/WB-FORMAT-CONVENTION.md` v1，**零代码**，只有格式与写入契约【据文档】：

| 约定 | 内容 | 实现状态 |
| --- | --- | --- |
| 锚点契约 | 每张卡标题下方必须跟 `<!-- memory:mem_<32hex> -->`，id = `mem_` + `sha256(workspaceKey + '\u0000' + 页面相对路径 + '\u0000' + 卡片标题)` 前 32 位 | ❌ **无实现**（无校验器） |
| 索引派生 | `index` 由页面**派生**（链接 + 一句话 + `layer`/`status`），不许手抄 | ❌ 无实现 |
| 写入门 | **只做一件事**：重写前后比对卡片集合；卡片不得凭空消失 | ❌ 无实现 |
| 人机分区 | `<!-- model -->` / `<!-- user -->` 两区永不互相覆盖 | ❌ 无实现 |
| lint | 零 token 四类（孤立 / 陈旧 / 被提及却无独立卡 / 缺交叉引用）+ 需 LLM 一类（矛盾检测，**必须手动触发**） | ❌ **无 lint 实现**；清单只写在文档里 |
| 答案归档回流 | 结论必须能一键沉淀为白板卡 / 记忆条目 / handoff 账本 | ⚠️ **半闭环**（只有记忆条目与 handoff 两条通道，白板卡通道缺）【据文档】 |
| 三页面时态 | PLAN 白板（现在时）/ handoff 账本（过去时）/ 笔记（累积时） | ✅ 文件已存在【据文档】 |

**白板相关的三条硬边界**（外部 Agent 不要建议违反）：不建状态机；不搬第三方代码（含 dsh-graph，只借范式）；不引入跨目标依赖图。

---

## 六、已拍板待改进项（逐卡清单）

**来源**：`docs/internal/TODO-GRAPH.html` 的 `DATA.items`（本次**逐卡实读**，位于该文件 `:145`–`:371`，共 **34 张卡片**【已核实】）。
**阶段**：阶段 0 已暂停（做完底层再拍板）/ 阶段 1 = 3.0 主轨（底层 · 语义 / 算法 / 实验）/ 阶段 2 = 3.0 主轨续 / 阶段 3、4 封存 / 阶段 5 待入池。
**归属标记**：`A` = 接口冻结线（C3/C5/C6）；`B` = 立规与审计线；`C` = 算法改造线（S1.3 → S5.3 → S2 → S4）；`—` = 不属本次攻关（前置 / 依赖 / 已封存）。

| # | 卡片 id | 标题 | 图内状态 | 阶段 | 归属 |
| --- | --- | --- | --- | --- | --- |
| 1 | `D1` | 会话检索口径：C + B（含丁组允许改字段） | ✅ 已拍板 | 阶段 1 | — （本攻关前置；依赖它才能跑检索） |
| 2 | `D2` | 【已暂停】白板路线：把看板 combine 进自己的白板 | 暂停（做完底层再谈） | 阶段 0 | — （关联 P1-6 界面层，封存） |
| 3 | `D3` | 【已暂停】WB-GRAPH 的 8 个拍板点什么时候拍 | 暂停（做完底层再谈） | 阶段 0 | — |
| 4 | `D4` | 记忆纠错两问 → 先按「默认可逆」实现 | 默认口径（可回退） | 阶段 1 | C（S5.2 配额 + S5.1 压缩，对应 P0-④d） |
| 5 | `D5` | 【已暂停】跨会话 / 跨 Agent 检索：路径 C 已定 | 已拍板 · 暂停（随大排期） | 阶段 3 | — |
| 6 | `P0-A` | 白板「接续」开关互锁 + 取消强制接续（成本） | 封存（3.1） | 阶段 3 | — |
| 7 | `P0-B` | 设置里 sub agent 的「模型 + 思考强度」选不动 | 封存（3.1） | 阶段 3 | — |
| 8 | `P0-1` | 解锁会话检索（可开工） | 待开工（口径已定） | 阶段 1 | — （前置：51 个阻塞文件；依赖 D1） |
| 9 | `P0-4` | 记忆增删 × 少重建：块级向量缓存 + 检索 fail-open | 待开工（约 1 天） | 阶段 1 | **C**（施工项 1 = S1.3） |
| 10 | `P0-4b` | supersede 改正语义（改正=新增声明，不物理删） | 待开工（约半天） | 阶段 1 | **C**（S1.3 后半） |
| 11 | `P0-4c` | 差量同步：upsert + tombstone | 待开工（约 1 天） | 阶段 1 | **C**（S1.3） |
| 12 | `P0-4d` | 注入压缩上限 + 可排除来源（坏记忆不再反复灌入） | 待开工（口径待 D4 确认） | 阶段 1 | **A/C**（S5.1 + S5.2，C5） |
| 13 | `P0-4e` | 索引同步防抖：持续写入会让语义索引永远不就绪（实测卡死 20 分钟） | 已实测复现 | 阶段 1 | **C**（施工项 2 = S5.3）+ 施工项 1 |
| 14 | `P0-2` | OpenViking 式三层补全（**阶段门**） | 施工完成（C1–C7 全 ✅；**待宿主重启后真实验收**） | 阶段 1 | **A**（全部 = C3/C5/C6） |
| 15 | `P0-3` | 分级精确检索：Tier-0 目录 → L0 摘要 → 原文 | 待开工（约 1 天） | 阶段 1 | **A**（C5 下探闸门）+ S5.2 |
| 16 | `P1-5` | 验收判据换代：能力可达性套件 | 待开工（约半天） | 阶段 2 | **A**（C6） |
| 17 | `P1-6` | 白板 combine：实时进展 + 全流程可视化 | 契约层已落地（B 线）；**界面层封存（3.1）** | 阶段 3 | **B**（契约层，= S10 / 白板六条）；界面层封存 |
| 18 | `P1-8` | procedural memory 重构（档着 3 条群反馈） | 封存（3.1） | 阶段 3 | — （属 ⑤晋升步，不在本攻关；依赖 P0-4b） |
| 19 | `P1-9` | 语义架构规范 v1（已立，**现为 v2**）：用规范 RAG 策略清单审计并约束检索 | 规范已立（v2）；**审计待跑** | 阶段 2 | **B**（本卡 = B 线全部：四线顺序 + S9 审计） |
| 20 | `CHK-1` | 记忆文件卫生：空行残留 / 标题层级 / 容量逼近上限 | 本机已复现（已清理一轮，机制待修） | 阶段 2 | **C**（与 S5.3 / 注入压缩相关；容量 94% → 写入被拒会打断链路） |
| 21 | `P1-14` | 语义臂会静默失效：miv 一变，0-1 相似度排序就消失 | 已实测复现（含根因） | 阶段 2 | **C**（施工项 1 + 2：块级缓存 + 显式降级标注） |
| 22 | `P1-15` | 注入层不是语义唤回：注入块里看不到 0-1 相似度 | 已修（待宿主重启验证） | 阶段 2 | **A**（C7 已落）；残留「注入层骨架未升级为 Tier-0 目录」归 P0-3 / C5 |
| 23 | `P1-16` | 三层检索的量化实验 | 词法基线已跑，待语义臂恢复后正式跑 | 阶段 2 | **B**（S7：E1/E3，两个实验） |
| 24 | `P2-7` | 跨 Agent 记忆入检索（外部文档 + 外部会话） | 待拍板 | 阶段 3 | — （依赖 P0-3；路径 C 分期） |
| 25 | `P2-8` | （已上移为 P1-⑧ · procedural memory 重构） | 见 P1-⑧ | 阶段 3 | — （占位卡，已并入 P1-8） |
| 26 | `P2-9` | 群反馈 / 日报 CI 的安全与运维收口 | 待确认 | 阶段 3 | — |
| 27 | `P2-10` | SCF 云函数 zip 重部署 | 待你操作 | 阶段 3 | — |
| 28 | `P2-11` | 日历换开源方案（自研太粗糙） | 待调研 | 阶段 3 | — |
| 29 | `P2-12` | 手机端远程控制：首次启动指引太大且关不掉 | 远期（随 UI 调整） | 阶段 3 | — |
| 30 | `A-1` | 大排期三件套（界面 / 文档 / 首页） | 推后 | 阶段 4 | — |
| 31 | `A-2` | 界面技术债：令牌层 / 组件层 / i18n / IA 重排 | 推后 | 阶段 4 | — |
| 32 | `A-3` | 文档体系：README 大改 / USER-GUIDE / 双语对账 / 27 张配图 | 推后 | 阶段 4 | — |
| 33 | `A-4` | 分发门面：npm 瘦身 / package.json 字段 / Pages / CHANGELOG 死链 | 推后 | 阶段 4 | — |
| 34 | `A-5` | 冷启动余项：向导兜底触发 / 幻觉 ON / 引擎步重试 / `welcomeTourEnabled` / 术语 Top5 | 推后 | 阶段 4 | — |

**关于卡片 id 的特别提醒**：图中有 **4 张卡的 id 字段不是连号** —— 分别是 **`CHK-1`**（= 图内编号 P1-⑬）、**`P1-14`**（= P1-⑭）、**`P1-15`**（= P1-⑮）、**`P1-16`**（= P1-⑯）。它们**不是** `P1-13/14/15/16` 的笔误，而是真实字段值【已核实】。请勿按连号跨卡引用。
**实际参与本攻关施工的卡片**（据 `RAG-KARPATHY-PROGRAM.md` §5 原文）：`P0-2 / P0-3 / P0-4 / P0-4b / P0-4c / P0-4d / P0-4e / P1-5 / P1-9 / CHK-1 / P1-14 / P1-15 / P1-16`（共 13 张）【据文档】。

---

## 七、固有缺陷与已知事故（附证据）

> 这一节是外部 Agent 最该看的部分：**这些都是有实测证据的真缺陷**，不是「待优化」。

### ① 语料身份 = 整份哈希 → 写一条记忆触发全库重嵌（**架构级根因**）

- 块 ID 已经是**内容寻址**：`chunk_id_for(memory_id, record_digest, ordinal)` → `'chk_pre_' + sha256('m7-chunk-pre-v1\0' + memory_id + '\0' + record_digest + '\0' + str(ordinal))[:32]`（`python/m7_embedding_pre_v1.py:75-78`）【已核实】。
- **但块 ID 不是缓存键**。索引身份是**整份语料哈希** `memoryIndexVersion`：`lib/index-sync-pre.js:62` 取该值、`:63` 只校验 `idx_pre_` 前缀，不匹配即 `{ ok:false, reason:'memoryIndexVersion' }`【已核实】。
- **后果**：任何细节改动 → miv 变 → **全量重发 + 全量重嵌**。在弱设备上表现为风扇、电耗、卡顿；在时序上表现为「索引追不上写节奏」（→ 见 ②）。
- **归属**：卡片 `P0-4/4b/4c/4e`、`P1-14`；规范条款 S1.2/S1.3。

### ② 索引未就绪曾**静默丢弃注入** → 「语义唤回突然消失」

- 现场：诊断日志从本地 07:43 到 08:01 持续刷 `ctx-host drop: index-not-ready:sync-in-progress`（`cv` 从 175 涨到 612，即**每轮都在换新语料版本、每轮都触发新一轮全量重建**），期间注入被**显式丢弃**【据文档/据日志】。
- 后果：语义唤回 packet 自 07:43:45 起停止注入；`recall` 也静默退化为纯词法，**不告诉调用方**【据日志】。
- 现况：已改为**降级但仍注入**（`index-not-ready:degraded:` + 显式 `[降级]` 行），见 §4.3 样本 C —— 这条已修复。【已核实，样本 C】

### ③ 不是「慢」，是「卡死」：worker CPU 增量 0.00s / 3s

- 决定性证据：worker 子进程 CPU 累计 659.4s，**3 秒采样增量 0.00s（在闲着）**；索引产物从 07:43 到 08:09 共 **26 分钟零更新**；而此前一次重建只花 **6 秒**（07:42:50 → 07:42:56）→ **慢不了 260 倍，是同步状态机卡死 / 任务被反复作废**。【据文档/据日志】
- 已排除的错误猜测：曾怀疑「两个 python worker 抢同一份索引」，实测为**父子结构**（一个逻辑 worker）【据文档】。

### ④ 水位 bug（**已由外部 PR 修复**）

- 根因：模型 id 字符类**不含斜杠** → provider 前缀式 id（形如 `deepseek/...`、`z-ai/...`）整行匹配失败 → 该模型的上下文窗口被**静默丢弃**并退化为 **131072**。
- 实测影响：真实窗口 **1,000,000** 的会话被按 131,072 当分母 → **水位放大 7.63 倍**（12.8% 显示成 98%）→ 未达 0.75 阈值即误弹接续确认卡。修复提交信息给出该数字。【据日志】
- 修复：外部 PR #31（作者 Minervaowl7），提交 2775567 改 `parseModelWindowsPre`。开发树本地同源 bug 已按同法移植修复，移植后水位三套件全绿（硬触发 44 / 步进 14 / 窗口 26）【据日志】。
- **遗留建议（尚未执行）**：现有水位窗口套件的 26 条断言**抓不住**这个 bug（fixture 用的都是非前缀式 id），应补一条**能失败**的回归断言（前缀式 id 必须取到真实窗口）【据日志】。

### ⑤ 「静默丢弃 / 静默降级」是本项目的**系统性风险模式**（已知几处）

| # | 位置 | 曾发生的静默行为 | 现状 |
| --- | --- | --- | --- |
| 1 | `lib/context-host-pre.js` 的 `index-not-ready` 分支 | 索引未就绪 → **丢弃整轮注入** | 已改为降级 + 显式标注【已核实，样本 C】 |
| 2 | Python worker 的三重过滤（`workspaceRef` + `scope` + `miv`） | miv 不匹配 → **返回空分**，调用方无从知晓 → 静默退化为纯词法 | 已加标注；根因（miv 全量重嵌）**未修** |
| 3 | 渲染层 `renderReferenceTail` | 候选分**算得出来但从不打印** → 看得见「要不要注入」，看不见「到底多像」 | C7 已修（增 `Score:` 行）【据文档/据日志】 |
| 4 | 水位解析 `parseModelWindowsPre` | 模型 id 不匹配 → **窗口静默丢弃** + 退化默认值 | 已由 PR #31 修复（§7-④） |
| 5 | 记忆文件容量门 | 容量逼近上限 → 写入被拒（**打断链路**，非静默但同样无预告） | `CHK-1` 待修；实测笔记容量 11,308 / 12,000 = **94%**【据文档】 |
| 6 | 测试运行器 | （见 ⑥）单套件忙等 → 全量回归**永不返回**，无告警 | **已修**（2026-09-14：护栏运行器 + 套件侧有界轮询；根因见 ⑥） |

**共性**：本项目倾向于用「丢弃 / 退化 / 沉默」来处理异常路径。规范里对应的治法是不变式 **I7**（必须显式降级标注，禁止静默丢弃）与条款 **S5.3 / S3.3**，但 I7 目前只在注入侧落地，**索引侧 / 解析侧 / 容量侧尚未统一收口**。

### ⑥ 全量回归**曾因单个套件忙等而永不返回**（根因已定案并**已修复**，2026-09-14）

- 现象【已核实，实测】：`tests/smoke/smoke-test-consolidate-isolation.mjs`（仅 **77 行**）出现挂钟约 **29 分钟**、累计 CPU 约 **18 分钟**的进程（**忙等**而非等 IO），且**存在并发实例**。
- 定位【**已定案**；由调试器取到闭环调用栈，非猜测】：**与锁无关** —— 早先「进程内锁在被测对象中断后不释放」的假设**已被证伪**。真因是两条叠加：
  1. **诊断通道（结论已按隔离实验修正）**：原先判断为「`uncaughtException` 处理器内 `console.error` 写已失效的 stdout/stderr → 同步抛 EPIPE → 自激」。**隔离实验证伪了这一步**：Node 的 console 写路径（`internal/console/constructor.js` 的 `kWriteToConsole` / `createWriteErrorHandler`）会临时挂 noop `'error'` 监听把写失败吞掉，故 `console.error` 对断管 EPIPE **天然免疫**（实测断管下 exit 0 / 2.3s / 78ms CPU，处理器只进入 1 次）；同一位置改用**裸 `stream.write`** 才真自激（10s 未退出、CPU 90% 单核、定时器仍活但进程永不自退）。因此「满核空转」这一半的**历史成因仍未定论**（不排除旧 Node 版本或另一条写路径），而「永不退出」这一半由第 2 条充分解释。装置与原始证据见 `artifacts/probe-epipe-selfignite.mjs`、`artifacts/probe-epipe-FINDINGS.md`、`artifacts/probe-epipe-runs/`。
     **追加加固（已实施 2026-09-14）**：诊断通道写路径改回 console（天然免疫）+ 保留 noop `'error'` 兜底 + `writableEnded` 检查三层并存；安全性不再单点依赖「监听器不被移除」。
  2. **定时器清理不可达**：三个定时器（重试 5 分钟 / 心跳 15 秒 / 通知 1 小时）只注册在 `ctx.effect` 的清理器里，而套件在断言失败后不再走到释放循环 → 定时器存活 → 事件循环**永不排空**。
  两条叠加 = **既不退出、又满核空转**。触发条件是一处约 24ms 的余量竞争。
- 影响：**「全量回归零失败」作为发布前置门不可靠** —— 门本身可能永远不返回。
- 修复（**已实施**）：①诊断通道三条约束（写前判 `destroyed/writableEnded/writable`、全程 try/catch + 同步重入闸、stdout/stderr 挂空 `'error'` 监听以吞掉写失败）；②三个定时器 `.unref()`（对齐 hub 定时器既有做法）；③套件侧固定睡眠改**截止时间轮询**，去重断言改用 diag 日志的「判定已发生」作肯定信号；④护栏运行器 `tools/run-smoke.mjs` 提供单套件超时（按进程树强杀后继续）。
- 实测：该套件单独运行 **exit 0 / 1.6s**（此前挂死）；全量 **PASS 79 / FAIL 0 / TIMEOUT 0，≈149s**（2026-09-14 收尾复测；较上午的 78 套件 / 117.5s，增量＝两个 15s 负例 + 新增 1 个解耦回归套件）。

---

## 八、现有规范本身（请外部 Agent 一并审）

三份规范 + 一份白板契约，构成目前的「规则层」。**我们邀请你审这些规则本身：哪里定错了 / 定漏了 / 定得不可判定。**

| 文件 | 它是什么 | 条款编号 | 关键内容 |
| --- | --- | --- | --- |
| `docs/internal/SEMANTIC-ARCHITECTURE-SPEC.md` | **语义/检索侧规范 v2**（v1→v2：§7 分档重写 + S9 拆条 + 数值口径统一） | **S1–S10** | S1 分块与增量（MUST）；S2 查询侧：改写/多查询/HyDE（SHOULD，**本仓最大空白**）；S3 混合臂 + 排名空间融合（MUST）；S4 精排（SHOULD）；S5 注入压缩/预算/降级（MUST）；S6 自适应检索决策（MUST，**本仓强项**）；S7 评估（MUST：没有实验就没有资格改算法）；S8 观测与再现（SHOULD）；**S9 成本（分档条款：S9.1 兼容档 MUST 零额外 LLM token / S9.2 最优档允许更重方案但须带「成本+门控+降级路径」三件套 / S9.3 两档共用同一套接口与判据 / S9.4 禁止把兼容档形态当目标形态）**；S10 wiki 层契约（MUST，六条：页面即语料 / 索引自动生成 / lint 补齐 / 不建状态机 / 答案归档回流 / 人机分区）。另设 §0.2「数值口径（代码真值）」表。 |
| `docs/internal/THREE-LAYER-CONTRACT.md` | **三层接口与预算契约 v2** | **I1–I7** + **C1–C7** | 预算：`B0` = 800 token、`L1` = 140 字、`K` = 8、`B2` = 2400 字；不变式 I1–I7（I5 = 非 current 条目在**检索与注入两处**被过滤；I7 = 缺数据必须显式降级标注）；施工项 C1–C7（断言数见 §4.2） |
| `docs/internal/WB-FORMAT-CONVENTION.md` | **白板格式约定 v1** | 六条 | 锚点契约 / 索引派生 / 写入门 / 人机分区 / lint 五类 / 答案归档（另含 6 条能失败的验收清单） |
| `docs/internal/RAG-KARPATHY-PROGRAM.md` | **攻关总细则**（不是新规范） | 下拆与判定 | 施工顺序、卡片隶属映射、不采纳清单、风险坑清单 |

**三份规范的效力关系**（原文）：SPEC 是上位规范；契约管接口与预算；白板约定管格式与写入；总细则只**下拆与判定**，**不新增条款、不改接口形状**，冲突以 SPEC 为准。【据文档】

### 8.1 我们**已经自己标注的**「不采纳项」（请审这个清单对不对）

1. **迭代式 RAG（多轮检索 / 自省循环）：不作为默认形态（两档皆然）。** 理由是每轮自动注入的场景下，多轮检索会把延迟与 token 乘 2 以上；「要不要检索」已由 S6（fv2 决策 + echo veto + 冷却）承担。**最优档若要把它当可选增强**，按 S9.2 带三件套后可以讨论。
2. **重排（S4）：先做近似级，cross-encoder 留给最优档。** 理由是候选池（`K`=8 / `B0`=800）与 S7 实验判据就绪前上重排，只增延迟而无从证明它比 RRF 融合序更好；判据就绪后 cross-encoder 作为最优档重方案上线（按 S9.2 标注成本），兼容档停在近似级。
3. **多引擎混排：禁止。** 双引擎是 OR 关系，两套向量空间混排即错误结果。
4. **Query 改写：兼容档不做 LLM 调用**（S9.1）；**最优档允许**，但要带三件套（S9.2：token 成本 + 触发门控 + 无 LLM 时的降级路径）。
5. **语义臂不可用时静默：不予采纳**（必须显式标注）。
6. **「不能跑通兼容档」的设计：不予采纳**（S9.4 的反面：任何新方案都必须证明降级路径仍然存在）。

### 8.2 规范自相矛盾（**已由我们自行修正**）＋ 仍需架构判断的**开放问题**

**（a）已修正项 —— 列在这里只为记录口径，不再请你裁判：**

| 项 | 旧状 | 统一后的值（**代码真值**） | 处置 |
| --- | --- | --- | --- |
| `B2` | 契约文内 **2000** 与 **2400** 并存 | **2400 字符**（`TIER_BUDGET_PRE_V1.B2`，`lib/tier-layer-inject-pre.js:36`）【已核实】 | 统一到 2400；SPEC §0.2 记为真值 |
| `injectBudgetChars` | 契约 §4.1 写 4800（旧默认值） | **默认 2000**（`lib/index.js:217`）【已核实】——**它是可配置项**，设置页可调 | 统一到 2000，并注明「可配置」 |
| `tier0MaxTokens` | 「400 与 `B0`=800 并存」曾被当作矛盾 | **默认 400；`B0`=800 是硬上限**（`lib/index.js:224` / `lib/tier-layer-inject-pre.js:33`）【已核实】 | **不是矛盾，是「默认值 vs 上限」之别**；同批写明 `tier0BudgetShare` 默认 **0.25** |
| `l0IndexEnabled` | 契约/图写「默认关」，代码为 `true` | **默认 `true`**（`lib/index.js:416`，2026-09-14 用户裁定）【已核实】 | 已统一（测试断言已改，契约/图由另一写者同步） |

> **我们把「措辞与数值对齐」从评审问题里撤掉了。** 理由：这些不需要架构判断，外部 Agent 的产能应该花在架构上，而不是替我们清理措辞。为防复发，已补两样机械保障：SPEC **§0.2 数值口径表**（每个数字都带代码出处）+ 守卫测试 `tests/smoke/smoke-test-doc-code-consistency-pre.mjs`（**代码默认值 ↔ 文档「默认」标注，任一侧漂移即报红**）。

**（b）仍然开放、确实需要架构判断的问题：**

1. **两档边界该划在哪里**（引擎档 / 预算 / 用户显式开关 / 功能面）？见 §3 设计问题 1。
2. **「降级路径必须存在」是否足以定义兼容档的可验收性？** 要不要补可行的硬指标（冷启动上限、单轮延迟上限、内存/磁盘占用上限）？
3. **S9.2 的三件套门槛形状对不对？** 是否应改成「先有离线对照实验再谈重方案」这类更强门槛？
4. **数值真值的归属**：现在真值在代码里，SPEC 与契约各自复述 → 这就是漂移的**结构性来源**。是否应该改成「单一数值源 + 文档生成/校验」？（我们的现状只见步就补一个守卫测试。）
5. **分档会不会隐性破坏「共用契约」？** 两档预算不同（引擎不同、注入预算不同）→ 截断行为与证据形态可能不同 → 模型实际看到的**注入块形状**可能不再一致。这算不算违反 S9.3（两档共用同一套接口与判据）？**如果算，正确的做法是固定形状、只缩放数量，还是明确接受形状差异？**

---

## 九、给外部 Agent 的提问清单（要它回答什么）

> **口径提醒**：本节只放**设计问题**。我们已经自行修正的措辞/数值问题（§8.2a）**不需要你裁判**；请把产能花在下面这些判断上。

1. 这套「**push 为主 + pull 为辅 + 兼容档检索路径零 LLM**」的定位对不对？在**两档用户**下**分别**对不对？有没有更优解？
2. **正确的目标架构应该是什么形状？相对现状的最小改动是什么？**
3. 请**分别**给出**最优档**与**兼容档**的架构建议，并明确指出**两档共用的最小契约**是什么（哪一层一旦分档就会破坏共用契约）。
4. 我们已定的 **S1–S10 / C1–C7 / 白板六条**里，**哪些是错的**？哪些**缺判据**（写成「声明了就算过」）？哪些**定得不可判定**？
5. **【分档设计问题】** 我们已把 §7 成本模型与 S9 改成**分档**（S9.1 兼容档 MUST 零额外 LLM token / S9.2 最优档允许更重方案但须带三件套 / S9.3 共用接口与判据 / S9.4 禁止把兼容档形态当目标形态）。**请判断这条分界线划得对不对**：是按**引擎档 + 预算**划，还是应该划在别处？**S9.2 的三件套是不是正确的准入门槛？**（不要评价我们过去的定调，只看现在这条线本身合不合理。）
6. RAG 雏形 → 可用检索层，**按什么顺序补**？我们排的是 **S1.3（块级增量）→ S5.3（降级标注）→ S2（查询侧加工）→ S4（精排）**，请评这个顺序（并说明每条服务哪一档）。
7. **白板（Karpathy wiki 层）接下来该怎么做，才不会变成「又一个草台」？**（现状：只有一份格式约定，零实现，见 §5.2。）
8. §7 的六条固有缺陷里，哪些是**架构根因**（必须改架构才能解决）、哪些只是局部 bug？
9. **数值真值该由谁拥有**：真值现在在代码里，两份规范各自复述 → 结构性漂移源。应该改成「单一源 + 生成/校验」，还是接受「代码为真 + 守卫测试」？（我们目前是后者。）

---

## 十、给它的输出要求（写进文档，作为**约束**）

1. **不要架构散文。** 每条建议必须写成**三件套**：
   **改哪个文件 / 哪一层 → 判定条件（一条「能失败的断言」）→ 成本归属（谁付费）。**
2. **每条建议必须标注它服务哪一档**（**最优档 / 兼容档 / 两档共用**）。**未标注的不计入。**
3. **不得违反 §2 的不可谈判约束。** 尤其：
   - 两档**共用同一套接口与判据**，切换只换引擎与预算，**不改契约形状**；
   - **禁止**给出「只能在轻档跑通」的设计然后当成目标形态（那只能作为**降级形态**被标注）；
   - **禁止**建议双引擎混排；**禁止**建议白板建状态机；**禁止**建议搬第三方代码。
4. **在检索路径上引入 LLM**：**最优档允许**该方案被提出，但每条必须同时给出**成本（谁付费）+ 门控条件 + 无 LLM 时的降级路径**；三者缺一不予采纳。**兼容档**的检索路径必须仍能在**零额外 LLM token + 弱设备**下工作。
5. **若你认为某条约束本身错了**（例如 §2.2-5 的 OR 双引擎、或 S9.1–S9.4 的分档边界），**必须单列一节论证**，不要在正文里顺手违反。
6. **判据必须能失败。** 不接受「声明了就算过」；每条判据要写成「若实现被改坏则报红」。
7. 引用本项目事实时，请区分**证据等级**（已核实 / 据文档 / 据日志 / 推测），**不要把你的推断写成我们的现状**。

---

## 十一、未确认事项（如实列出；不做无根据的补全）

以下内容**本次未独立复核**，报告中已按「据文档 / 据日志」标注，请外部 Agent 按较低置信度使用：

1. **全量回归已实跑（更新于 2026-09-14 收尾）**：`node tools/run-smoke.mjs --timeout=60000` → **79 套件 PASS 79 / FAIL 0 / TIMEOUT 0，≈149s**【据实测】。此前的 `77 套件 0 失败` 系引自工作日志【据日志】且当时**未复跑**——因已知有一个套件会忙等卡死；该套件根因已定案并修复（§7-⑥），本条为修复后的完整实测。**本次只对 §4.2 的逐项做了单独核验，全量表以本条为准；套件数当晚由 78 增至 79（新增解耦回归套件）。**
2. **C1 21 / C2 21 / C4 33 / C7 29 / C5 83 / C6 122 断言数**：口径来自契约文档与今日日志【据文档/据日志】。本次实跑其中 6 个套件：C1/C2/C4/C7 为 **21 / 21 / 15 / 29**（早前实跑，`smoke-test-l0-index-pre.mjs` 实测 15 断言；文档未给出 C3 断言数，故无法对账），C5/C6 为 **83 / 122（均 fail 0，本轮复跑）**【已核实部分】。
3. **Tier-2 实际形态**「只是更长的摘录（受激活候选 20–480 字限制）」：引自今日日志的交付记录【据日志】，本次未逐行核对 `activation-inbox-pre.js` 的 excerpt 长度上限。
4. **Python 档激活帧不带 query**：引自今日日志【据日志】，未自行核对 Python 侧代码。
5. **索引「按层各一份」**：引自日志【据日志】；本次已核实 `lib/l0-index-sync-pre.js` 导出 `l0IndexFileNamePre(workspaceKey, layer, chars)` —— **签名带 layer，与「按层各一份」一致**【已核实，推断部分标推测】。
6. **稠密臂零贡献（`dense=0.00`）的根因**：未定。文档记为「可能与 miv 未就绪 / 向量文件缺失同源」【据文档】，本次未追查。
7. ~~**`smoke-test-consolidate-isolation.mjs` 卡死根因**：调查进行中，**结论未定**~~ → **已定案并已修复（2026-09-14）**：挂死＝定时器清理只挂在 `ctx.effect`、套件断言失败后走不到释放链（已改 `.unref()`）；「满核空转」假设经隔离实验修正——只有**裸 `stream.write`** 会自激（`console` 写路径天然免疫），诊断通道已改回 console。**本条原有「结论未定」的写法已被证伪，请勿再引用**；详见 §7-⑥。
8. **§7-④ 水位 bug 的量化数字**（1,000,000 → 131,072 → 7.63 倍 → 12.8% 显示成 98%）：引自 PR #31 提交信息转述【据日志】，本次未读 PR 原文。
9. ~~**`B2` = 2000 / 2400 哪个是当前实现值**~~ → **已核实：`B2` = 2400**（`lib/tier-layer-inject-pre.js:36` `TIER_BUDGET_PRE_V1.B2`）；`B0` = 800（同文件 `:33`）。契约文内旧写法 2000 属待同步项（SPEC §0.2 记为真值）。**同批已核实**：`injectBudgetChars` = 2000（`lib/index.js:217`）、`tier0MaxTokens` = 400（`:224`）、`tier0BudgetShare` = 0.25（`:227`）、`tier0CatalogEnabled` = true（`:220`）、`l0IndexEnabled` = true（`:416`）【已核实】。
10. **白板 lint / 写入门 / 人机分区**有无任何部分实现：本次只读了 `WB-FORMAT-CONVENTION.md` 与 `docs/internal/` 文件清单，**未全仓搜索**相关实现；文中记为「❌ 无实现」是**据文档（文档自称零代码）**，非穷尽核实。

---

## 附：本文件的来源（可核验）

| 来源 | 用途 |
| --- | --- |
| `docs/internal/TODO-GRAPH.html` | §6 全部 34 张卡片的 id / 标题 / 状态 / 阶段（本次逐卡实读 `:145`–`:371`） |
| `docs/internal/SEMANTIC-ARCHITECTURE-SPEC.md` | §2 / §3 / §5 / §8 的条款与立场（S1–S10、§4 阶段门、§4.1 不采纳项、§7 成本模型、§8 wiki 层、附录 A–F） |
| `docs/internal/THREE-LAYER-CONTRACT.md` | §4 的预算与断言数、I1–I7、C1–C7 |
| `docs/internal/RAG-KARPATHY-PROGRAM.md` | §6 的卡片隶属映射、§9 的施工顺序与不采纳清单、风险坑 |
| `docs/internal/WB-FORMAT-CONVENTION.md` | §5.2 白板现状（锚点 / 索引派生 / 写入门 / 人机分区 / lint 五类 / 答案归档） |
| 代码：`lib/tier0-catalog-pre.js`、`lib/tier-layer-inject-pre.js`、`lib/l0-index-pre.js`、`lib/l0-index-sync-pre.js`、`lib/water-window-pre.js`、`lib/l0-extract-pre.js`、`lib/index.js`、`python/m7_embedding_pre_v1.py` | §4 的导出与默认值、§7-① 的 `chunk_id_for` 与 `memoryIndexVersion` |
| 当日工作日志（`~/.dsh/memory/workspaces/<工作区键>/2026-09-14.md`） | §4.3 注入实测样本、§4.4 回归口径、§7 的事故证据 |
| `tests/smoke/*.mjs`（本次实跑 6 个套件） | §4.2 的实测断言数、§4.2 末尾的失败条目 |
| `tests/smoke/smoke-test-c5-tier-inject-pre.mjs` / `smoke-test-three-layer-pre.mjs`（本轮复跑） | §4.2 的 C5/C6 现状（83/0、122/0）与 §8.2a 的口径漂移案例 |
| `tests/smoke/smoke-test-doc-code-consistency-pre.mjs`（**本轮新建**） | §8.2a 的机械保障（代码默认值 ↔ 文档「默认」标注） |
