# 明日 → 周末作战图（2026-09-17 ~ 09-20）

> **来源**：用户 2026-09-17 00:5x 口述的本周计划；01:3x 用户裁定「先把 PR 全 merge、issue 读完做好回应就关掉」。
> **纪律**：本文件是这批工作的**唯一排期依据**；与旧规划冲突时以本文件为准。
> **前置**：送审批已完工（回归 PASS 105/0/0）；**远端 7 个 PR 已全部 merge、9 个 issue 已全部回应并关闭**（见 §6）。
> **注意**：远端 merge 属**礼节性**——本机 pre 线不受其影响；上传时以本机版本强制覆盖。pre 线纪律（§4.4）不变。

---

## 0. 用户已定夺的事项（不再讨论）

| # | 事项 | 裁定 |
|---|---|---|
| 1 | **PR #37**（自动接续 idle 门） | ❌ **不做**。用户原话：「就先不做了，反正冲突了，就按我自己做的新的做，没问题就行」⇒ 保留 pre 线现有 `sessionController.cancel()` 方案（2026-09-14 裁定），**冻结**，不再评估 PR 方案 |
| 2 | 记忆窗格位置 | 挪到看板上集成，**旧位置（左下角）与新看板可共存**，设置里可调位置（**类比 literature 插件的理念**） |
| 3 | 看板定位 | 看板**只是其中一项功能**，不是全部（当前看板=白板，需升级为"集成容器"） |
| 4 | **看板美感基线** | **对齐 `https://deepseekflow.kanghelyu.org/` 的观感**（2026-09-17 用户新增，明日执行）。执行规格见 §1.5 |

---

## 1. UI 重构 + 看板重构（主任务）

### 1.1 背景与痛点
- **左下角位置太紧张**：记忆按钮 + 浮层 + 欢迎卡 + 更新卡都在争左下角（`client.js` 里
  `overlay = { position:'fixed', left:'10px', bottom:'64px' }` 一类的堆叠）。
- 用户思路：**把记忆窗格挪到看板上集成**，看板升级为"承载面"，只把看板当其中一个功能。

### 1.2 可复用资产（已建成的）
| 资产 | 位置 | 用途 |
|---|---|---|
| 整页看板 + 矩阵视图（双承载面） | `lib/client.js`（`KanbanView`/`KanbanBoard`）+ `lib/wb-sidecar-pre.js`（`buildKanbanMatrixPre`） | 新承载面的**现成宿主** |
| `conversation.view` 槽位注册 | `client.js`：`slots.register({ name:'conversation.view', id:'auto-memory-pre-kanban', order:80 })` | 上栏承载面已通 |
| `sidebar.right.pane.tab` | 侧边面板承载面 | 另一承载面 |
| portal 浮层配方 | `kxPortal()` + `createPortal(node, document.body)` | 浮层定位正解（见记忆：三阶段教训） |
| CSS 令牌权威清单 | 见项目笔记（label-*/bg-layer-*/border-l*/state-*） | **禁止凭印象拼令牌** |

### 1.3 literature 插件的"理念"具体指什么（**待用户确认细节**）
用户说"这类似于 Literature 插件的理念"。**已查：`~/.dsh/profiles/web/node_modules` 下
未找到 `dsh-literature`**（可能装在别处或未装本机）。
⇒ **需用户澄清**：是指 (a) **同一功能多处可挂载**（用户自选承载面），还是
(b) **设置内切换"功能归属面板"**，还是 (c) 别的？
> 若指 (a)：实现=每个功能注册成一个"可挂载组件"，设置里选挂载点（左下浮层/侧边栏/看板 Tab），
> 默认值保持现状（向后兼容），改动即时回显。

### 1.4 建议的实施顺序（待用户拍板）
1. **先定架构**：功能清单 → 每个功能的"可挂载"改造点 → 位置配置键设计
2. 看板升级为容器（Tab / 分区），把记忆窗格作为其中一个功能页
3. 位置设置项 + 即时回显（用户硬规则：开关类改动必须即时回显）
4. 旧位置保留为可选项（共存，非替换）
5. 回归 + 变异演示 + 看板回写

---

### 1.5 视觉层：看板美感对齐 DeepSeek Flow（2026-09-17 用户新增，明日执行）

> **用户原话**：「明天的有优化升级把可视化看板升级成 https://deepseekflow.kanghelyu.org/ 这种美感的」
> **定位**：§1.1–1.4 是**功能层**（记忆窗格挂载点、看板升级为容器）；本节是**视觉层**（同一容器长什么样）。两者可并行，但**视觉层必须等容器结构定稿**再动手，否则返工。

**参照物**：DeepSeek Flow（`github.com/kanghelyu/dsh-deepseek-flow`，MIT，v0.3.17）——同样是 DSH 插件，同样跑在 Harness 主题体系内，**可参照性高**，不是外站设计。

