@@ -119,11 +119,6 @@ bun run docs:dev
119119- ** 7 providers** : ` firstParty ` (Anthropic direct), ` bedrock ` (AWS), ` vertex ` (Google Cloud), ` foundry ` , ` openai ` , ` gemini ` , ` grok ` (xAI)。
120120- Provider selection in ` src/utils/model/providers.ts ` 。优先级:modelType 参数 > 环境变量 > 默认 firstParty。
121121
122- ### Encoding Detection
123-
124- - ** ` src/utils/encoding.ts ` ** — 文件编码检测的唯一入口。提供 ` detectEncoding ` (三层检测:BOM → UTF-8 fatal → ICU 回退链)和 ` decodeBuffer ` /` encodeString ` 函数。检测基于文件头部 4KB,零外部依赖,仅使用 TextDecoder API。ISO-8859-1 作为最终兜底编码(单字节编码永远成功)。` FileEncoding ` 类型扩展了 ` BufferEncoding ` ,覆盖 gbk/gb18030/shift_jis/euc-kr/euc-jp/big5/iso-8859-1。
125- - ` fs.readFileSync(path, { encoding }) ` 的 ` encoding ` 选项只接受 ` BufferEncoding ` ,不支持 ` gbk ` /` shift_jis ` 等 ICU 编码名。读取非 UTF-8 文件时必须先 ` fs.readFileSync(path) ` 读 Buffer,再用 ` TextDecoder ` 解码。项目中所有文件读取路径(fileRead.ts、fileReadCache.ts、file.ts)已统一使用 ` decodeBuffer ` 函数处理此逻辑。
126-
127122### Tool System
128123
129124- ** ` src/Tool.ts ` ** — Tool interface definition (` Tool ` type) and utilities (` findToolByName ` , ` toolMatchesName ` ).
@@ -319,6 +314,48 @@ mock.module("src/utils/debug.ts", debugMock);
319314
320315路径规则:统一用 ` .ts ` 扩展名 + ` src/* ` 别名路径,禁止双重 mock 同一模块。
321316
317+ #### 跨文件 mock 污染(process-global ` mock.module ` )
318+
319+ ** Bun 的 ` mock.module ` 是进程全局的(last-write-wins),不是 per-file 隔离的。** 一个测试文件的 ` mock.module ` 会污染同一进程中所有其他测试文件的 ` require ` /` import ` 。
320+
321+ ** 关键事实(Bun 1.x 实测验证):**
322+ - 测试文件执行顺序** 不是严格字母序** ,不要假设文件 A 一定在文件 B 之前执行。
323+ - ` mock.module ` 在 ` beforeAll ` 内部调用时** 不会被提升** (hoist),但仍会污染后续加载的文件。
324+ - ` require() ` 和 ` import() ` 共享同一模块注册表,` mock.module ` 对两者都生效。
325+ - 一个模块一旦被某个文件的 ` mock.module ` 替换,同一进程中所有后续 ` require ` /` import ` 都会返回 mock 值,即使调用方使用不同的 specifier 路径。
326+
327+ ** 核心规则:不要 mock 被测模块的上层业务模块。**
328+
329+ 错误做法(会污染同目录的 ` api.test.ts ` ):
330+ ``` ts
331+ // launchSchedule.test.ts — 直接 mock 源 API 模块 ❌
332+ mock .module (' src/commands/schedule/triggersApi.js' , () => ({
333+ listTriggers: listTriggersMock ,
334+ // ...
335+ }))
336+ ```
337+
338+ 正确做法(mock 底层 HTTP 层,不污染业务模块):参考 ` launchSkillStore.test.ts ` 、` launchVault.test.ts ` 的模式。
339+ ``` ts
340+ // launchSchedule.test.ts — mock axios 而非 triggersApi ✅
341+ import { setupAxiosMock } from ' ../../../../tests/mocks/axios.js'
342+
343+ const axiosHandle = setupAxiosMock ()
344+ axiosHandle .stubs .get = axiosGetMock
345+ axiosHandle .stubs .post = axiosPostMock
346+
347+ beforeAll (() => { axiosHandle .useStubs = true })
348+ afterAll (() => { axiosHandle .useStubs = false })
349+ ```
350+
351+ ** 判断标准:** 如果目录下同时有 ` launch*.test.ts ` (集成测试)和 ` api.test.ts ` (回归测试),` launch*.test.ts ` 必须 mock axios 而非源 API 模块。` api.test.ts ` 需要测试真实 API 模块的 HTTP 方法/URL/错误处理逻辑,被 mock 后就无法测试。
352+
353+ ** 排查 mock 污染的方法:**
354+ 1 . 单独运行可疑文件确认其通过:` bun test path/to/suspect.test.ts `
355+ 2 . 与同目录其他文件一起运行定位污染源:` bun test path/to/__tests__/ `
356+ 3 . 在两个文件中各加 ` console.error('[file] milestone') ` 追踪实际执行顺序
357+ 4 . 检查 ` mock.module ` 的 specifier 是否与同目录其他测试的 ` require ` /` import ` 路径解析到同一模块
358+
322359### 类型检查
323360
324361项目使用 TypeScript strict 模式,** tsc 必须零错误** 。每次修改后运行:
0 commit comments