> **投喂方式**：本段须与 `_COMMON.md` 一并投喂。
> 依赖：无。**风险低、价值高，建议尽早做**（可与 P9 并行）。
> 起因：M8-2b 的 P0 缺陷（裸 `readdirSync` → 管道静默失效）之所以藏得住，根本原因就是 `catch (eImp) {}` 静默吞异常。

## 【P11】fail-soft 空 catch 统一可观测（只加日志，不改行为）

**背景（实读代码，2026-09-09 核实）**：
- M8-2b 的 P0 已修（`4d54664`），同提交给 `catch (eImp)` 加了 `diag('evidence-agg 降级为中性(impMap 空): …')`。
- 但同一条 recall 融合链上**仍有同款静默空 catch**：`eRrf`、`eL0Sem`、`eAnchor`（名称以实际 grep 为准）。
- 这类空 catch 让任何接线失效都**完全不可观测**：单测全绿，生产路径从不执行。

**目标**：把**记忆/检索链路**上的 fail-soft 空 catch 统一加上可辨识的 diag 日志。**只加日志，控制流一律不变**。

**涉及功能模块**：`lib/index.js`（recall / 融合 / 接续锚点相关链路）。

**验收标准**：
1. 先给出**完整清单**：grep 全仓 `catch` 后直接 `{}` 或仅注释的空捕获，按模块分组列出 `文件:行号`；**明确标注本次改哪些、不改哪些及理由**（建议只改记忆/检索/接续链路，避免全仓噪声）
2. 每个补日志的 catch：
   - 使用**可辨识前缀**（如 `recall-fusion 降级:` / `l0-sem 降级:` / `handoff-anchor 降级:`），便于日志检索
   - 含异常摘要（`String(e && e.message || e).slice(0, 140)`）
   - **外层再包一层 try/catch**，确保 diag 本身抛错也不会影响主流程
3. **行为不变**：异常仍被吞掉（保持 fail-soft，不向上抛）；不得改变任何控制流分支
4. **日志不得进入提示词/注入内容**（遵守 I1 / I3）——diag 只写日志文件
5. 基线不降：p8 14 / p4 34 / evidence-agg 14 / handoff 51 / continue-chain 58

**需先检索的仓库路径与符号关键词**：
- 路径：`lib/index.js`（重点 recall 与接续链路）、`lib/client.js`
- 关键词：`catch`、`eRrf`、`eL0Sem`、`eAnchor`、`eImp`、`diag(`
- **必须先确认**：① `diag()` 的定义位置、输出目标文件、是否有开关 ② diag 是否已被高频调用（评估日志量，避免刷屏）③ 空 catch 的真实数量与分布

**改动边界**：
- ✅ 允许修改：`lib/index.js` 中**记忆/检索/接续链路**的 catch 行（最小 diff）
- ❌ **禁止修改**：任何 `try` 块内的业务逻辑；任何控制流（不得改成抛出、不得加重试）
- ❌ 禁止：全仓无差别改造；给与记忆无关的 catch 加日志；引入日志库或新依赖
- ❌ 禁止：把异常信息写入提示词、注入内容或对外响应

**集成位置正确性（回报必写）**：清单 + 取舍理由 + 每处 `文件:行号 — 原 → 新`。

**停止条件**：若 `diag()` 不存在或其输出目标不在 `~/.dsh/memory` 内（可能污染用户记忆目录或造成隐私外泄），**立即停止回报**。

**回滚**：`git checkout lib/index.js`。

**自检清单**：按 `_COMMON.md` §5 执行（本段重点：`node --check lib/index.js` + 五套基线 + 确认无控制流改动：`git diff` 仅含 catch 行）。