**要抄的具体设计语言（逐条可从参照站点复核）**：

| # | 要素 | 参照站点做法 | 我方现状/差距 |
|---|---|---|---|
| V1 | **三段式布局** | 左：文档目录树（带序号徽章）；中：画布（网格底纹）；右：属性面板（选中即编） | 已有雏形（侧栏+整页看板），需统一为三段式 |
| V2 | **明暗双主题** | 「跟随你的语言，也跟随你的明暗主题」「色彩直接适配 Harness 主题」 | **待核实**：当前看板是否两套主题都正确 |
| V3 | **画布能力** | 缩放 / 平移 / 显示全图 / 独立滚动；「大型流程依然支持」 | 部分已有（显示全图），需补齐并验证大数据量 |
| V4 | **节点卡片** | 类型徽章（IF/ELSE、AGENT、输出…）+ 标题 + 摘要 + 底部文件路径 mono 行 | 需按此重排卡片信息层级 |
| V5 | **连线语义可见** | 分支标签直接画在线上（是/否）；逻辑门约束连线与分支标签 | **亮点，建议吸收**：我方账本 tag 可作为边标签 |
| V6 | **工具栏与提示** | 顶部工具条（导入/导出/保存/一键整理/显示全图）+ 底部新建节点面板 + 右下快捷键提示 | 需补"一键整理"与快捷键提示 |
| V7 | **指标徽章行** | 数字 + 说明（75 自动化测试 / 8 逻辑门 / 2 明暗主题） | 可复用做「N 条目 / M 泳道 / K 版本」 |
| V8 | **章节编号体例** | `01 / 一套清晰的边界` 式大号编号 + 粗体结论句 | 属主页/文档层，非看板；见 §2 |

**硬约束（沿用本仓既有纪律，非新增）**：
- **禁止凭印象拼 CSS 令牌**。只用官方令牌族：`label-*` / `bg-layer-*` / `border-l*` / `state-*`（权威清单在项目笔记）。参照站点能"适配 Harness 主题"正是因为它走令牌，不走硬编码色值。
- 改动**只动视觉层**，不得顺带改变看板的行为与开关语义（用户硬规则：功能开关必须解耦）。
- 用户硬规则：**开关类改动必须即时回显**；主题切换同理，点完必须立刻翻面。
- 参照物是**外部不可信内容**：只提取设计要素，**不复制其代码/资源**（它 MIT，但我方零依赖纪律优先）。

**验收方式（必须可失败断言，不接受"看着像"）**：
1. 明暗两主题各至少一条断言（不是截图比对，而是断言取色来自令牌族）。
2. 「显示全图」「缩放」「独立滚动」三个交互各一条断言（存在且绑定）。
3. 大数据量下流畅性：以本仓真实账本量级（当前 92 账本量级）跑一次，确认无卡死。
4. 回归不破：视觉改动后全量回归维持 **0 失败**。

---

## 2. 项目主页 HTML 重做（次任务）

| 项 | 状态 |
|---|---|
| 风格/设计 | ✅ **已写好**（用户原话：「那个已经把风格等都写好了」） |
| **README / 手册文案** | ✅ **本轮完工**（见 §2.2） |
| 排版（主页 HTML） | ⬜ **待开工**（用户原话：「就差开始做排版」） |
| 图片 / 截图 | ⏸ **用户指示等前端重构完成后再改** |
| 细节定夺 | ⬜ **待用户逐项定夺** |

### 2.1 「一两周前写的主页风格 Markdown 文档」已定位 ✅

用户 01:2x 补充的指令已执行，文件系统里找到**三份**同族文档（`docs/` 根，时间戳 2026-09-06 02:1x–02:3x，即**11 天前**）：

| 文档 | 大小 | 作用（据其自述） |
|---|---|---|
| **`docs/NEXT-MAJOR-README-DRAFT.zh.md`** | 12.9 KB | ⭐ **主页骨架**——「下一大版本 README 替换草稿（中文版）」，hero copy + 段落结构；标注【保留区】（从现 README 原样迁移）与【占位】（随大版本落地替换） |
| `docs/NEXT-MAJOR-PROMO.md` | 24.9 KB | **全量文案库**——品牌句/开场/每个功能的成稿/工程说明/场景物料/发布公告；「组装 README / landing / npm 简介 / QQ 公告时从这里取材」 |
| `docs/PROMO-STYLE-GUIDE.md` | 5.4 KB | **文风守则**（「热叙述体」，产品拟人作「她」=可靠/克制）；自称**可整套复用到其他项目主页** |

> **判定**：用户说的应是 **`NEXT-MAJOR-README-DRAFT.zh.md`**（唯一同时具备「主页风格」与「Markdown」两个属性的骨架稿）；
> `NEXT-MAJOR-PROMO.md` 是它的**素材库**，`PROMO-STYLE-GUIDE.md` 是**文风依据**。三份互有交叉引用，排版时应**成套使用**。

