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:
@@ -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` 命令,用于日常开发期间验证代码质量和基础行为。
|
||||
|
||||
50
openspec/specs/commit-quality-gates/spec.md
Normal file
50
openspec/specs/commit-quality-gates/spec.md
Normal 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 跳过,不覆盖已有配置
|
||||
Reference in New Issue
Block a user