1
0

chore: 强化代码质量与风格检查体系

ESLint 升级到 recommended-type-checked + stylistic-type-checked,
引入 perfectionist 导入排序和 import 插件导入验证。

Prettier 显式声明全部格式化参数,消除跨环境差异。
TypeScript 启用 noUnusedLocals 和 noPropertyAccessFromIndexSignature。
完善 ignore 列表,排除 .agents/、bun.lock、data/ 等。
引入 husky + lint-staged(pre-commit)+ commitlint(commit-msg)。
更新 DEVELOPMENT.md 代码质量章节。
修复所有新增规则检测到的类型和风格违规。
This commit is contained in:
2026-05-12 18:44:59 +08:00
parent ce8baae3d1
commit a5cf6065c2
83 changed files with 2654 additions and 1824 deletions

View File

@@ -5,7 +5,7 @@
## Requirements
### Requirement: ESLint 代码质量门禁
项目 SHALL 提供 ESLint 代码质量门禁,用于审查 TypeScript、React 前端、脚本和测试代码中的质量问题。
项目 SHALL 提供 ESLint 代码质量门禁,用于审查 TypeScript、React 前端、脚本和测试代码中的质量问题。ESLint 配置 SHALL 包括 `@eslint/js` recommended 规则、`typescript-eslint` recommended-type-checked 和 stylistic-type-checked 规则、`eslint-plugin-perfectionist` 导入排序规则、`eslint-plugin-import` 导入验证规则,以及精选的单项类型安全和风格规则。
#### Scenario: 运行 lint 检查
- **WHEN** 开发者运行文档化的 lint 命令
@@ -19,8 +19,24 @@
- **WHEN** `src/web` 前端代码导入 `src/server` 后端运行时实现
- **THEN** lint 命令 MUST 失败并报告前后端边界违规
#### Scenario: 检测类型安全违规
- **WHEN** 代码中存在浮动的 Promise 未 await、any 类型泄漏到明确类型位置、模板字符串中包含非字符串化对象等类型安全隐患
- **THEN** lint 命令 MUST 失败并报告对应 `@typescript-eslint` 规则违规
#### Scenario: 检测导入路径错误
- **WHEN** 代码中导入路径指向不存在的文件或已废弃的路径
- **THEN** lint 命令 MUST 失败并报告 `import/no-unresolved``import/no-deprecated` 错误
#### Scenario: 排除第三方模板目录
- **WHEN** ESLint 运行检查
- **THEN** 系统 MUST 排除 `.agents/` 等第三方模板目录,不检查其中的代码
#### Scenario: 排除生成产物和锁文件
- **WHEN** ESLint 运行检查
- **THEN** 系统 MUST 排除 `dist/``.build/``node_modules/``openspec/``.opencode/``.claude/``.codex/``*.bun-build``bun.lock``data/` 等非源码目录
### Requirement: Prettier 代码格式门禁
项目 SHALL 提供 Prettier 格式化和格式检查命令,用于统一代码风格。
项目 SHALL 提供 Prettier 格式化和格式检查命令,用于统一代码风格。Prettier 配置 SHALL 显式声明 `printWidth``semi``singleQuote``trailingComma``bracketSpacing``arrowParens``endOfLine``tabWidth``useTabs` 全部格式化参数。
#### Scenario: 检查代码格式
- **WHEN** 开发者运行文档化的格式检查命令
@@ -32,7 +48,51 @@
#### Scenario: 排除 OpenSpec 文档和生成产物
- **WHEN** Prettier 格式化或格式检查运行
- **THEN** 系统 MUST 排除 `openspec/``dist/``.build/``node_modules/``bun.lock` 和临时构建产物
- **THEN** 系统 MUST 排除 `openspec/``dist/``.build/``node_modules/``bun.lock``skills-lock.json``.agents/``data/``*.bun-build``.opencode/``.claude/``.codex/` 和临时构建产物
#### Scenario: 格式化配置一致性
- **WHEN** 不同开发者在不同操作系统上运行 `prettier --write`
- **THEN** 由于所有格式化参数均显式定义,产物 SHALL 完全一致
### Requirement: TypeScript 未使用变量检测
项目 SHALL 启用 TypeScript `noUnusedLocals` 编译选项,将未使用的局部变量检测为编译错误。
#### Scenario: 存在未使用的局部变量
- **WHEN** TypeScript 代码中存在声明但未被引用的局部变量
- **THEN** `tsc --noEmit` MUST 以非零状态退出并报告未使用变量
### Requirement: TypeScript 索引签名属性访问检测
项目 SHALL 启用 TypeScript `noPropertyAccessFromIndexSignature` 编译选项,禁止通过点号访问未显式声明的属性。
#### Scenario: 通过点号访问 Record 动态属性
- **WHEN** 代码通过 `.property` 点号语法访问 `Record<string, T>` 类型或索引签名类型的属性
- **THEN** `tsc --noEmit` MUST 以非零状态退出,强制使用 `["property"]` 括号语法显式访问
### Requirement: ESLint 导入自动排序
项目 SHALL 通过 `eslint-plugin-perfectionist` 对导入语句进行自动排序,确保导入顺序一致性。
#### Scenario: 导入语句无序排列
- **WHEN** 文件中导入语句未按要求排序
- **THEN** `eslint --fix` SHALL 自动重排 import 声明和 named imports 内部顺序
#### Scenario: type import 与 value import 混合
- **WHEN** 文件中同时存在 `import type``import` 语句
- **THEN** perfectionist SHALL 正确识别并分别排序,不将 type 和 value 导入混淆
### Requirement: ESLint 导入路径验证
项目 SHALL 通过 `eslint-plugin-import` 验证导入路径的有效性和一致性。
#### Scenario: 导入不存在的模块路径
- **WHEN** 代码中导入了不存在或路径错误的模块
- **THEN** lint 命令 MUST 失败并报告 `import/no-unresolved` 错误
#### Scenario: 存在重复导入
- **WHEN** 同一个模块在同一文件中被多次导入
- **THEN** `eslint --fix` SHALL 自动合并重复导入为目标模块的单条导入
#### Scenario: 存在循环依赖
- **WHEN** 模块 A 导入模块 B同时模块 B 导入模块 A
- **THEN** lint 命令 MUST 报告 `import/no-cycle` 警告
### Requirement: 快速检查命令
项目 SHALL 提供快速 `check` 命令,用于日常开发期间验证代码质量和基础行为。