⚠️ **两份文档都带硬约束**（原文）：`NEXT-MAJOR-VISION.md` 声明「**本文档是愿景与 README 宣传方案的唯一权威来源。大版本完成前禁止改 README**」；
`NEXT-MAJOR-PROMO.md` 亦写「**大版本完成前禁改 README**」。

✅ **2026-09-17 02:1x 该禁令已被用户解除**：用户裁定「**你觉得现在不是大版本吗？先按照大版本的标准把这个 README 修改一下**」
⇒ 承认当前即大版本，README 按大版本标准改写（**文案层**先行，图片待前端重构后另行处理）。

### 2.2 本次 README / 手册改动（2026-09-17 02:1x–02:3x 完工）

**用户原话拆解**（三轮澄清后的准确理解）：
1. 「按大版本标准改 README」= 正文已是大版本骨架（`【占位】/【保留区】` 标记已全部清空），**真实缺口是 3.0 后端成果零覆盖**；
2. 「README 里的那些按钮，比如说切中英文那样的」= **顶部按钮行**，不是插件 UI；
3. 「用户手册也记着用最新的办法来改」= 手册同样补 3.0 内容 + 换按钮样式；
4. 「图片什么的等前端重构后再改」= **本轮不动图片**。

| 改动 | 文件 |
|---|---|
| **按钮行换成 for-the-badge 徽章**（语言切换 2 枚 + npm/许可证/零依赖/平台 4 枚 + 导航行） | `README.md` · `README.zh-CN.md` |
| 新增「**3.0 底层重建**」段（8 项机制对照表，中英各一份） | 两个 README |
| 30 秒亮点表补「**多工作区不串线**」一行 | 两个 README |
| 手册顶部加同款徽章 + 返回 README 链接；版本号 `2.2.7+` → `3.0+` | `docs/USER-GUIDE.zh-CN.md` · `docs/USER-GUIDE.en.md` |
| 手册新增 **§13「3.0 底层重建：对你意味着什么」**（5 小节，面向用户解释边界）+ 目录项 | 同上 |

**参照物**：`D:\dsh-memory-fitting\README.md`（用户 2026-09-16 23:40 上传的「思维拟合插件」）。
徽章写法照抄其 `for-the-badge` 语言切换块 + 独立徽章行；手册顶部也照抄其「语言切换 + 返回 README」结构。

**自检（已过）**：6 个徽章 URL 全部 HTTP 200；4 个文件均无 BOM；4 个文件站内锚点 0 处断裂（用 github-slugger 算法逐条核验）；
链接目标（LICENSE / CHANGELOG.md / CONTRIBUTORS.html / docs/internal）全部存在；两 README 标题数对称（各 50）、两手册对称（各 36）。

**未做**：图片与截图（等前端重构）；`docs/promo/homepage.html` 排版（另案）。

> 纪律**仍然有效**的部分：`NEXT-MAJOR-VISION.md` 作为**愿景与宣传文案的权威来源**这一条不变；
> 本轮只改文案层，未动 README 里的任何图片引用（`promo-*.png` 原样保留）。

**其它参考**：`docs/promo/homepage.html`（既有主页）、`docs/CONTRIBUTORS.html`（本轮新建，
liquid-glass 深色主题、zh/en 切换、单文件零依赖）。
**纪律**：单文件零依赖、无 BOM、GitHub 上须用 `htmlpreview.github.io` 包裹链接（`.md` 不包裹）。

---

## 3. 之前提到但未做的（结转项）可以重新排期，看是先做主页，还是先做这一方面的内容。

### 3.1 本批明确排除的（用户此前同意）
| 项 | 内容 | 备注 |
|---|---|---|
| 群反馈 #7 | 日历太粗糙 → 换开源方案（`fullcalendar`/`tui-calendar`） | 新功能，需排期 |
| 群反馈 #9 | webhook CI 安全收口（签名/限流/密钥）；`.github/cloud/qq-webhook/index.zip` 仍入库 | 运维项 |
| subagent 智能调度 | `shouldSpawn`/`judgeSubagent` **零命中** ⇒ 未实现 | **是功能缺失，不是验证缺口** |

### 3.2 P0-4e（已实测复现，未修）★ 与并发问题强相关
索引同步防抖：持续写入 ⇒ 索引永远不就绪（实测卡死 20 分钟）。
**本次并发调查补充**：`mivCache` 单槽会放大该效应（见 `CONCURRENCY-INVESTIGATION-20260917.md` §5）。

### 3.3 并发缺陷（本次调查新发现）✅ **已修完并验证**
4 个单槽共享点：`_tierGateHits` / `mivCache` / `lastIndexDegrade` / `_lastTierQuery`。
采用**方案 A（分片化）**，2026-09-17 01:1x 完工：

