关于 add-a-linter
用于向 vigiles 添加内置 linter 的贡献者技能,涵盖适配器注册、文档、测试和 CI,确保各处定义保持一致。
主要功能
- 01通过注册表集成 linter
- 02检查存在性与配置启用状态
- 03为类型生成发现规则
- 04校验文档与网站内容一致
- 05规定 CI 二进制文件与测试
适用场景
- 01为 vigiles 添加内置 linter
- 02实现 linter 配置解析器
- 03检查注册表、文档和网站的一致性
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ zernie/ vigiles --skill add-a-linter安装后在 Claude Code 中输入/add-a-linter确认已加载。
详细介绍
为 vigiles 的交叉引用引擎(enforce("eslint/...")
机制)添加一个代码检查器。这是贡献者任务,不是第三方扩展点:LINTERS
注册表是一个 Record<BuiltinLinter, LinterAdapter>——一个内置于核心的封闭
集合——因此,添加代码检查器需要编辑 vigiles 本身,而类型系统和一致性测试会确保
兼容性不会被遗忘。
这项技能存在的根本原因:过去,添加一个代码检查器需要在约 7 个分散的位置
分别修改(存在性检查、配置检查器、CLI 工具映射、建议枚举器、generate-types 发现器、
文档、网站),却没有任何机制确保你改全了——漏掉一处就会静默失败。现在,如果缺少
注册表条目,tsc 就会报错;如果文档表格或宣传网站出现偏差,src/core/linter-contract.test.ts
就会失败。按步骤操作;让各项检查发现你遗漏的内容。 请参阅
research/linter-adapter-architecture.md。
唯一的不变原则
一个代码检查器就是一个 LinterAdapter,位于一个注册表中。其他所有内容——
存在性、配置启用状态、建议、类型生成、文档、网站——都是该适配器的字段或
方法,并由一致性测试交叉检查。你再也不必四处寻找“注册这个代码检查器的其他位置”。
步骤
按此顺序操作——每一步的检查都会告诉你下一步需要做什么。
-
命名(唯一事实来源)。 在
src/core/spec.ts的BUILTIN_LINTERS中添加小写名称。BuiltinLinter根据此数组派生,因此保存后,tsc就会在linters.ts的LINTERS处报错,提示“缺少属性<name>”——这个错误就是 你的待办清单。 -
选择存在性检查类型(
src/core/linter-adapter.ts中的LinterCapabilities.existenceCheck)——这决定了用哪个辅助函数构建适配器:node-api— 从已安装的 npm 包解析规则集 (eslint、stylelint)。使用nodeApiAdapter(name, resolver, configEnabled, discover)。cli— 调用真实命令,询问工具规则是否存在(ruff、clippy、 pylint、rubocop、detekt、ktlint、checkstyle、golangci-lint)。使用cliAdapter(name, cliTool, checkExists, configEnabled, discover, enumerate?)。filesystem— 项目文件中存在相关内容即视为存在,不需要工具(cedar)。编写一个 字面量适配器(参见linters.ts中的 cedar)。format-only— 只验证引用的格式,没有工具可以列出规则(ktlint 的规则目录 无法列出)。它仍然是cli适配器,只需省略enumerate参数;存在性检查采用带限定格式的规则。
-
实现发现器
discover<Name>Rules(basePath): DiscoveredRules | null,位于linters.ts中——读取项目实际使用的代码检查器配置,并返回其启用规则,供generate-types使用(失败时放行:无法枚举时返回null,绝不要将所有规则都标记出来)。 如果是cli代码检查器,还要编写其<name>CheckExists存在性探测函数(规则未知时会抛出异常), 如果需要读取真实的配置启用状态,也要编写其<name>ConfigEnabled检查器——这些都是适配器在LINTERS注册表中直接引用的普通命名函数(无需修改单独的映射)。使用真正的解析器 解析结构化配置(js-yaml / @iarna/toml / 共享的 markdown-it 辅助函数),切勿使用手写正则表达式—— 参见parse-structured-input-with-a-real-parser规则; detekt 的parseDetektConfig(js-yaml)可作为范例。 -
注册。 在
LINTERS(linters.ts)中使用相应的辅助函数注册。到此处tsc应该通过——注册表现在已完整。 -
编写文档。 在
docs/linter-support.md中:在## Supported Linters表格中添加一行,并添加一个## <Linter>小节(配置约定、 规则前缀,以及任何能力限制,例如“仅格式检查”或“仅白名单”)。 一致性测试会将表格条目与注册表进行集合匹配,因此缺少一行就会导致 CI 失败。 -
网站会自动更新——vigiles.sh 的标签条(
Wedge.tsx)从BUILTIN_LINTERS派生,因此新增的代码检查工具会自动显示;无需编辑数组。如果需要特殊处理(例如ESLint、RuboCop),可以选择在Wedge.tsx的LINTER_LABELS中添加显示标签;若未添加,则会以小写名称显示。符合性测试会确保派生逻辑保持不变(如果改回手动输入列表,CI 就会失败)。 -
如果它是
cli代码检查工具,就要确保 CI 实际运行它——不能静默跳过。 实际二进制文件测试使用src/core/linters.test.ts中的describe.skipIf(!hasBinary("<tool>"));如果 CI 中没有该二进制文件,这些测试就会静默跳过(这是一个隐蔽的缺口——no-silent-skips规则)。在.github/workflows/ci.yml的test作业中安装该工具(通过作业env固定版本,并缓存该工具),并且将它加入command -v检查循环,这样二进制文件缺失时就会导致构建失败,而不是跳过测试。然后编写两个互补测试:实际二进制文件测试(describe.skipIf(!hasBinary))和二进制文件缺失时的错误提示测试(it.skipIf(hasBinary))——两者总有一个会运行,无论哪种情况都会明确报错。 -
添加对等测试数据。
src/core/linter-contract.test.ts中的符合性循环是通用的(会遍历注册表),因此会自动覆盖新增的代码检查工具——但还要在linters.test.ts中为该工具自己的解析器添加针对性的配置解析/发现单元测试;如果它有特殊的能力差异(例如format-only、alwaysEnabled),还要添加针对该工具的能力断言。
确保安全的检查项
运行 npm test(或至少运行 npx vitest run src/core/linter-contract.test.ts src/core/linters.test.ts + tsc --noEmit)。只有满足以下条件才算完成:
tsc无错误——注册表中存在该项(完整性)。linter-contract.test.ts通过——键值 ===name,每个能力标记都与其方法是否存在相符,existenceCheck === "cli"⟺ 存在cliTool,并且注册表键集合与BUILTIN_LINTERS以及docs/linter-support.md以及网站标签列表一致(文档 + 网站保持一致)。- 新增代码检查工具的配置解析单元测试无需二进制文件即可通过,其实际二进制文件测试会在 CI 中运行(已安装并通过检查),而不是被跳过。