# 周末作战 · 进度表（2026-09-17 收盘）

> 权威顺序依据：`docs/internal/BATTLE-PLAN-20260917.md`（396 行）。
> 回归口径：`node tools\run-smoke.mjs`（全量，非单套件）。
> 本表每次阶段完工后回写。

## 总进度条

```
L 层 ████████████████████ 100%   ✅ 已冻结（PASS 112 / FAIL 0）
G4   ████████████████████ 100%   ✅ 已完成（=M3，已吸收）
M9   ████████████████████ 100%   ✅ 已完成（容量默认 12000→24000 + 老配置迁移）
M 层 ░░░░░░░░░░░░░░░░░░░░   0%   ⏭ 下一步（M1/M2）
S 层 ░░░░░░░░░░░░░░░░░░░░   0%   ⏸ 待 L/M 冻结后开
G2   ████████████████████ 100%   ✅ 已完成
G3/G5/G6 ░░░░░░░░░░░░░░░░   0%   ⏸ 待办（见文末）
```

---

## 〇、M9 · 容量出厂默认 12000 → 24000（用户报障驱动）

**用户原话**：「先把所有人的默认都改到 24000，好多人跟我抱怨写满了，写不进去了。」

| # | 项 | 改动 |
|---|---|---|
| M9a | 出厂默认 | `DEFAULT_NOTE_CAPACITY_CHARS` / `DEFAULT_USER_CAPACITY_CHARS` 12000 → **24000** |
| M9b | **老配置一次性迁移** | 新增 `upgradeCapacityDefaultsPre()`：配置里**仍是 12000**（= 没表达过偏好）才抬到 24000；用 `capacityDefaultsVersion` 守卫**只升一次**；用户自设值（8000/50000…）一律不动；异常 fail-soft |
| M9c | 落盘 | `loadConfigSync`（注册期真正跑的那条）+ `loadConfig` 都接上；异步路径抬升后 `persistConfigPre()` 落盘（否则设置页读盘仍显示 12000） |
| M9d | 文案同步 | 设置页 zh/en 各 2 处提示 + 两个输入框占位默认值 + 注入纪律行 + `memory_note_pre`/`memory_user_pre` 描述 |
| M9e | 历史保全 | **2.4.0 changelog 里的 12000 原样保留**（那是发布记录，改它=伪造历史）——已写成断言 M9-10 锁死 |

**为什么必须配迁移（关键）**：`saveConfig` 把**整个合并后的 config** 落盘（实测本机 95 个键全在盘上）⇒ 老用户只要在设置页存过**任何一项**，`noteCapacityChars: 12000` 就已被钉死在磁盘上。**只改常量对老用户完全无效**（配置值覆盖默认值）。这正是"好多人抱怨写满了"的机制。

**验证**：`smoke-test-m9-capacity-default-pre.mjs` **10/10 绿**；变异演示 **6 处变异 → 4 条断言真红**，还原后 10/10 绿。

---

## 一、本轮完工明细（逐条可回代码核对）

| # | 项 | 状态 | 关键改动 | 证据 |
|---|---|---|---|---|
| L1 | 看板渲染解耦 | ✅ | `kanbanBoardData` 删掉 `handoffEnabled` 早退（渲染不归产物开关管） | 首 900 字符内无 `handoffEnabled`；`boardMode` 门保留 |
| L2 | 面板 render 解耦 | ✅ | `handoffPanelData` 门改为 `boardMode!=='graph'` → `{enabled:false,reason:'legacy-mode'}` | `legacy-mode` 存在；无 `handoffEnabled` 早退 |
| L3 | 接续预算重构 | ✅ | 新增 `assembleCarryPre({head,nav,bulk,budget})`：**nav 配额先扣、永不截断**，bulk 可截断 + 截断自述 | `export function assembleCarryPre(...)` 签名核对；`材料因预算被截断` 存在；`bulkParts.push` 存在 |
| L3.5 | 附件路径进转写 | ✅ | `attachmentsOfContent` / `attachmentBlobPathsPre` / `renderAttachmentLinesPre` + `foldSessionLogEvents` 带 attachments | 12/12 断言绿 |
| **L3.6** | **旧会话可检索化** | ✅ | 3 纯函数 `slimTranscriptPre` / `prevSessionSidAnchorPre` / `prevSessionL0Pre` + `listPrevSessionTranscripts` 接进 `searchHandoffCorpus` | **10/10 断言绿**；3 处变异**真红** |
| L4 | 白板进检索 | ✅ | `recallMemoryPre` 的 `pushL0` 加 `handoff/PLAN.md` + 最新账本（词法臂 :5745 / 语义臂 :5953） | grep 命中两处 + `latestLedgerNamePre`（:8143） |
| L5 | 锚点解耦 | ✅ | PLAN 锚点与账本锚点的 `boardMode==='graph'` 门移除 | `applyAnchorsPre(wsKey,'handoff/PLAN.md',...)` 处无 boardMode 门 |
| L6 | 账本保护门注释 | ✅ | `checkMutationPre` 两条 `not-applicable` 分支 | `:2455 target-not-protected` / `:2456 ledger-append-only-no-before-side` |
| L7 | 死导出存活标注 | ✅ | `wb-contract-pre.js` 两处标「对外契约保留」 | `:47` `WB_STATUSES_PRE_V1` / `:69` `describeWbReasonPre` |
| **G4** | **白板纪律 + 写记忆时维护** | ✅ | GUIDANCE 三层分工 + 三条硬约束；`memory_log_pre` 描述加"顺手维护白板" | **7/7 断言绿**；关键词从全 False → 全 True |
| G2 | 标本作废标记 | ✅ | `MEMORY.md` 两处 `> ⚠️ 已作废（2026-09-17 · G2 标记）` | 标记存在且指向 4 门结论 |