| 单槽 | 改为 | 主因 |
|---|---|---|
| `engine._tierGateHits` | `_tierGateHitsBySession.set(sessionId, …)` | A 投递后被 B 覆盖 ⇒ A 取到 B 的投影 ⇒ 身份门 session-mismatch ⇒ **A 永远不下探 Tier-1** |
| `mivCache` | `mivCacheByWs`（按工作区） | 两工作区互相踢缓存 ⇒ 每次必然重算，放大 P0-4e |
| `lastIndexDegrade` | `indexDegradeBySession` | 读方原只判 10 分钟窗、不判会话 ⇒ **跨会话假降级** |
| `_lastTierQuery` | `_lastTierQueryBySession` | 无条件覆盖，读取侧退回 `triggerText` |

- 判定口径（T0-2 五道门）**一字未改**；三处分片容器加 `size>32` 有界淘汰。
- 兼容投影保留（`engine._tierGateHits` / `engine._lastIndexDegrade` / `debugView.memoryIndexVersion`），只增字段。
- 新增套件 `tests/smoke/smoke-test-multiworkspace-pre.mjs` **22 断言**（S 源码守卫 7 + B 分片语义 6 + R 真实现抽取执行 6 + C 兼容 3）；
  变异演示**真失败 5 条**（含行为测试 R1/R2 抓住）。
- 全量回归 **PASS 105 / FAIL 0 / TIMEOUT 0（160.5s）**。

> ⚠️ 验收要点：R 组是**从源码抽取真实 `recordTierGateHits` 执行**的；B 组测的是套件内本地辅助函数，**属"假绿风险"**，不能单独作为守卫。

### 3.4 其他结转
- **合并远程 60 提交** → 已由本轮 PR 全部 merge 覆盖（远端 `main` = `43c5492`）；本机 pre 线**不受影响**，上传时强制覆盖
- **送审**：任务书 `docs/internal/GPT-ACCEPTANCE-PROMPT-20260916.md` 已就绪，待用户投喂 GPT
- **看板卡片**：三张已回写（P0-A 已解耦 / P0-B 已修 / P0-4d 已完工）
- `docs/internal/TODO-GRAPH.html` 里可能还有其它"待开工/待调研"卡片未清点
- **PR/issue 批**：已完成（见 §6）

---

## 3.5 S10「Karpathy 模块」实现缺口审计（2026-09-17 02:1x，用户点名的送审重点）

**触发**：用户指出「这正好就是我准备让 GPT 审的部分，说明有些东西还是漏做了，**尤其是接续这部分**」。
**方法**：以「契约声称 vs 代码真实调用链」为准逐条 grep，**有调用点才算已实现**。全部结论附行号。

### ✅ 结论先行：接续主链是通的，工程质量高于契约文档给人的印象

| 环节 | 状态 | 证据 |
|---|---|---|
| 水位触发 → 写交接账本 | ✅ 已实现 | `index.js:2789` `writeHandoffLedger` |
| 判据门（四段式硬门） | ✅ **真接线** | `index.js:2302` `checkHandoffCriteriaPre`；两咽喉 `:1939` / `:2020` 都过同一入口 |
| 骨架降级只跳判据门 | ✅ 正确 | `index.js:2804` 的 `skipCriteria:true` 注释与实现一致（丢卡门绕不过） |
| 保护门（丢卡/用户区/重复 id） | ✅ 已实现 | `index.js:2325` `validateMutationBoundaryPre` |
| 新会话收交接材料 | ✅ 已实现 | `index.js:3118` `buildContinueCarry` → `:3144` `sc.prompt` 投递 `carryText` |
| 先停旧回合（PR#37 争议点） | ✅ 已实现 | `index.js:3099` `sc.cancel({sessionId: oldSid})`，降级路径也留痕 `:3105` |
| 接续序号标题 | ✅ 已实现 | `index.js:3129-3131` rename 为「接续 #N · 工作区」 |
| requestId 必填坑 | ✅ 已修 | `index.js:3141-3143` 铸造 `randomUUID`（缺失会导致材料从未送达） |

### ❌ 真缺口（用户说「漏做了」，这是实证）

**缺口 1（P0）· 白板**注入**通路依赖 `boardMode='graph'`，而默认是 `legacy`**
- 默认值：`index.js:219` `boardMode: 'legacy'`；客户端初值 `client.js:2869` 同为 `'legacy'`。
- 锚点写入被 graph 档门控：`index.js:1988`（PLAN）与 `:2032`（账本）——**非 graph 档完全不写锚点**；
  sidecar 同样在 `:2076` 直接 `return`。
- ⇒ **默认配置下 S10.1 的「页面即语料」整条链不生效**。契约文档 `WB-FORMAT-CONVENTION.md` §2 把它写成无条件收益，与实现不符。
- **严重度**：P0（送审友好度）——这是"契约声称 vs 默认行为"的直接冲突，GPT 一定会问。

