# 交接说明 — 2026-08-04 (D) > **⚠️ 这不是最新的一份。** 本文写的是 v3.9.15,当前一份是 > [HANDOFF-2026-10-15.md](HANDOFF-2026-10-15.md)。**它的状态表与"仍未做"清单请一律以最新那份为准** —— > 交接是 append-only 的,旧的不删也不改结论。本文仍值得读的是:§5("更正"比新增声明更危险)。 > > 另:`ls docs/` 的排序**不等于**时间顺序(`-B.md` 的 `-` 排在 `.md` 的 `.` 之前,而 > `HANDOFF-2026-08-05.md` 的文件名日期是错的)。顺序只看索引 [README.md](README.md)。 **上一份**:[HANDOFF-2026-08-04-C.md](HANDOFF-2026-08-04-C.md)。它的 §0 状态表与 §4 清单已 过期(见 §1);§5 两条仍然有效。方法论沿用 [AUDIT-LEDGER.md](AUDIT-LEDGER.md) 第十一、 十二轮。 --- ## 0. 当前状态 ``` 版本 / tag 3.9.15 / v3.9.15(tag 落在 master 上,CI + Release 六个 job 全绿) master == origin/master,已推 门禁 3427 pass / 0 fail(263 个文件,exit 0) 突变 六个 spec 共 57 条:53 CAUGHT + 4 条声明的 expectCaught: false (lastUsed 项 / WAITABLE 白名单 / backoff 倍数 / known() existence 项) secret-scan EXIT=0 ← 仍然跳过 test/ 且只读被跟踪文件,见 §4.3 工作树 干净,只剩 master;远端也只剩 master 发布产物 四个资产;windsurfapi-macos.zip = 45MB(含 x64;不含时约 22MB) CI runtime 九个 action 已升 node24 —— deprecation 警告实测 0 次命中 ``` ### 门禁数字权威表 | ref | pass | 新增 | |---|---|---| | `v3.9.12` | 3342 | | | `v3.9.13` | 3401 | +59 | | `v3.9.14` | 3418 | +17 | | `v3.9.15` | **3427** | +9 | 数字请只引这张表。测量口径 `npm run test:release`(逐文件进程隔离)。**文件数 263** —— 见到 260/261/262 都是旧数。 --- ## 1. 上一份的过期处 1. **#234 已收尾并关闭**。它的六条验收判据本轮逐条核过:五条满足,**第六条是真缺陷、已修** 2. **Cascade 流式记账已修**。上一份把它列为"既有,未修" 3. **CI 九个 action 已升 node24**。上一份把它列为"需你拍板" 4. 门禁数字与文件数都变了(3418/261 → 3427/263) --- ## 2. v3.9.15 发了什么 见 [RELEASE_NOTES_3.9.15.md](releases/RELEASE_NOTES_3.9.15.md)。三件: - **#234 最后一条判据**:`DEVIN_CONNECT=1` 免费池上,Dashboard `/models` 列 163 行、 `/v1/models` 列 1 行、**零重叠** —— 面板列的全调不了,唯一调得了的不在列表里。修法是一个 导出的谓词两边都调;面板改成**标注**(`reachable` + `connectSelector`)而非删行 - **Cascade 流式 `recordAccountSpend`**:四条路径里三条有调用点,流式没有 - **九个 CI action → node24**:每个版本号从对应 tag 的 `action.yml` 读 `runs.using` 定的 --- ## 3. 接手第一步 ```bash cd /Users/dwgx/Documents/Project/WindsurfAPI echo alive # 工具层活着吗 git status --short # 期望:干净 git rev-parse master origin/master # 期望:相同 git describe --tags --exact-match master # 期望:v3.9.15 npm run test:release # 期望:3427 / 0(263 个文件) for s in test/mutations/*.json; do npm run mutate -- "$s"; done # 期望:六个全绿 ``` **跑突变时的一条硬规矩(本轮踩了三次)**:**循环启动后就不要碰仓库。** 它每一步都在 `写入 → 跑测试 → git checkout HEAD -- 还原`,期间任何别的编辑都会被 guard 6 判脏并中止整轮, 而且真有被它的还原吃掉的风险。要并行干活就去 worktree。 --- ## 4. 仍未做的 ### 4.1 等外部 - **PR #241(warelik,+439/−26)** —— 已审完并回评 ([评审](https://github.com/dwgx/WindsurfAPI/pull/241#issuecomment-5178604707))。等他改两处: nudge 累积(一行修法,已验证他 233 条断言全绿)、以及第 2 条理由补证或改写。他的 base 是 v3.9.10,需 rebase 到 v3.9.15 - **#236** —— 判据太模糊(只有"反代给 chatgpt、遇到浏览器操作就报错",无请求体/错误码/模型 名)。**该做的是向报告者要能区分候选机制的信息,不是从代码倒推一份猜测清单** - **#239 / GPT tag 校准** —— 需付费号跑 `DEVIN_CONNECT_DEBUG_META=1 npm run calibrate:devin` ### 4.2 #235 还差一半 技术主体 v3.9.8 已发(费率表判免费),v3.9.15 的面板标注让"哪些**调得动**"可见了。 **但"哪些是**免费**的"仍未暴露** —— `getCurrentlyFreeConnectSelectors`(`auth.js:290`)只有 一个生产调用者(`auth.js:322`,干旱判定内部),没有任何接口把它露出来。报告者是 pro 号、 设了 GLM-5-2 一下把周限用完,他问的正是这个。修法应该很小:把这个集合接进面板那一行的 `credit`/`reachable` 旁边。**这是眼下最小、最直接解掉一个真实用户痛点的一条。** ### 4.3 已知的记账口径问题 - **`secret-scan` 跳过 `test/`** 且只读被跟踪文件。本轮改动里 4 个文件在它盲区,已手工扫过 增量(无凭据形态)。"secret-scan 干净"这句话要带上这个范围说 - **两条有据可查的漏网**:`known()` existence 项(没有 fixture 能造出 mapped-but-unknown, 前提已被断言钉住)、backoff 倍数(`RETRY_ON_EMPTY_MS=0` 下不可观测) - **`release.yml` 的 action 升级已被 v3.9.15 真实验证过一次**(六个 job 全绿),但那是第一次 —— 下次发版仍值得看一眼终态 - **`RELEASE_NOTES_3.9.12.md` 那处 5.6x 错引刻意不改**(append-only,且已作为 Release body 发布) ### 4.4 未 exhaustive 扫描 见台账文末那张表(`Ctrl-F` 搜 `仍未 exhaustive 扫描`,**取最后一个命中**)。 --- ## 5. 本轮最该记住的 台账第十二轮有完整版。两条会直接害到下一个人的: ### 5.1 "更正"比新增声明更危险 我判定台账第十一轮那句"已加测试钉住"是假的,写成一条更正落进台账,还在 commit message 里 说这是"注释声称有覆盖而实际零断言"的又一次。 **那条更正是错的。守卫一直在** —— `strict-usage-total.test.js`,源码扫描形态,它的失败消息 里甚至预先写好了"哪天流式路径真的记账了就删掉这条"。 怎么错的:grep 提到 `recordAccountSpend` 的测试文件(它命中了),再对命中文件 grep `stream|cascade`(它又命中了),然后**看着命中行判断那是 usage 算术测试,没打开读**。两次 grep 都指向了正确的文件,我在最后一步用眼扫过去就下了结论。**是全量门禁抓到的,而且是在 修复已经提交之后。** 为什么这类错误特别贵:新增声明会被下一轮审;而"我核过了,上一轮那句是假的"会让下一个人 **停止怀疑**这个位置。 **动作**:要断言"这个面没有守卫",除了 grep 行为关键字,还要 grep**被守对象的名字**在 `test/` 下的全部命中并**逐个打开读**。命中少的时候成本是几十秒。另:源码扫描形态的守卫在 按行为搜索时是隐形的。 ### 5.2 一条 SURVIVED 先问"这段代码今天会被执行吗" 本轮两条 SURVIVED,处置**相反**: - FREE_REACHABLE 兜底 → **压根不执行**,是我自己上一个 commit 写的死代码 → 删 - `known()` existence 项 → 会执行,但没有输入能让它说话 → 记 `expectCaught: false` + 钉前提 **两者读起来一样。** 把死代码当漏网留着,正是 v3.9.13 那条 medium 缺陷的形状(被导出的 helper 零生产调用者,而它的突变守卫在守到不了线上的代码)。