View File

@@ -0,0 +1,50 @@
## Purpose
定义 Git hooks 自动化质量门禁行为,在 pre-commit 阶段自动运行代码检查和格式化,在 commit-msg 阶段校验提交信息格式。
## Requirements
### Requirement: pre-commit 自动质量检查
项目 SHALL 通过 husky 和 lint-staged 在 git commit 前自动对变更文件运行 ESLint 和 Prettier 检查。
#### Scenario: 变更 TypeScript 文件后提交
- **WHEN** 开发者 stage 了 `.ts``.tsx` 文件并执行 `git commit`
- **THEN** lint-staged SHALL 自动对变更文件运行 `eslint --fix``prettier --write`,修复后继续提交
#### Scenario: 变更 Markdown 或 JSON 文件后提交
- **WHEN** 开发者 stage 了 `.md``.json``.yaml``.yml` 文件并执行 `git commit`
- **THEN** lint-staged SHALL 自动对变更文件运行 `prettier --write`
#### Scenario: lint 检查失败阻止提交
- **WHEN** 变更文件存在无法自动修复的 ESLint 错误
- **THEN** pre-commit hook MUST 以非零状态退出,阻止提交
#### Scenario: 无变更文件提交
- **WHEN** 开发者执行 `git commit` 但无 stage 文件
- **THEN** lint-staged SHALL 正常通过,不阻止提交
### Requirement: 提交信息格式校验
项目 SHALL 通过 commitlint 在 git commit 时校验提交信息必须符合 "类型: 简短描述" 格式,类型限定为 feat/fix/refactor/docs/style/test/chore。
#### Scenario: 有效的中文提交信息
- **WHEN** 开发者提交信息为 "feat: 新增导入排序功能"
- **THEN** commit-msg hook SHALL 通过校验
#### Scenario: 缺少类型前缀的提交信息
- **WHEN** 开发者提交信息为 "新增导入排序功能"(无 "feat:" 前缀)
- **THEN** commit-msg hook MUST 以非零状态退出,提示正确格式
#### Scenario: 无效的提交类型
- **WHEN** 开发者提交信息使用不在允许列表中的类型(如 "update: 修改配置"
- **THEN** commit-msg hook MUST 以非零状态退出,提示可用类型
### Requirement: husky 初始化自动化
项目 SHALL 通过 `prepare` 生命周期脚本在 `bun install` 时自动初始化 husky。
#### Scenario: 首次安装依赖
- **WHEN** 开发者运行 `bun install`
- **THEN** husky SHALL 自动初始化,安装 pre-commit 和 commit-msg hooks
#### Scenario: 已有 husky 配置时安装
- **WHEN** 开发者运行 `bun install` 且 husky 已初始化
- **THEN** husky 初始化 SHALL 跳过,不覆盖已有配置