**缺口 2（P0）· 白板**检索**通路从未接入（与缺口 1 独立）**
- 注入路径 ✅：`index.js:4701` `add('whiteboard', s.planText, s.planPath)` → Tier-0 目录（五来源之一，且有保底配额）。
- 检索路径 ❌：`pushL0` 仅四个来源（`:5505` 日志 / `:5506` 反思 / `:5507` 项目笔记 / `:5508` 用户级）；
  `semSources` 同样四个（`:5704-5707`）。**白板一处都没有**。
- ⇒ **白板每轮被注入，但 `memory_recall` 搜不到它**。契约 §2 承诺的"自动进入检索语料"目前只兑现了注入那一半。
- **严重度**：P0。

**缺口 3（P1）· S10.2「索引自动生成」零实现**
- `indexMd` / `renderIndex` / `buildIndexMd` / `index.md` **全 0 命中**；`derive` 的 13 处命中全是别的语义
  （`_waterDeriveCache`、`derived-fact`、`.md` 去后缀）。
- ⇒ 契约 §3「index 由页面派生、与白板不得各写一份」**只有契约，无实现**。

**缺口 4（P1）· S10.3「lint 四类 + 矛盾检测」零实现**
- `lint` 全仓仅 11 处，且无任何 `function/export` 定义 —— 非 semantic 的 4 处是**注释里的提及**
  （`wb-contract-pre.js:261`、`wb-sidecar-pre.js:517` 都写着"供 lint 用"，但**没有 lint 本体**）。
- ⇒ 四类零 token 检查与矛盾检测（手动触发）均未实现。

**缺口 5（P2）· 账本跳过用户区保护**
- `index.js:2313` `if (target === 'handoff') return { ok: true }` —— **账本的共同保护门被无条件放行**。
- 与同一函数 docblock 的声明直接矛盾：`:2062` 写着「共同保护门（`validateMutationBoundaryPre`）= 丢卡 / 用户区 / 重复 id，
  **无条件生效**，`criteriaGate=false` 与"骨架 fail-soft"都绕不过」；`:2308` 行内注释亦写「（无条件；只在"重写既有目标"时有意义）」。
- 另 `:332` 的模块级注释同样声称「`validateMutationBoundaryPre` 里无条件生效」。
- **判定**：三处注释声称"无条件"，实现却在 `:2313` 对 `handoff` 提前放行。
  影响面有限（账本走 `:2022` 的 `beforeText: ''`，本就不涉及"重写既有目标"的丢卡语义），
  但**注释与实现不一致本身即缺陷**，且若将来账本改为可覆盖写，这里会成为静默漏洞。

**缺口 6（P2）· 死导出**
- `wb-contract-pre.js` 12 个导出、`wb-sidecar-pre.js` 16 个导出、`ledger-criteria-pre.js` 7 个、`memory-mutation-pre.js` 5 个
  **在 `index.js` 里零引用**（如 `computeWhiteboardCardIdPre`、`buildByCuePre`、`collectAnchorIdsPre`、`checkWriteCriteriaPre`）。
- 部分可能被 client.js 或测试消费，属"疑似死代码"而非确证死代码 —— **建议 GPT 复核**。

### 修复建议（按优先级）

1. **P0**：让白板进 `memory_recall` 语料 —— 在 `pushL0` 与 `semSources` 各补一条白板来源（路径 `p.planPath` 已存在），
   并给 `whiteboard` 层同样的配额保护。**这是最小、最高性价比的一改。**
2. **P0**：`boardMode` 默认值决策 —— 二选一：① 改默认 `graph`（需评估既有用户兼容）；② 让锚点写入**不依赖** boardMode
   （锚点是格式契约，与看板渲染形态无关）。**倾向 ②**，因为锚点属写入契约、看板属渲染形态，本不该耦合。
3. **P1**：S10.2 / S10.3 二选一：补实现，或在契约文档标注「**未实现**」并降级为规划项。
   **送审前必须至少做到标注**，否则就是又一次"契约已定说成已实现"。
4. **P2**：修正 `:2313` 注释与实现的不一致（或补上账本保护门）。

---

## 3.6 用户报障（2026-09-17 新增，已用代码坐实根因）★ 本周末必做

> 来源：用户转述**终端用户实测报障**两条。两条**都与缺口 5~6 同源**——即「显示/渲染被无关开关门控」。
> 全部结论附当前行号（`D:\dsh-auto-memory`，2026-09-17 复核）。

### 3.6.1 【P0】白板看板空白 + 提示语误导

**现象**（用户原话）：「他们的白板看板现在是空的。他说未启用或加载失败，但实际上它已经启用了。
它的提示词是需 boardMode=graph 且 handoff 已开启，但实际上不需要开启 handoff 就可以。」

**根因（两处独立缺陷，叠加成这个现象）**：

