Files
deepseek-harness/.agents/notes/implemented/process/2026-07-29-oxlint-linter.zh.md
2026-08-09 14:55:15 +08:00

6.2 KiB
Raw Blame History

Agent Note: 使用 Oxlint 作为仓库 linter

Status: implemented

English | 中文

问题

仓库的自有源码需要类型感知的 TypeScript 正确性规则、一致的格式以及文件内重复逻辑检查。ESLint 通过 JavaScript 解析器、项目服务和多个插件提供这些检查,但在本地迁移基线上,一次无问题的 lint 运行约需 1 分钟,并且需要 8 GiB Node 堆、CI 结果缓存和单独调优的 ESLint 并发度。

不能以提高运行速度为由丢失规则。迁移必须保留严格类型检查预设、仓库覆盖配置、内联抑制指令、@stylistic 修复、SonarJS 检查、host/client TypeScript 隔离和 vendor 排除规则。

决策

根目录的 .oxlintrc.json 是仓库类型感知 lint 配置的权威来源。不加载项目的 .oxlintrc.staged.json 配置继承其源码规则,为有界的 pre-commit 路径禁用类型分析,并重新纳入类型感知后端无法分析但需保留的 TypeGraph fixture测试前置数据lintlint:fix 包脚本、门禁调度器、CI 和 lefthook 通过 scripts/run-oxlint.ts 调用 Oxlint仅使用 Oxlint 的修复工作流负责多轮插件修复,并取代单独的格式化回退路径。

options.typeAware 启用 oxlint-tsgolint。其后端按文件发现 TypeScript 项目包源码使用各自的包项目host 测试、示例和网站使用 tsconfig.host.jsonclient 测试及 scripts/client-bundle-purity.spec.ts 使用 tsconfig.client.json。不含程序的根解决方案绝不会被扁平化。Oxlint 的 --tsconfig 覆盖项会影响导入解析,但类型感知 lint 会忽略它,因此本仓库不设置该选项。该配置显式载入迁移后的严格类型检查规则和仓库覆盖配置,而不启用内容可能发生变化的 Oxlint 宽泛类别。typescript/no-unnecessary-condition 仍从 Oxlint 的 nursery 规则集中启用,因为它在迁移前就是仓库强制执行的规则。

Oxlint 的 JavaScript 插件兼容层运行 @stylistic/eslint-plugineslint-plugin-sonarjs,从而继续强制执行现有的格式和文件内重复逻辑规则。兼容层会报告 @stylistic 违规并执行其安全修复;max-len 仍仅用于验证。自有源码中的抑制指令使用 oxlint-* 指令和 typescript/* 命名空间未使用的指令仍作为警告报告vendor 源码保留其上游指令,因为 Oxlint 会排除 vendor/**

CI 不恢复或保存 lint 结果缓存。DSH_OXLINT_THREADS 使共享运行器将同一上限传给 Oxlint 的 --threads 选项和类型感知后端的 GOMAXPROCS 环境变量普通本地运行对两者均采用默认值。Pre-commit 运行不加载项目的 Oxlint 验证,应用带一次有界重试的安全修复,接受仅含已忽略文件的文件选择,并通过 lefthook 重新暂存结果。公共 lint 和 CI 会先准备生成的声明,并保留完整的类型感知规则。

验证

解决两处分析器差异后,迁移后的配置报告与迁移前一致的自有源码无问题基线:移除了一项冗余测试断言,而 tsc 要求的一处结构性类型转换使用了窄范围的 Oxlint 抑制指令。以已删除 ESLint 配置的精确 blob 为基准进行的一次性审核在完成规则名映射后确认:源码为 88 项对 88 项,示例为 87 项对 87 项,测试为 83 项对 83 项。已提交的指纹锁定这些经审核的 Oxlint 规则配置及完整的覆盖结构;它既不执行已删除的配置,也不纳入后续的上游预设变更。对 typescript-eslint@8.61.0 的评估还确认,strictTypeChecked 并未启用 @typescript-eslint/no-empty-function;已删除、仅用于测试的 off 条目不起作用。

可执行约定测试要求包、host 和 client 项目产生类型感知诊断,断言 client 专用脚本所用的项目,拒绝未匹配的回退分析,并检验 Stylistic、SonarJS 和 nursery 兼容路径。它们还锁定暂存配置不加载项目的继承行为与 TypeGraph fixture 覆盖、未使用抑制指令的报告行为、仅选择已忽略暂存文件的情况、完整的 Stylistic 规则集,以及收敛后最终格式化的字节。运行器测试锁定两项工作线程控制,类型检查则确认迁移引发的源码改动没有破坏 TypeScript 程序。

考虑过的替代方案

在全仓库范围内同时运行两个 linter。 所有正确性规则均可通过 Oxlint 原生规则、nursery 规则或 JavaScript 插件兼容层获得。在全仓库范围启用 ESLint 回退会保留较慢的项目服务初始化和两套正确性配置,却不会增加任何检查。

使用单独的格式化器。 迁移保留了窄范围的 ESLint 流程,因为当时认为兼容层无法执行修复。锁定版本的工具链证明能够执行相同修复后,仅使用 Oxlint 的修复工作流以一次有界重试取代了该部分决策。

移除尚无原生实现的 @stylistic 或 SonarJS 规则。 这会移除依赖,但也会削弱机械质量约定。兼容层会保留这些规则,直到能够通过单独决策评估原生替代规则。

迁移期间用 Oxfmt 替换 @stylistic。 格式化器迁移会产生超出 lint 引擎边界的输出变化,并带来全仓库格式 diff。保留既有规则可使本次变更便于评审并让格式化器选择保持独立。

结果

本地迁移测量显示,不使用结果缓存时,一次无问题的类型感知 lint 运行从约 61 秒缩短至约 8 秒。确切比例因主机而异,不构成性能保证。

类型感知诊断现在来自通过 oxlint-tsgolint 捆绑的 TypeScript Go 分析器,因此即使 tsc 接受同一程序,边界场景下的类型推断也可能与 typescript-eslint 不同。lint 与类型检查仍是两项相互独立的必要证据。

JavaScript 插件兼容 API 和暂存配置是需要维护的额外边界。每次提交把类型感知诊断留给公共 lint 和 CI并避免依赖生成的声明。全仓库验证、修复、类型感知分析、缓存政策、工作线程控制和内联指令仍由 Oxlint 负责。