AI 编程铁三角:03 Harness Engineering 入门

AI 编程铁三角:03 Harness Engineering 入门

模型是给定的,Harness 才是你能控制的

一个令人沮丧的场景

某天,你让 AI 助手帮你重构一个模块。

3 小时后,你发现:

csharp 复制代码
✓ 功能实现了
✗ 代码风格和项目不一致(它用了 var,你用 const)
✗ 目录结构被它改了(新增了 utils/helper.js)
✗ 测试文件被它删了(「我觉得不需要」)
✗ 留下了 10 个 TODO 注释(「后续优化」)

你问 AI:为什么这样改?

AI:我觉得这样更好...

问题 :AI 有能力,但没有边界

这就是 Harness Engineering 要解决的问题。


Harness Engineering 是什么

一句话定义:

Harness Engineering = AI Agent 的约束系统工程

核心理念

ini 复制代码
Agent = Model + Harness

Model(模型)= 马,提供能力
Harness(约束)= 缰绳,提供边界

你控制不了马的能力(模型是给定的) 但你可以设计缰绳(Harness 是你能控制的)

反直觉的洞察

很多人认为:

约束越多,AI 越不自由,效率越低

事实恰恰相反:

约束越清晰,AI 越确定该做什么,效率越高

例子

css 复制代码
无约束场景:
AI:这个数据结构用 Map 还是 Object?自己猜一个吧
    这个函数要不要加缓存?先加上再说
    这个模块放哪个目录?随便放一个

有约束场景:
AI:CLAUDE.md 说「使用 Object 而非 Map」
    「所有 I/O 操作都要加缓存」
    「工具函数放在 src/utils/」
→ 不用猜,直接做,效率更高

三大支柱

Harness Engineering 由三大支柱组成:

支柱一:Context Engineering(上下文工程)

核心问题:AI 看不到的信息等于不存在

AI 的上下文窗口
LAUDE.md ← 项目约定 CLAUDE.md ← 项目约定 AGENTS.md ← Agent 身份 代码注释 ← 逻辑说明> 设计文档 ← 架构决策 Git 状态 ← 项目上下文

实践要点

上下文类型 作用 如何管理
静态上下文 项目约定、代码规范 CLAUDE.md / AGENTS.md
动态上下文 运行状态、Git信息 自动注入或 Hook 抓取
记忆上下文 历史决策、长期知识 MEMORY.md / 日志系统

支柱二:Architectural Constraints(架构约束)

核心问题:如何给 AI 画清晰的边界

约束项 说明
目录结构 src/api/ 放接口
命名规范 camelCase 变量
代码风格 TypeScript strict
模块职责 每个 < 300 行
依赖规则 api 不能直接调用 db

实践要点

  • CLAUDE.md 定义核心约束
  • 测试套件验证约束
  • Pre-commit Hook 自动检查

支柱三:Entropy Management(熵管理)

核心问题:系统如何长期保持健康

实践项 说明
定期清理 删除死代码
约束验证 代码仍符合 CLAUDE.md
性能监控 关注关键指标
文档同步 代码和文档一致

熵增的表现

  • 代码风格不一致
  • 目录结构混乱
  • 测试覆盖率下降
  • 文档过时

背景

hot-trends 是一个 Python CLI 工具,用于抓取热榜文章并筛选 AI 相关内容。来自于前两篇 AI 编程铁三角:01 Superpowers 入门 [AI 编程铁三角:02 OpenSpec 入门] (mp.weixin.qq.com/s/WOTMhe8ji...) 的案例,完成 Harness 的搭建。

Level 1 Harness:5分钟搭建基础约束

Level 1 是最轻量的 Harness,只需要 CLAUDE.md + 测试 + Hook

第一步:编写 CLAUDE.md

在项目根目录创建 CLAUDE.md,定义项目的核心约束:

💡 如果你用 Claude Code。你用 /init 命令会自动扫描项目,识别技术栈、目录结构、常用命令生成CLAUDE.md的基础骨架。