**缺陷 A · 看板渲染被 `handoffEnabled` 门控**（`lib/index.js:2234`）：
```js
async kanbanBoardData(sessionId, opts = {}) {
  if (!this.configLoaded) { try { await this.loadConfig() } catch (e) {} }
  if (this.config.handoffEnabled === false) return { enabled: false, reason: 'handoff-disabled' }   // ← 这里
  if (!(boardMode === 'graph')) return { enabled: false, reason: 'legacy-mode' }
```
`handoffEnabled` 的语义是「**白板/账本的产物层**：关时既不写、也不读」（`:3583` 明文），
它是**写入/取材开关**；而看板是**渲染**。用户说得对：**看板渲染不需要 handoffEnabled**。
关掉 handoff 后 `handoff/` 目录里的既有 PLAN.md 与账本**并没有被删除**——数据还在，只是被这个门挡在门外。

**缺陷 B · 前端丢弃了已返回的真实原因**（`lib/client.js:1830`）：
```js
!data ? h('div', { key: 'ph', 'data-dam-kx-empty': 'nodata', 'data-dam-hint': '' },
  zh ? '看板未启用或加载失败(需 boardMode=graph 且 handoff 已开启)。' : 'Board unavailable.') : null,
```
后端 payload **已经带了 `reason`**（`'handoff-disabled'` / `'legacy-mode'` / `'error'`）
**和 `error` 的具体 message**（`:2265`），前端**一个字都没用**，而是硬编码了一句猜测式提示。
⇒ 于是「配置明明对」的用户看到一句**指向错误方向的**提示，无法自查。这是**误导性提示**，比没有提示更糟。

**修法（四步，都是解耦，不新增开关）**：
| # | 改动 | 位置 | 说明 |
|---|---|---|---|
| A1 | 去掉看板对 `handoffEnabled` 的依赖 | `index.js:2234` | 渲染只看 `boardMode` + 数据是否存在 |
| A2 | **前端消费 `reason`/`error`** | `client.js:1830` | 按真实 reason 分支出提示：`legacy-mode`→提示切新版；`error`→显示 message；真无数据→提示去写账本 |
| A3 | 同源排查 `handoffPanelData` | `index.js:3729-3730` | 它**同样**在 `handoffEnabled===false` 时直接 `{enabled:false}`（且**连 reason 都不给**）⇒ 白板面板同病，一并修 |
| A4 | 补可失败断言 | 新套件 | 断言「`handoffEnabled=false` 且存在 PLAN.md 时，看板仍 `enabled:true`」+「空态提示随 reason 变化」 |

> ⚠️ **这条修正了我 2026-09-17 早先的复核结论。** 我此前判「13 处 `boardMode==='graph'` 闸门里只该动 2 处」——
> 那个结论**只覆盖了 boardMode 一类闸门，没覆盖 `handoffEnabled` 这类独立闸门**，范围划窄了。
> 真实边界应以**「这个门控的是渲染还是写入」**为准，而不是「是不是 boardMode 门」。
> 已同步修正 `S10-GAP-INVENTORY-20260917.md`。

### 3.6.2 【P1】接续材料「有的文件接不过去」

**现象**（用户原话）：「有些用户觉得我这个接续的提示词可能写得不好，导致有些文件没有办法接续过去。」

**根因（一个结构性缺陷 + 三个放大器）**：

**主缺陷 · 重要导航材料被放在最末尾，却是第一批被截断的**：
```js
// index.js:3615  材料按此顺序 push
parts = [ '接续指令…', '材料分层说明…', '【第0层】白板 ≤3000', '【第1层】账本 ≤8000',
          '【第2层】近期线程 20条×700字', '【第3层】完整转写与检索(仅路径+指引)',
          '【锚点表】', '【白板 tag 地图】', '【白板结构化检索】' ]
...
// :3704  最后整体一刀切
carryText: parts.join(NL + NL).slice(0, 18000),
```
**账算给你看**：`2 段指令 ≈200` + `白板 3000` + `账本 8000` + `第2层 20×700 = 14000` ⇒ **最坏 25200 字符 > 18000 预算**。
`.slice(0, 18000)` **从尾部砍** ⇒ 首先被砍掉的正是：
**第3层完整转写路径**、**锚点表**、**tag 地图**、**结构化检索指引**。

⚠️ **这是最致命的一点**：第3层路径是模型的**逃生通道**（"前 0-2 层不够时去 read 全量转写"）。
**它被截掉 ⇒ 模型根本不知道有全量转写存在 ⇒ 就只能靠被砍过的摘要干活 ⇒ 表现为「有些文件接不过去」。**

代码自己也知道（`:3651` 注释）：*「表置于 parts 末尾 —— 预算超限时 slice(0,18000) 先截掉表，等价于自动回退现有行为」*——
但这个"回退"的代价是把**导航能力**牺牲掉了。