**新增测试套件**：`smoke-test-l36-prev-session-pre.mjs`(10) + `smoke-test-g4-whiteboard-pre.mjs`(7)
**全量回归**：`PASS 111 / FAIL 0 / TIMEOUT 0`（171.0s）

---

## 二、用什么方式填补了什么空缺

| 空缺（现象） | 根因（代码级） | 填法 | 为什么是这个填法 |
|---|---|---|---|
| 旧会话转写**检索不到**（用户"有些文件接不过去"） | `listHandoffLedgers` 的过滤正则只认 `handoff-<ts>`/`PLAN-<ts>`，**结构性排除** `prev-session-*` ⇒ `scope='handoff'` 永远是孤岛 | **新增独立 lister** `listPrevSessionTranscripts` 并接进 `searchHandoffCorpus` | **不放宽既有正则**——放宽会把旧会话混进账本/归档的血缘语义 |
| 转写正文被工具噪声淹没（1854 工具事件 vs 530 assistant 消息） | 旧实现全量转写 | `slimTranscriptPre`：工具事件**转计数**，单条 2000 / 总长 60000 双上限 | 保留可追溯性（计数自述）同时让正文可见 |
| 转写体每次重建 id 都变，破坏"index.json 完全可重建" | 无 | `prevSessionSidAnchorPre`：由 **sid 推导**（`sha256('prev-session\0'+sid)`）而非时间戳 | 同一会话恒等 ⇒ 可重建 |
| 模型**不知道有白板这回事**，从不维护 | GUIDANCE 对 白板/PLAN/kind=plan/handoff **零覆盖**（实测七个关键词全 False） | GUIDANCE 加三层分工 + 三条硬约束；`memory_log_pre` 描述加"顺手维护白板" | 挂在**既有**每轮注入机制上，零新增通道 |
| 白板与账本都写"下一步" ⇒ 漂移 | 无权威划分 | GUIDANCE 明确：账本=**动态状态的唯一权威** | 一处权威，另一处不再重复 |

---

## 三、之后还待做什么

### M 层（下一步，按 BATTLE-PLAN）
- **M1** 契约行渲染
- **M2** lint ①②④（只读纯函数）
- ~~**M3** GUIDANCE 白板纪律~~ → **已被 G4 吸收，跳过**

### S 层（M 冻结后开）
- **S1** 容器结构
- **S2** 视觉对齐 DeepSeek Flow
- **侧边栏进度表**（用户长期要求，本表即其内容蓝本）

### G 系列剩余
- **G3/G5/G6**：`supersedes`/`status` 约定 + 读侧过滤；矛盾检测 lint（复用 M2，判据③④待用户裁定）；结论层 replace+archive 语义
- 三层方案 A/B/C：**A**（条目带 `supersedes`/`status`，低成本）/ **B**（矛盾 lint）/ **C**（结论层 replace+archive，长期）

### 待用户动作
1. **自行重启宿主** —— `lib/index.js` 已改（L 层 + G4），不重启不生效。（agent 绝不碰 3080）
2. ~~`noteCapacityChars` 建议 12000 → 24000~~ → **已完成（M9）**：出厂默认已改 24000，老配置（仍是 12000 的）会在重启后自动抬到 24000 并落盘，无需手动改设置。

### 已知未做（有意，不在批准范围）
- `boardMode` 原始字符串闸门尚有 13 处未改用 `isGraphModePre`（**L5 批准范围只含 2 处锚点写入**）
