patbaumgartner/habbit-hooks
GitHub: patbaumgartner/habbit-hooks
habit-hooks 将 Java 静态分析工具的违规报告转化为带修复指导的 AI 编程习惯,帮助 AI agent 产出更高质量的 Java 代码。
Stars: 0 | Forks: 0
# habit-hooks
[](https://github.com/patbaumgartner/habbit-hooks/actions/workflows/ci.yml)
[](https://opensource.org/licenses/MIT)
[](https://adoptium.net)
[](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, 域名枚举, 安全专业人员, 实时流处理, 开发工具, 错误基检测, 静态代码分析