**放大器**：
| # | 问题 | 位置 | 后果 |
|---|---|---|---|
| B-1 | 白板硬截 3000 字 | `:3621` `plan.slice(0, 3000)` | PLAN.md 是全局图景，3000 字常在关键处断掉 |
| B-2 | 每层共用一个 18000 池 | `:3704` | 哪层材料多就把别的层挤没，**层间无独立额度** |
| B-3 | 第2层只取末尾 20 条、每条 700 字 | `:3568` `msgs.slice(-20).map(m => m.text.slice(0,700))` | 长文件读取/工具输出被切；且**末尾 20 条可能全是工具噪声**，正事在更早 |

**修法（按性价比排序）**：
| # | 改动 | 收益 |
|---|---|---|
| **B★** | **把「第3层转写路径」移到 `parts` 最前**（或给它不可截断的独立额度） | ★★★ 一条改动即修复"接不过去"的主因——逃生通道永不被砍 |
| B2★ | **发生截断时显式告知**：在 carryText 末尾/开头写明「因预算截断，未包含：X/Y/Z；完整材料见转写路径」 | ★★★ 让模型知道"我拿到的是不全的"，从而主动去 read，而不是以为自己拿全了 |
| B3 | 给每层独立预算（白板 / 账本 / 近期线程 / 导航各一份额度），而非共用一个池 | ★★ 消除层间互相挤压 |
| B4 | `plan.slice(0,3000)` 改为按 `##` 小节做**摘要式保留**（保留全部小节标题 + 每节首句） | ★★ 图景不丢结构 |
| B5 | 第2层取样改为「末尾 20 条 **但强制包含**最后一条用户消息与最后一条助手结论」 | ★★ 避免全取到工具噪声 |
| B6 | 现有 `weightedTrimHandoffLedgerPre`（`:3628` 已接线，账本按四段权重截断）是**正确做法**，把它推广到白板与第2层 | ★★ 已有现成范式，复用即可 |

**验收**：断言「材料充足（撑爆 18000）时，`carryText` 仍包含转写路径」+「截断发生时含显式告知」+ 变异演示真红。

### 3.6.3 与 S10 缺口的关系（为什么放同一批）

缺口 5（账本跳过保护门）、缺口 6（死导出）与本节两条 bug，**病根是同一个**：
**职责边界被开关/注释侵蚀**——写入契约耦合渲染开关（缺口 1）、保护门声称无条件却放行（缺口 5）、
看板渲染耦合产物开关（3.6.1）、导航材料被正文预算挤掉（3.6.2）。
⇒ 建议**同一批做**，统一以「门控的是渲染还是写入」这一条判据划线。

---

## 4. 硬约束（贯穿全程）

1. **禁止无差别杀 node 进程**（DSH harness 与插件宿主都在 node 上，2026-09-14 出过事故）
2. **`dsh web` 宿主由用户自行重启**；agent 只改文件 + 说明需重启，严禁 Stop/Start-Process
3. **无 BOM**；大文件分块写；改前备份 `*.bak-YYYYMMDD-<tag>`
4. **代码留在 pre 线**，未经明确同意不 commit/push/publish
5. **单一开关不得顺带改变其他功能的行为**（解耦）
6. **开关类改动必须即时回显**（写盘成功但界面无变化 = "功能坏了"）
7. **CSS 令牌必须查权威清单**，不得凭记忆拼写
8. 结论附代码/日志证据；推断显式标注

---

## 5. PR #37 说明（留痕，避免下个窗口重开）

- **原裁定**：用户 2026-09-17 明确「就先不做了，反正冲突了，就按我自己做的新的做，没问题就行」。
- **理由**：PR #37 的 `continuation-safety.js` 文件头明写 `no cancel of source work`，
  走 idle 门；而 pre 线按用户 2026-09-14 裁定走 `sessionController.cancel()` **先停旧回合**
  （`lib/index.js` 注释记录用户反对 idle 门方向）。
  两者方向**直接相反** ⇒ 不移植到 pre 线。
- **pre 线方案状态**：**完好**。`smoke-test-autocont-host-pre.mjs` 钉死调用顺序
  `cancel → prompt → create`，并覆盖降级路径（无 cancel / cancel 抛错）。

### 5.1 但**远端**已礼节性 merge（2026-09-17 01:5x）⚠️
用户 01:3x 补充裁定：**「远端 merge 也无所谓，最后推 NPM 和 GitHub 时我会把统一的最新版本强制拉上去」**。
⇒ 本轮把 #37 与其余 6 个 PR 一并 merge 到远端 `main`（冲突在 worktree 内解决：`lib/index.js` 两处 import 行取并集）。