markdown 复制代码
## 项目概述

Hot-Trends CLI 是一个 Python 命令行工具,主要用于抓取并筛选来自中文技术社区(掘金、知乎)的 AI 相关文章。它可以在终端中以表格形式展示结果,并支持导出为 JSON 或 Markdown 格式。

## 开发命令

```bash
# 安装依赖(可编辑模式)
pip install -e .

# 运行所有测试
pytest tests/ -v

# 运行单个测试文件
pytest tests/test_fetcher.py -v
pytest tests/test_filter.py -v
pytest tests/test_output.py -v

# 本地运行 CLI(安装后)
hot-trends
hot-trends -l 100 -v
hot-trends -o output.json

# 不安装直接运行 CLI
python -m src.main

## 架构设计

### Fetcher 模式
项目使用基类模式来管理数据源:
- `src/fetchers/base.py` - `BaseFetcher` 抽象类,定义接口
- `src/fetchers/juejin.py` - `JuejinFetcher` 实现掘金 API(支持分类)
- `src/fetchers/zhihu.py` - `ZhihuFetcher` 实现知乎热榜抓取

新增数据源应继承 `BaseFetcher` 并实现 `fetch_hot_trends(limit)` 方法,返回 `List[Article]`。

### 数据流
1. `main.py` 解析 CLI 参数,根据 `--source` (juejin/zhihu/all) 协调 fetchers
2. 从选定的 fetchers 收集文章
3. `AIFilter.filter_articles()` 按 AI 关键词过滤(可通过 `-k` 自定义)
4. `OutputFormatter` 显示表格,并可选择保存到文件

### 核心类
- `Article` (models.py) - 数据类,包含 `to_dict()` 方法用于序列化
- `AIFilter` (filter.py) - 基于关键词的过滤,带默认 AI 词库
- `OutputFormatter` (output.py) - 处理终端表格(rich)、JSON 和 Markdown 输出

## CLI 参数

| 参数 | 说明 |
|------|-------------|
| `-l, --limit` | 文章数量(默认:50) |
| `-o, --output` | 输出文件(.json 或 .md) |
| `-s, --source` | 数据源:juejin/zhihu/all(默认:juejin) |
| `-c, --category` | 掘金分类:backend/frontend/ai 等(默认:all) |
| `-k, --keywords` | 自定义关键词(逗号分隔,追加到默认值) |
| `-v, --verbose` | 详细日志 |

## 项目结构说明

- 测试使用 pytest fixtures 和 tmp_path 进行文件操作
- `openspec/` 目录包含使用 OpenSpec 格式的变更提案(非核心代码)
- Husky 通过 package.json 配置 git hooks

关键点CLAUDE.md 应该"刚好够用",覆盖核心决策点即可。这个配置适用于 hot-trends 这类 TypeScript CLI 项目,你可以根据自己的项目调整。

第二步:配置 Pre-commit Hook

Husky 是一个 Git Hook 管理工具,让你在提交代码前自动运行检查和测试。

安装 Husky(以 npm 项目为例):

bash 复制代码
npm install -D husky
npx husky init

husky init 会自动生成 .husky/pre-commit 文件,默认内容只有:

bash 复制代码
npm test

你可以根据项目需要编辑 .husky/pre-commit,增强 Hook 检查:

bash 复制代码
# Python 项目示例
pytest tests/ -v          # 运行测试
flake8 src/               # 代码风格检查
black --check src/        # 代码格式化检查

💡 不同语言的 Hook 示例

  • Python : pytest, flake8, black, mypy
  • Node.js/TypeScript : npm test, npm run lint, npx tsc --noEmit
  • Go : go test ./..., golangci-lint run
  • Java : mvn test, mvn checkstyle:check

这样每次提交代码时,都会自动验证代码质量、测试通过率和类型安全。

第三步:验证测试套件

hot-trends 项目在前两篇文章中已经创建了完整的测试套件:

bash 复制代码
tests/
├── test_fetcher.py   # 数据获取器测试(4个测试)
├── test_filter.py    # AI过滤器测试(7个测试)
└── test_output.py    # 输出格式化器测试(3个测试)

验证测试是否正常工作

bash 复制代码
pytest tests/ -v

应该看到类似输出:

ini 复制代码
tests/test_fetcher.py::test_fetcher_initialization PASSED                                                 [  7%]
tests/test_fetcher.py::test_fetcher_with_custom_params PASSED                                             [ 14%]
tests/test_fetcher.py::test_fetch_hot_trends_success PASSED                                               [ 21%]
tests/test_fetcher.py::test_fetch_hot_trends_failure PASSED                                               [ 28%]
tests/test_filter.py::test_default_keywords PASSED                                                        [ 35%]
tests/test_filter.py::test_custom_keywords PASSED                                                         [ 42%]
tests/test_filter.py::test_is_ai_related_by_title PASSED                                                  [ 50%]
tests/test_filter.py::test_is_ai_related_by_tags PASSED                                                   [ 57%]
tests/test_filter.py::test_not_ai_related PASSED                                                          [ 64%]
tests/test_filter.py::test_case_insensitive PASSED                                                        [ 71%]
tests/test_filter.py::test_filter_articles PASSED                                                         [ 78%]
tests/test_output.py::test_save_json PASSED                                                               [ 85%]
tests/test_output.py::test_save_markdown PASSED                                                           [ 92%]
tests/test_output.py::test_print_table PASSED                                                             [100%]

============================================== 14 passed in 0.24s ===============================================

💡 为什么需要测试?

  • Hook 会在提交前自动运行测试
  • 如果测试失败,提交会被阻止
  • 这确保了代码质量,防止有 bug 的代码进入仓库

如果没有测试怎么办?

如果你的项目还没有测试,可以先创建一个简单的冒烟测试:

python 复制代码
# tests/smoke_test.py
def test_smoke():
    """冒烟测试 - 确保测试框架正常工作"""
    assert True

验证 Level 1 Harness

**完成以上三步后,即使有 CLAUDE.md,AI 也不会自动遵循 Harness 流程。**要让 AI 真正遵循 Harness 流程,需要:

  • 1.在对话开始时明确声明 - 每次开始新任务时,主动说明将遵循 Harness Level 1 流程
  • 2.使用技能系统 - 通过 Skill 工具调用相关的 Harness 规范
  • 3.设置 Git Hooks - 在提交前强制检查是否遵循了流程

我们先用第一种方式在对话前声明(长期使用按第二种方式新增一个 Skill):

python 复制代码
你:请按照 Harness Engineering Level 1 流程来完成这个任务:
1. 先读取 CLAUDE.md 了解项目规范
2. 查看相关代码和测试文件
3. 先写测试(TDD)
4. 实现功能
5. 运行测试验证
6. 更新文档

任务:帮我优化输出格式,支持 CSV 导出

AI:(Step 1: 读取上下文)
    ✅ 已读取 CLAUDE.md 了解项目规范
    ✅ 已查看 src/output.py、src/models.py、src/main.py
    ✅ 已查看 tests/test_output.py 了解测试模式
    
    关键发现:
    - 现有输出格式:JSON、Markdown
    - OutputFormatter 类已有 save_json() 和 save_markdown() 方法
    - 测试使用 pytest fixtures 和 tmp_path
    - CLI 参数通过 argparse 解析
    
    (Step 2: 测试驱动开发 TDD)
    先编写测试用例(功能实现前):
    
    在 tests/test_output.py 中添加:
    ```python
    def test_save_csv(formatter, sample_articles, tmp_path):
        """测试CSV导出"""
        filepath = str(tmp_path / "test.csv")
        formatter.save_csv(sample_articles, filepath)
        
        assert os.path.exists(filepath)
        
        with open(filepath, 'r', encoding='utf-8-sig') as f:
            content = f.read()
        
        # 检查CSV头部
        assert "排名,标题,作者,来源,链接,阅读量,点赞,评论,标签" in content
        
        # 检查数据行
        assert "GPT-4使用指南" in content
        assert "张三" in content
        assert "1" in content
        assert "2000" in content
        assert "掘金" in content
    ```
    
    验证测试失败(TDD 原则):
    $ pytest tests/test_output.py::test_save_csv -v
    FAILED - AttributeError: 'OutputFormatter' object has no attribute 'save_csv'
    
    ✅ 测试如预期失败,因为 save_csv 方法还未实现
    
    (Step 3: 实现功能)
    在 src/output.py 中实现:
    
    1. 导入 csv 模块
    2. 新增 save_csv() 方法
       - 使用 utf-8-sig 编码确保 Excel 兼容
       - CSV 列名使用中文
       - 标签使用分号分隔
    3. 更新 format_output() 方法支持 CSV
    
    在 src/main.py 中更新 CLI 参数:
    - 更新 -o/--output 帮助文本
    - 在 -f/--format  choices 中增加 'csv'
    - 更新帮助信息示例
    
    (Step 4: 验证测试)
    运行测试验证:
    
    $ pytest tests/test_output.py -v
    tests/test_output.py::test_save_json PASSED [ 20%]
    tests/test_output.py::test_save_markdown PASSED [ 40%]
    tests/test_output.py::test_print_table PASSED [ 60%]
    tests/test_output.py::test_save_csv PASSED [ 80%]          ← 新增
    tests/test_output.py::test_format_output_with_csv PASSED [100%]  ← 新增
    
    $ pytest tests/ -v
    collected 16 items
    ... (所有测试通过)
    ============= 16 passed in 0.25s ==============
    
    ✅ 所有 16 个测试全部通过,包括新增的 2 个 CSV 测试
    
    实际运行 CLI 验证:
    $ python -m src.main -l 10 -o /tmp/test_ai_articles.csv -v
    🚀 开始抓取热榜...
    📊 抓取掘金热榜...
    ✅ 获取 10 篇掘金文章
    🎯 筛选出 5 篇AI相关文章
    ✅ 已保存到: /tmp/test_ai_articles.csv
    
    ✅ CSV 文件成功生成,包含完整的文章数据
    
    (Step 5: 更新文档)
    更新 CLAUDE.md:
    - 项目概述:增加 CSV 格式支持说明
    - 核心类描述:增加 CSV 输出
    - CLI 参数表格:增加 -f 参数说明
    
    ✓ 任务完成!

关键点:AI 不再是"自由发挥",而是基于明确的约束进行开发。这就是 Harness 的力量!

Level 1 效果对比

指标 无 Harness 有 Harness
代码风格一致性 60% 95%
测试覆盖率 65% 88%
文档同步率 50% 90%
返工率 30% 8%

关键改进

  • AI 不再"自由发挥",而是基于明确约束开发
  • 每次提交都自动验证,问题早发现早解决
  • 项目长期保持健康状态

Level 2 Harness:动态约束与自动化

Level 2 在 Level 1 基础上增加 动态上下文更多 Hook,让 AI 能感知项目实时状态。

增加动态上下文

动态上下文是指那些会随时间变化的项目状态信息,AI 需要了解这些实时信息才能做出更准确的决策。

objectivec 复制代码
静态上下文(不变或很少变化):
├── CLAUDE.md          ← 项目约定、架构设计
├── 代码规范            ← 命名规则、代码风格
└── 目录结构            ← 文件组织方式

动态上下文(经常变化):
├── Git 分支            ← 当前在哪个分支
├── 修改的文件          ← 哪些文件被改动了
├── 测试状态            ← 测试是否通过
├── 依赖版本            ← 安装了哪些包
└── 运行环境            ← Python/Node 版本等

创建脚本自动生成项目当前状态信息,让 AI 了解实时环境:

bash 复制代码
#!/bin/bash
# scripts/generate_context.sh

echo "# 项目动态上下文" > CONTEXT.md
echo "" >> CONTEXT.md
echo "生成时间: $(date)" >> CONTEXT.md
echo "" >> CONTEXT.md

# Git 信息
echo "## Git 状态" >> CONTEXT.md
echo "- 当前分支: $(git branch --show-current)" >> CONTEXT.md
echo "- 最后提交: $(git log -1 --oneline 2>/dev/null || echo '无')" >> CONTEXT.md
echo "- 未提交修改:" >> CONTEXT.md
git status --short 2>/dev/null | sed 's/^/  - /' >> CONTEXT.md
echo "" >> CONTEXT.md

# 测试状态
echo "## 测试状态" >> CONTEXT.md
if pytest tests/ -q --tb=no 2>/dev/null; then
    echo "- 测试结果: ✅ 全部通过" >> CONTEXT.md
else
    echo "- 测试结果: ❌ 有失败的测试" >> CONTEXT.md
fi
echo "" >> CONTEXT.md

# Python 环境
echo "## 环境信息" >> CONTEXT.md
echo "- Python 版本: $(python --version 2>&1)" >> CONTEXT.md
echo "- 已安装包:" >> CONTEXT.md
pip list 2>/dev/null | head -10 | sed 's/^/  - /' >> CONTEXT.md

CLAUDE.md 中添加:

markdown 复制代码
## 动态上下文

在执行任何任务前,先运行 `scripts/generate_context.sh` 生成最新的 CONTEXT.md,
然后读取它了解项目当前状态。

好处:AI 能感知 Git 分支、修改文件、测试状态等动态信息,做出更准确的决策。

增加 Hook 种类

Pre-commit Hook 增强:添加更智能的检查逻辑

bash 复制代码
#!/usr/bin/env sh

# 检查是否修改了核心文件(如 hot-trends 的 fetchers 目录)
CHANGED=$(git diff --cached --name-only)
if echo "$CHANGED" | grep -q "src/fetchers/"; then
  echo "⚠️  修改了数据抓取器,请确认:"
  echo "  1. 是否需要更新对应的测试?"
  echo "  2. 是否需要更新 API 文档?"
fi

# 运行测试
npm test

# 运行 lint
npm run lint

其他可选 Hook

  • pre-push: 推送前运行完整测试套件
  • commit-msg: 验证提交信息格式(如约定式提交)
  • post-merge: 合并后自动安装依赖

实际效果 :当你在 hot-trends 中修改 src/fetchers/zhihu.ts 时,Hook 会提醒你检查测试和文档。


Level 3 Harness:完整工程化体系

Level 3 是企业级的 Harness,适用于团队协作和大型项目。对于 hot-trends 这样的单人项目,可以根据需要选择性采用。

1. 多层约束

企业级 Harness 层级

层级 说明
L1: 企业规范 所有项目共享
L2: 团队规范 团队内共享
L3: 项目规范 项目特有
L4: 模块规范 模块级别

示例

  • L1: 公司要求所有项目使用 TypeScript strict mode
  • L2: 前端团队统一使用 React + Vite
  • L3: hot-trends 项目使用特定的目录结构(见 CLAUDE.md
  • L4: fetchers 模块有特殊的安全要求(如 API key 管理)

2. 纵深防御

通过多层验证确保代码质量:

层级 说明
第1层 CLAUDE.md 静态约束
第2层 测试套件验证边界
第3层 Pre-commit Hook 检查
第4层 CI/CD 自动验证
第5层 Code Review 最终把关

原理:每一层都有机会发现问题,越早发现成本越低。

hot-trends 实践

  • 第1层:CLAUDE.md 规定 fetcher 不能混入过滤逻辑
  • 第2层:单元测试验证每个模块功能
  • 第3层:Hook 在提交前自动运行 lint 和 test
  • 第4层:GitHub Actions CI 流程(可选)
  • 第5层:如果是团队项目,可以设置 PR 审查

3. 熵管理流程

建立定期检查机制,防止系统逐渐混乱:

markdown 复制代码
# 每周熵管理 Checklist

## 代码质量
- [ ] 运行 `npm run lint` 检查代码风格
- [ ] 运行 `npm test` 检查测试通过率
- [ ] 检查是否有新的 TODO 注释

## 文档同步
- [ ] 检查 CLAUDE.md 是否需要更新
- [ ] 检查 README 是否过时
- [ ] 检查 CHANGELOG 是否遗漏

## 依赖管理
- [ ] 运行 `npm outdated` 检查过期依赖
- [ ] 运行 `npm audit` 检查安全漏洞

熵增的表现

  • 代码风格不一致(如有的地方用 var,有的用 const
  • 目录结构混乱(如在 src/ 根目录直接放文件)
  • 测试覆盖率下降(新增代码没有测试)
  • 文档过时(README 中的使用说明与实际不符)

建议:对于 hot-trends 这样的个人项目,可以每月进行一次熵管理检查。


常见问题

Q1:Harness 会不会限制 AI 的创造力?

答案:不会。

Harness 约束的是边界 ,不是方法

scss 复制代码
约束:使用 TypeScript strict mode
AI 仍然自由:选择算法、设计模式、实现细节

约束:测试覆盖率 > 80%
AI 仍然自由:测试怎么写、测什么

约束:代码风格统一
AI 仍然自由:逻辑实现方式

Q2:CLAUDE.md 写多少合适?

答案:刚好够用。

复制代码
太少:AI 还是自己猜
太多:没人看,变成形式主义
刚好:覆盖核心决策点

建议

  • 项目概述:50-100字
  • 技术栈:列出主要技术
  • 目录结构:核心目录即可
  • 代码规范:5-10条核心规则
  • 质量要求:可量化的指标

Q3:和 Superpowers / OpenSpec 的关系?

复制代码
OpenSpec       → 定义「做什么」(需求约束)
Superpowers    → 定义「怎么按流程做」(流程约束)
Harness        → 定义「如何确保可控」(行为约束)

三者结合 = 完整的 AI 编程工程化体系

我们会在下一篇「铁三角导论」中详细讲解。


下一步

你已经学会了 Harness Engineering 的基本概念和实践,知道它如何给 AI 套上缰绳。

到此为止,你已经认识了「铁三角」的三个工具:

  1. Superpowers → 流程约束 ✅
  2. OpenSpec → 需求约束 ✅
  3. Harness Engineering → 行为约束 ✅

下一篇,我们来讲 铁三角导论:三层架构设计,揭示三者如何协同工作。


扩展阅读

相关推荐
周末程序猿1 小时前
技术总结|十分钟了解GEO
人工智能·aigc
guo_xiao_xiao_1 小时前
YOLOv11海上多场景船只目标检测数据集-980张-Boat-1
人工智能·yolo·目标检测
周末程序猿1 小时前
技术总结|十分钟了解大模型投毒
人工智能·aigc
漫游的渔夫1 小时前
前端开发者做 Agent:模型说执行就执行?先加 3 道闸门再碰真实业务
前端·人工智能·typescript
joshchen2151 小时前
强化学习基础(赵世钰)第一章
人工智能·深度学习·算法·机器学习·强化学习
拜特说1 小时前
RAG 进化史:从基础检索到智能体驱动
人工智能
weixin_398187751 小时前
YOLOv11改进:全维度动态卷积ODConv与C3k2模块创新
人工智能·yolo
李昊哲小课1 小时前
Hermes Agent Dashboard 二次开发指南
人工智能·智能体·hermesagent
MATLAB代码顾问1 小时前
RAG技术详解:从检索增强生成到知识库问答实战
人工智能