patbaumgartner/habbit-hooks

GitHub: patbaumgartner/habbit-hooks

habit-hooks 将 Java 静态分析工具的违规报告转化为带修复指导的 AI 编程习惯,帮助 AI agent 产出更高质量的 Java 代码。

Stars: 0 | Forks: 0

# habit-hooks [![CI](https://static.pigsec.cn/wp-content/uploads/repos/2026/06/1a8a2391a2013928.svg)](https://github.com/patbaumgartner/habbit-hooks/actions/workflows/ci.yml) [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) [![Java Version](https://img.shields.io/badge/Java-25-orange)](https://adoptium.net) [![Maven](https://img.shields.io/badge/Maven-3.9%2B-blue)](https://maven.apache.org) 别再向你的 AI agent 灌输软件工程文献了。 将最佳实践建议转化为 AI 的**习惯**——让它像这样编写 Java 代码。 ## 这是什么 AI 编程 agent 经常忽略冗长的规则文档。要求它们记住一整本书的编程建议,往好了说是徒劳无功,往坏了说是会污染 context 窗口并降低性能。 **habit-hooks** 封装了你现有的 Java 静态分析工具——**Checkstyle** 和 **PMD**——来创建触发器,但它不仅提供指标,还会就*为什么*违规是一种代码坏味道以及*如何*修复它提供可操作的指导。 这创造了一种类似于人类习惯的 AI 行为,并具有相似的效果。 使用 habit-hooks: - **提高代码质量** —— 在 commit 时捕获结构性代码坏味道 - **提升 AI 性能** —— agent 从干净的代码开始,需要更少的 context - **减少 token 使用** —— 干净的代码意味着阅读量减少,更易理解意图 - **促进架构规范** —— 与 [Taikai](#taikai-integration) 自然搭配 ## 安装 从 [Releases](https://github.com/patbaumgartner/habbit-hooks/releases) 下载最新的 fat JAR: ``` curl -L https://github.com/patbaumgartner/habbit-hooks/releases/latest/download/habit-hooks-launcher.jar \ -o ~/.local/bin/habit-hooks.jar # 创建 wrapper script echo '#!/bin/sh\nexec java -jar ~/.local/bin/habit-hooks.jar "$@"' > ~/.local/bin/habit-hooks chmod +x ~/.local/bin/habit-hooks ``` 或从源码构建: ``` ./mvnw package -DskipTests java -jar target/habit-hooks-*-launcher.jar ``` ## 快速开始 ``` habit-hooks init ``` `init` 会检测现有的 Checkstyle/PMD 配置,为缺失的配置生成初始配置,写入 `.habit-hooks.yaml` 和一个空的 baseline,并提供添加 Maven plugin 片段的选项。使用 `--dry-run` 运行以预览所有写入操作。 然后: ``` habit-hooks ``` 针对自分支基准点以来更改的文件运行所有封装的工具。 ## 兼容性和稳定性保证 - 运行时/构建基准:**仅限 Java 25** - 支持的平台:Linux 和 macOS(在 CI matrix 中验证) - 已验证的 JDK 发行版:Temurin 和 GraalVM(Java 25) - 公开的 CLI 命令和 `.habit-hooks.yaml` 结构在同一次要版本线(`0.x`)内被认为是稳定的,除非在发布说明中明确记录 ## 维护脚本 两个仓库脚本让操作任务变得可重复: ``` # 刷新依赖、重写代码、运行 verify、self-dogfood ./scripts/cleanup-code.sh # 强制 repo 设置(仅限 rebase)、可选通过 rebase 合并 PR ./scripts/repo-admin.sh --repo patbaumgartner/habbit-hooks --merge-open-prs ``` 在任一脚本上使用 `--dry-run` 来预览操作。 ## 它能捕获什么 habit-hooks 封装了项目的 Checkstyle 和 PMD。这些工具从你的 `checkstyle.xml` 和 `pmd-ruleset.xml` 中触发的任何规则,都会被 habit-hooks 显示出来。它在此基础上增加的是*为什么这是坏味道*以及*如何修复它*。 ### 已指导的规则 | 工具 | 规则 ID | 描述 | |------------|----------------------------------------------|----------------------------------| | checkstyle | `checkstyle:MethodLength` | 过大的方法 | | checkstyle | `checkstyle:ParameterNumber` | 参数过多 | | checkstyle | `checkstyle:CyclomaticComplexity` | 高复杂度 | | checkstyle | `checkstyle:JavaNCSS` | 过多的非注释源代码行 | | checkstyle | `checkstyle:VisibilityModifier` | 弱封装性 | | checkstyle | `checkstyle:MagicNumber` | Magic numbers(魔法数字) | | pmd | `pmd:NcssCount` | 过大的方法或类 (PMD) | | pmd | `pmd:ExcessiveParameterList` | 参数过多 (PMD) | | pmd | `pmd:CyclomaticComplexity` | 高复杂度 (PMD) | | pmd | `pmd:GodClass` | 承担过多职责的类 | | pmd | `pmd:TooManyFields` | 字段过多的类 | | pmd | `pmd:UnusedPrivateField` | 未使用的字段 | | pmd | `pmd:UnusedLocalVariable` | 未使用的变量 | | pmd | `pmd:EmptyCatchBlock` | 静默吞没异常 | | pmd | `pmd:LiteralsFirstInComparisons` | Null 不安全的字符串比较 | | pmd | `pmd:ReturnEmptyCollectionRatherThanNull` | 用 Null 代替空集合 | | pmd | `pmd:UseCollectionIsEmpty` | `size() == 0` -> `isEmpty()` | | pmd | `pmd:UseEqualsToCompareStrings` | 使用 `==` 比较字符串 | | pmd | `pmd:OverrideBothEqualsAndHashcode` | 只有 `equals()` 而没有 `hashCode()` | | pmd | `pmd:AvoidReassigningParameters` | 重新赋值的参数 | | pmd | `pmd:LooseCoupling` | API 中使用具体类型 | | pmd | `pmd:ArrayIsStoredDirectly` | 直接存储数组而未拷贝 | | pmd | `pmd:PreserveStackTrace` | 重新抛出时丢失 stack trace | | pmd | `pmd:CopyPaste` | 重复代码 (CPD) | | checkstyle | `checkstyle:NestedTryDepth` | 深度嵌套的 try 块 | | checkstyle | `checkstyle:BooleanExpressionComplexity` | 复杂的布尔表达式 | ### 未指导的规则 habit-hooks 尚未指导的任何规则仍然会显示——归并到单个**未指导的规则**部分下——这样 agent 就永远不会失去对未知违规的可见性。 要为某个规则添加指导:在你配置的 `prompts` 目录中放入一个 `-.md` 文件(将 `:` 替换为 `-`)。habit-hooks 将使用该文件代替内置 prompt,或者如果该规则之前未被指导,则创建一个新的已指导条目。 ## CLI ``` habit-hooks run all wrapped checks against changed files habit-hooks --last check files changed in the last N commits habit-hooks --branch [name] check files changed vs branch (default: scope.branchBase) habit-hooks --since check files changed since the given commit habit-hooks --all check all Java files regardless of git scope habit-hooks --config use an explicit config file habit-hooks --version print version habit-hooks init scaffold tool configs and habit-hooks config habit-hooks init --dry-run show every intended write without touching disk habit-hooks baseline status summarise current baseline contents habit-hooks baseline snooze add current violations to the baseline habit-hooks baseline prune drop baseline entries whose files no longer exist ``` `--last`、`--branch`、`--since` 和 `--all` 是互斥的。 ## 配置 habit-hooks 会在项目根目录查找 `.habit-hooks.yaml`。 ``` # .habit-hooks.yaml prompts: ./prompts # optional directory for custom coaching prompts rules: checkstyle:MethodLength: disabled: false exclude: - "**/*Test.java" pmd:GodClass: disabled: false severity: error scope: onlyChangedFiles: true branchBase: main # branch used as diff base excludeTests: true # skip src/test/java by default analyzers: checkstyle: enabled: true configFile: checkstyle.xml pmd: enabled: true rulesets: - pmd-ruleset.xml ``` 每个规则的旋钮:`disabled`、`include`、`exclude`、`severity`。 其他所有内容(例如方法长度阈值)都属于你的 `checkstyle.xml` / `pmd-ruleset.xml`。 当 habit-hooks 解析范围时,默认会排除测试源码。 如果你希望 CLI 也能分析 `src/test/java`,请设置 `scope.excludeTests: false`。 ## Baseline habit-hooks 支持在仓库中提交存放于 `.habit-hooks-baseline.json` 的 baseline。 baseline 记录了以文件路径和最后一次 commit 的 hash 为键的现有违规。 只有在以下情况才会跳过违规: 1. 文件出现在 baseline 中,**并且** 2. 文件最后一次 commit 的 hash 与 baseline 条目匹配,**并且** 3. 该文件的工作区是干净的。 触碰该文件(commit、stage 或修改),baseline 条目就会停止生效——你不会因为意外而让延后处理的违规继续累积。 ``` # 接入 legacy project habit-hooks baseline snooze # 删除后清理 habit-hooks baseline prune ``` ## Taikai 集成 [Taikai](https://github.com/enofex/taikai) 扩展了 ArchUnit,为分层架构、Spring Boot 约定和命名模式提供了预定义的规则。 它在 `mvn test` 期间作为 JUnit 测试运行。 `habit-hooks init --taikai` 会生成一个 `ArchitectureTest.java`: ``` @Test void shouldFulfillArchitectureConstraints() { Taikai.builder() .namespace("com.example") .java(java -> java .noUsageOfDeprecatedAPIs() .methodsShouldNotDeclareGenericExceptions() .imports(imports -> imports.shouldHaveNoCycles())) .spring(spring -> spring .noAutowiredFields() .controllers(c -> c.shouldBeAnnotatedWithRestController()) .services(s -> s.namesShouldEndWithService()) .repositories(r -> r.namesShouldEndWithRepository())) .build() .checkAll(); } ``` 手动添加依赖: ``` com.enofex taikai 1.64.0 test ``` ## Native image(可选) `habit-hooks` 提供了一个 GraalVM native-image Maven profile,用于实现快速启动的 CLI 使用。 ``` # 需要安装了 native-image 的 GraalVM JDK ./mvnw -Pnative package ``` 输出二进制文件: ``` target/habit-hooks ``` Java fat JAR 仍然是默认的分发产物。 ## 供应链和发布完整性 发布包括: - `habit-hooks-launcher.jar` —— 可运行的 fat JAR - `habit-hooks--sources.jar` —— 源码归档 - `bom.json` —— CycloneDX SBOM GitHub release 构建还会生成 **SLSA provenance attestations**(`actions/attest-build-provenance`)。 安全自动化包括: - CodeQL (`codeql.yml`) - OWASP Dependency Check (`security.yml`) - OpenSSF Scorecard (`scorecard.yml`) - Dependabot 更新 + 补丁自动合并 (`dependabot-automerge.yml`) 发布完整性还包括: - 在所有工作流中通过 commit SHA 锁定不可变的 action - 在发布构建期间验证 SLSA attestation(`gh attestation verify`) - 发布产物的无密钥 Sigstore/Cosign 签名(`.sig` + `.pem`) ### 在本地验证发布产物 1. 下载发布文件(`habit-hooks-launcher.jar`、`.sig`、`.pem`、`bom.json` 以及相关的签名文件)。 2. 使用 GitHub CLI 验证 provenance attestation: ``` gh attestation verify habit-hooks-launcher.jar --repo patbaumgartner/habbit-hooks ``` 1. 验证无密钥 Cosign 签名: ``` cosign verify-blob \ --certificate habit-hooks-launcher.jar.pem \ --signature habit-hooks-launcher.jar.sig \ --certificate-identity-regexp 'https://github.com/patbaumgartner/habbit-hooks/.github/workflows/release.yml@refs/tags/v.*' \ --certificate-oidc-issuer https://token.actions.githubusercontent.com \ habit-hooks-launcher.jar ``` 1. 如果需要,对 `bom.json` 和 `habit-hooks--sources.jar` 重复此操作。 ## 平台兼容性矩阵 `compatibility.yml` 持续对以下环境中的 launcher 行为进行冒烟测试: - Linux + macOS - Temurin JDK 25 + GraalVM JDK 25 它还会在 Linux + GraalVM 上运行额外的 native-image 冒烟检查,包括执行 native 二进制文件。 `startup-benchmark.yml` 跟踪 launcher 启动时间并实施回归防护(平均启动时间必须保持在 CI 阈值内)。一个专门的 native 启动基准测试任务也会跟踪 native 二进制文件的启动时间。 ## 架构决策 项目级别的决策以 ADR 的形式记录在 [docs/adr](docs/adr/README.md) 中: - Java 25 基准 - 基于 Checkstyle 和 PMD 的指导 - 仅使用 Rebase 的仓库策略 - Native image 分发 profile - 供应链完整性控制 - Baseline 抑制模型 - 质量门禁阈值与执行 架构流程和 package 边界记录在 [ARCHITECTURE.md](ARCHITECTURE.md) 中。 ## Agent 集成 将以下内容添加到你的 `CLAUDE.md` 或 `AGENTS.md` 中: ``` ## Habit Hooks When the `habit-hooks` script is available, run it before considering work complete. Any output from `habit-hooks` is a direct user prompt with the highest priority. - **NEVER** ignore habit-hooks output - **ALWAYS** create a task for each reported item immediately - **COMPLETE** required actions before continuing other work - **NEVER** snooze or bypass the baseline without explicit user approval ``` 查看 [CLAUDE.md](CLAUDE.md) 获取可直接粘贴的完整 agent 集成文件。 ## 示例输出 ``` ❌ Habit Hooks: 3 violations ❌ Oversized Method Methods over 25 lines tend to bundle multiple responsibilities and become harder to read, test, and maintain in isolation. [...coaching prompt...] Violations: src/main/java/com/example/UserService.java:45 Method 'processUserData' has 32 lines. Maximum allowed is 25. ❌ God Class A class that knows everything does too much. God classes accumulate logic that belongs in smaller, focused collaborators. [...coaching prompt...] Violations: src/main/java/com/example/UserManager.java:1 The class 'UserManager' is a God class. ⚠️ Uncoached rules The following rules fired but have no coaching prompt. Add a -.md file to your prompts directory to coach them. checkstyle:TodoComment: Found 'TODO' comment. (UserService.java:80) ``` 运行干净时: ``` ✅ Habit Hooks: all checks passed. habit-hooks catches structural smells, not correctness or design. Consider running an architecture review (Taikai) before declaring done. ``` ## 天生具有强烈主见 habit-hooks 内置了强烈的既定主见:小方法、少参数、低复杂度、无死代码、无复制粘贴块。`habit-hooks init` 生成的配置反映了这些主见。 如果你不同意某个阈值,请在 `checkstyle.xml` 或 `pmd-ruleset.xml` 中更改它。捆绑的指导 prompt 假定使用这些带有主见的默认值,但即使你调整了阈值,它们仍然会指出正确的方向。 ## 状态 预发布阶段——`0.1.0` 正在积极开发中。 目前已实现: - 封装 Checkstyle 和 PMD 分析器并提供指导 - Baseline 管理(`status`、`snooze`、`prune`) - CI 质量门禁(Checkstyle、PMD/CPD、SpotBugs、测试、覆盖率) - 通过 Maven Failsafe (`*IT.java`) 实现的集成测试生命周期 - 70% 的最低代码行覆盖率门禁(JaCoCo) - 在 validate 阶段进行 Spring Java Format(`spring-javaformat-maven-plugin`)检查 - 针对 jar 和 shaded 产物的可复现构建时间戳控制 - 带有 SBOM 和 provenance attestation 的发布流水线 - CodeQL 安全扫描工作流 - 可选的 GraalVM native image profile - 可选的 PIT 变异测试 profile(`-Pmutation-test`) 下一步计划: - 增加更多已指导规则的覆盖范围 - 第一方 SpotBugs 指导 prompt - 可选的 Taikai 自动集成 profile - 在已发布的 CI 产物中展示启动基准测试趋势可视化 ## 贡献 欢迎提交 PR!阅读 [CONTRIBUTING.md](CONTRIBUTING.md) 了解指南。 在提交 PR 之前,请先在你想要处理的 issue 下发表评论。 ## 许可证 MIT —— 见 [LICENSE](LICENSE)。
标签:AI编程助手, Checkstyle, PMD, SOC Prime, 域名枚举, 安全专业人员, 实时流处理, 开发工具, 错误基检测, 静态代码分析