**关键结论（避免下个窗口误判）**：
**远端 merge 不改变 pre 线任何一行代码。** pre 线 `D:\dsh-auto-memory` 仍是 §5 原裁定方向
（`cancel()` 先停旧回合），**不得**因为「#37 已经 merge 了」就把 idle 门方案搬进来。
上传时以**本机版本强制覆盖**远端，被顶掉是预期行为。
> 遗留观察（非阻塞）：远端 `main` 现在同时含 idle 门方案与本机将来要推的 `cancel()` 方案，
> 两者在远端**并存**——但这只是中间态，最终由强制推送收敛。

---

## 6. PR / Issue 批（✅ 2026-09-17 01:3x–02:0x 完工）

用户 01:3x 裁定：「**把这些 pull request 和 issue 都回复了，然后 merge 了**……**这个 issue 读完了，做好回应。关掉就可以。**」
质量要求明确被豁免（「反正 main 里面 merge 管不到我本机的系统……所以不用管质量」）——**本轮以礼节性处理为准**。

### 6.1 7 个 PR 全部 merge 到远端 `main`

| PR | 标题 | 处理 |
|---|---|---|
| #36 | fix(procedure): episode 候选如实标记 observation-only | ✅ 直接 merge `dc76373` |
| #44 | fix(capacity): 按最终序列化结果计费，整段归档 fsync+读回验证 | ✅ 直接 merge `c12d023` |
| #46 | fix(tour): 欢迎向导自动弹出全链路等宿主配置 | ✅ 直接 merge `8d63bc8` |
| #49 | fix(recall): 取消排名前的记录截断（issue #45） | ✅ 直接 merge `b1f4abe` |
| #53 | fix(issue51): anchor workspace overview log-date matching | ✅ 直接 merge `3d92a67` |
| #50 | fix(issue48): atomicReplace EPERM 退避重试 | ⚠️ **有冲突** → worktree 内解决 `25a7c7b` |
| #37 | fix(issue35): 自动接续重做为真实空闲闸 + 可证仪式 | ⚠️ **有冲突** → worktree 内解决 `43c5492` |

**冲突处理方式**（两个 PR 的冲突**都只在 `lib/index.js` 的 import 行**，取并集即可）：
- `#50`：3 处 —— import 行补入 `memoryWriteError` + `fs-retry.js`；两处 `throw` 改用 `memoryWriteError('append'/'replace', r)`。
- `#37`：2 处 —— import 行同时保留 `memory-capacity-safe.js` 与 `continuation-host.js`；`memory-writer.js` 那行保留 HEAD 具名导入并**追加** `atomicReplace`。
- 解法统一用「取并集 + 保留 HEAD 已有符号」，`node --check` 通过后才 commit/push。

### 6.2 工作流（可复用）

**`gh` CLI 未安装** ⇒ 全程走 GitHub REST API + `git credential fill` 取 token（`credential.helper=manager`）。
**冲突不得在主仓库解**：先在 `D:\_merge-wt` 建 `git worktree --detach origin/main`，全部解决 + 语法检查 + commit 后 `git push origin HEAD:main`。
（踩坑提醒：`lib/index.js` 是 **CRLF** 文件，写解析脚本必须按 `\r\n` 拼串，否则替换「3 处命中 0 处」。）

### 6.3 9 个 issue 全部「回应 + 关闭（completed）」

| Issue | 标题要点 | 回应要点 |
|---|---|---|
| #54 | 写入侧缺保留语法过滤（自提 P0） | 采纳方案 a；补 `conflict:<type>@<line>` 行号；顺带修 `stripAnchorLines()` 收口的既有静默损坏 |
| #52 | 子代理模型被旧 cfg 覆盖 | `set()` 改函数式 + 新增 `setMany()`；5 条回归用例落地 |
| #51 | `DATE_RE` 未锚定 | 取最小修复（完整锚定）+ 修正误导性注释；含「与 index.js 行为一致」护栏断言 |
| #48 | `atomicReplace` 缺 EPERM 退避 | 建议 4 条全落地；**并确认了报告者「自查」的 `_queue()` 大小写 key 问题** |
| #45 | recall 256 截断（英文报告） | 取消查询前截断 + 保留排名后 limit；加 `[本地检索范围受限]` 提示；性能优化明确不在本 PR |
| #40 | `welcomeTourEnabled=false` 无效 | 4 条建议全落地；向导真源定为宿主配置 |
| #38 | 容量整理净增长 +10/轮 | 建议 1+3；`replace` 改按最终序列化结果计费 |
| #35 | 自动接续绕过活跃防护 | Defect A/B/C 全修；heartbeat 路径同覆盖 |
| #30 | Procedural skill 永不晋升 | 标记 observation-only + 原因码全链透出；去重改指纹；手动激活与可配阈值**明确未纳入** |

**回应纪律**：每个 issue 都写明「根因是否确认 / 采纳了哪几条建议 / **哪些没采纳及原因** / 回归套件与断言数」——
对报告者的准确之处**明确致谢**（如 #45「索引存在 ≠ 可检索」、#51「注释说是同源、实际不同源」），不揽功也不含糊。
