编程 Harness Engineering:2026年顶级AI工程师停止写代码的真相——从百万行代码实验到五大核心制品全解析

2026-08-16 06:15:18 +0800 CST views 8

Harness Engineering:2026年顶级AI工程师停止写代码的真相——从百万行代码实验到五大核心制品全解析

2026年2月,OpenAI一个小团队交付了100万行生产代码。没有一行是手写的。人类做的事情,是设计一套让AI Agent变得可靠的环境系统——这套系统现在有了名字:Harness Engineering

一、背景:为什么2026年所有人都在谈Harness

如果你在过去一年里用过AI编码助手(Claude Code、Cursor、Copilot、Codex),大概率经历过这样的崩溃时刻:

  • 让AI改一个按钮颜色,它直接把整个页面布局重写了
  • 明明说了「单文件不超过200行」,几轮对话后AI写了个1000行的巨无霸
  • 让AI修一个Bug,结果修出了三个新Bug
  • 跑了一晚上Agent,第二天发现它在一个循环里打了6小时转

这些问题在过去一年里被反复讨论。大多数人的解法是:换一个更强、更贵的模型

但2026年的数据告诉我们,这是一个方向性错误。

一个研究者对同一个AI模型、同一套测试基准做了两次实验。唯一不同的,是模型周围的Harness(缰绳系统)。

  • 第一次得分:42%
  • 第二次得分:78%

同一模型,36个百分点的差距,全部来自Harness。

LangChain在行业标准测试Terminal Bench 2.0上,用同样的模型,只是换了Harness,从30名开外跃升至前5名。

OpenAI的Codex团队用这套方法论,仅凭3人团队、0行手写代码、5个月时间,交付了超过100万行生产代码。

这意味着什么?

2026年,AI编程的瓶颈从来不在模型,而在你围绕模型搭建的那套「缰绳」够不够好。


二、核心概念:什么是Harness Engineering

2.1 最简洁的定义

ThoughtWorks给出了一个精准的公式:

Agent = Model + Harness

Harness是除了模型之外的一切

  • 约束Agent不跑偏的规则
  • 捕捉错误的反馈回路
  • 告诉Agent当前处境的文档
  • 它被允许使用的工具

去掉Harness,模型只能在代码库里瞎摸。加上合适的Harness,它就成了一个能交付生产代码的系统。

2.2 马具的隐喻

这个名字来自马具(Harness)。

一匹马强壮但不可预测。没有缰绳、鞍和嚼子,它想去哪就去哪。骑手的核心工作不是让马变聪明,而是通过装备设计让马的力量变得可控

AI Agent也是一样。模型很强大,但没有合适的Harness,它会:

  • 按自己的理解随意修改文件
  • 在同一个地方反复犯同样的错误
  • 上下文窗口耗尽后无声地丢弃需求
  • 产出的代码在本地能跑,上线就炸

Harness Engineering的目标,就是成为那套「缰绳+鞍+嚼子」。

2.3 操作系统类比:最精准的技术比喻

Hugging Face的Philipp Schmid给出了一个绝妙的技术类比:

传统系统AI Agent系统
CPU(原始算力)Model(原始推理能力)
内存(有限的、易失的工作内存)上下文窗口(有限的、易失的工作区)
操作系统(管理CPU看到什么、什么时候看到)Harness(管理模型的行为边界)
运行在上面的应用Agent(最终交付产物的载体)

模型很强大,但如果没有操作系统来管理内存、调度任务、执行规则,它就只是一块硅片。

大多数人在用Agent时,实际上缺少这样一个「操作系统层」——这也是为什么很多Agent在生产环境中不稳定。


三、2026年的关键实验:数据说话

3.1 OpenAI的百万行代码实验

2026年2月,OpenAI的Codex团队面临一个现实挑战:需要快速交付Sora Android应用,团队规模有限。

他们的解法不是雇更多人或换更强模型,而是设计了一套严格的Harness:

  1. 严格的依赖流规则:Types → Config → Repo → Service → Runtime → UI,每层只能依赖下层
  2. 分布式的AGENT.md文件:在代码库各角落嵌入AI引导文档
  3. Agent直连CI/CD:每次提交自动触发完整测试流水线
  4. JSON特性追踪器:跨会话记录每个特性的完成状态

结果:

  • 4名工程师,28天,Play Store排名第一
  • 崩溃率低于0.1%
  • Codex每周处理70%的内部Pull Request
  • 全程0行手写代码

3.2 Anthropic的三Agent架构实验

Anthropic遇到了另一个问题:当Agent评估自己的产出时,它倾向于给自己打高分——即使质量明显不达标。

自我评估行不通。Agent同时充当学生和老师,缺乏客观性。

他们的解法是三个专业化Agent

┌─────────────────────────────────────────┐
│            Sprint 规划阶段               │
│  ┌──────────┐  ┌──────────┐             │
│  │ Planner  │→ │Evaluator │→ 达成契约   │
│  │ (规划者) │  │ (评审者) │             │
│  └──────────┘  └──────────┘             │
│       ↑              ↑                   │
│  人类审查确认 ← 契约 ← 人类审查确认       │
└─────────────────────────────────────────┘
              ↓ 契约锁定
┌─────────────────────────────────────────┐
│            Sprint 执行阶段               │
│  ┌──────────┐  ┌──────────┐             │
│  │Generator │→ │Evaluator │→ 产出代码   │
│  │ (生成者) │  │ (评审者) │             │
│  └──────────┘  └──────────┘             │
└─────────────────────────────────────────┘
  • Planner:把两句话的提示词展开成完整的产品规格
  • Generator:每个sprint实现一个特性
  • Evaluator:用浏览器自动化测试运行中的应用,像真实用户一样操作

关键洞察:让一个独立的评估者变得严格,远比让生成者对自己的工作保持批判要容易得多。

效果对比(Anthropic A/B测试真实数据):

方案成本耗时结果
无Harness单Agent$920分钟UI可用,但核心功能有缺陷
完整Harness(3-Agent)$2006小时功能完备,UI精致,业务逻辑正确

22倍的成本差距,换来的是一个真正可交付的产品,而不是只在截图里好看的demo。

3.3 LangChain的Terminal Bench逆袭

LangChain在Terminal Bench 2.0上用同一个模型跑了两次:

  • 旧Harness:52.8分(30名开外)
  • 新Harness:66.5分(前5名)

唯一的区别就是Harness设计。

3.4 Vercel的减法哲学

Vercel走了相反的方向——他们砍掉了Agent 80%的工具

结果性能反而更好了。

这个发现很反直觉,但道理很简单:工具越多,Agent越容易陷入「工具选择瘫痪」,在决策上消耗的token比实际工作还多。


四、五大核心制品:Harness的具体构建块

4.1 制品一:AGENT.md / CLAUDE.md(上下文引导文件)

最通用、最容易上手的Harness制品。

这是分布在代码库各处的Markdown文件,Agent在每次会话开始时读取它们,就像新工程师入职时的引导文档。

# AGENT.md - 项目AI助手指南

## 技术栈
- 后端:Go 1.24 + GORM
- 前端:React 18 + TypeScript 5
- 数据库:PostgreSQL 17
- 部署:Docker + K8s

## 编码规范
- 单文件不超过200行
- 错误必须返回,panic只用于不可恢复场景
- 所有公共API必须有单元测试覆盖
- 提交前必须运行 `make lint && make test`

## 架构决策记录
- 使用六边形架构(Ports & Adapters)
- 数据库迁移使用 golang-migrate,不允许手动DDL
- API版本管理:/api/v1/* 前缀

## 当前进行中的工作
- 用户权限模块重构(进行中,预计本周完成)
- 不要修改 auth/ 目录下的文件(稳定区)

## 硬规则
- 禁止删除文件(只允许归档到 archived/ 目录)
- 禁止修改 .env 文件(配置变更走 ConfigMap)
- 所有数据库操作必须在事务中

核心原则(来自ETH Zurich对138个仓库的研究)

  1. 保持简短:60行以内。超过这个长度,Agent开始忽略它
  2. 只写通用规则:不要列目录(Agent可以自己发现)
  3. 不要条件规则:「如果做X则Y」会让Agent困惑
  4. 人类写,不要AI生成:研究发现AI生成的AGENT.md实际上会降低性能,且多消耗20%的token

4.2 制品二:JSON特性列表(进度追踪器)

当Agent跨多个会话构建一个完整应用时,每次会话的上下文窗口都是空白的。Agent怎么知道哪些已经做完了?

靠一个JSON文件。

{
  "project": "电商后端API",
  "version": "2.1.0",
  "lastUpdated": "2026-08-15T10:30:00Z",
  "features": [
    {
      "id": "auth-jwt",
      "name": "JWT认证",
      "status": "done",
      "verifiedAt": "2026-08-10",
      "verificationMethod": "e2e tests passed"
    },
    {
      "id": "product-crud",
      "name": "商品CRUD",
      "status": "done",
      "verifiedAt": "2026-08-12",
      "verificationMethod": "api tests passed"
    },
    {
      "id": "order-state-machine",
      "name": "订单状态机",
      "status": "in_progress",
      "startedAt": "2026-08-14",
      "blockers": ["payment-webhook integration not ready"],
      "acceptanceCriteria": [
        "pending→paid transition works",
        "paid→shipped transition works",
        "cancelled refunds inventory"
      ]
    },
    {
      "id": "inventory-reservation",
      "name": "库存预占",
      "status": "todo",
      "priority": "high",
      "dependsOn": ["order-state-machine"]
    }
  ]
}

Agent的会话启动序列:

1. 读取 progress.json
2. 找到 status="in_progress" 且无blockers 的特性
3. 读取该特性的 acceptanceCriteria
4. 实现功能
5. 运行验证
6. 更新 status="done" + verifiedAt
7. 提交代码

为什么用JSON而不是Markdown? Anthropic发现Agent意外覆盖JSON的概率比Markdown低得多。这在小细节,但在6小时无人值守运行中,这类差异的累积影响相当可观。

4.3 制品三:会话初始化例程(Session Init)

每次会话都用同样的方式启动。每一次都是。

Anthropic的7步启动序列:

# session_init.py - 每个Agent会话的第一个动作
def session_init():
    # Step 1: 确认工作目录
    current_dir = verify_workspace()

    # Step 2: 读取 git 日志和进度文件
    git_log = run("git log --oneline -20")
    progress = read_json("progress.json")

    # Step 3: 找到优先级最高的未完成项
    next_feature = find_next_feature(progress)

    # Step 4: 启动开发服务器(如果需要)
    if needs_dev_server(next_feature):
        start_dev_server()

    # Step 5: 运行基础端到端验证
    baseline = run_e2e_check()
    if baseline != "passing":
        log(f"⚠️ 基线检查未通过: {baseline}")
        # 记录但不阻塞

    # Step 6: 实现一个特性
    implement_feature(next_feature)

    # Step 7: 提交并更新进度
    commit_with_description(next_feature)
    update_progress(next_feature, "done")

没有这套流程,Agent需要花前20分钟搞清楚当前状态。有了它,Agent立刻进入工作状态。

4.4 制品四:Sprint契约(Sprint Contract)

在Agent写任何代码之前,先由两个Agent协商。

┌──────────────────────────────────────────────────────┐
│                  Sprint 契约协商                       │
│                                                      │
│   Generator Agent              Evaluator Agent       │
│   ┌─────────────┐             ┌─────────────┐       │
│   │「我要构建:  │ ──────────→ │「审查:      │       │
│   │  用户积分   │             │  方案完整?  │       │
│   │  等级系统」 │             │  验收标准   │       │
│   └─────────────┘             │  明确?」   │       │
│           ↑                   └─────────────┘       │
│           └──────────── 反馈/修改 ──────────── →     │
│                                                      │
│              ↓ 双方达成一致                           │
│         ┌─────────────────────┐                      │
│         │   契约锁定,开始实现   │                     │
│         └─────────────────────┘                      │
└──────────────────────────────────────────────────────┘

契约模板

{
  "sprintId": "sprint-2026-08-15-001",
  "feature": "用户积分等级系统",
  "generatorProposal": {
    "approach": "在 PostgreSQL 中使用 enum 存储等级,积分计算通过触发器自动更新",
    "files": ["models/user_level.go", "services/points.go", "migrations/xxx_add_level.sql"],
    "estimatedTokens": 8000
  },
  "evaluatorReview": {
    "completeness": "PASS - 覆盖所有验收标准",
    "successCriteria": [
      "积分增加后等级实时更新",
      "等级变更触发通知事件",
      "历史积分记录可查"
    ],
    "concerns": ["触发器方案在高频场景下性能需实测验证"],
    "decision": "CONDITIONAL_APPROVE - 先用触发器,性能瓶颈出现再优化"
  },
  "agreedContract": {
    "approach": "PostgreSQL 触发器方案",
    "verificationRequired": ["单元测试", "集成测试", "性能基准测试"],
    "rollbackPlan": "如果 QPS>1000 时 P99>50ms,切换为应用层计算"
  }
}

核心价值:这本质上是设计评审,只是参与者换成了AI。规划步骤由AI独立完成,能显著提升输出质量。

4.5 制品五:结构化任务模板(Impact Map)

在Agent写代码之前,Harness先分析真实代码库,产出一份基于实际情况的影响图:

# analyze_impact.py
def generate_impact_map(task: str) -> dict:
    """
    分析任务并产出基于真实代码库的影响图。
    不要臆造路径和API,全部基于代码库实际内容。
    """
    codebase = analyze_codebase()

    # 找到相关的真实文件
    relevant_files = find_related_files(task, codebase)

    # 找到真实存在的符号名(函数、结构体、接口)
    real_symbols = extract_symbols(relevant_files)

    # 找到可以遵循的现有模式
    existing_patterns = find_patterns(relevant_files)

    # 生成具体的验收标准
    acceptance_criteria = define_acceptance(task, real_symbols)

    return {
        "real_file_paths": relevant_files,
        "real_symbols": real_symbols,
        "existing_patterns": existing_patterns,
        "acceptance_criteria": acceptance_criteria,
        "estimated_scope": "medium"  # small/medium/large
    }

影响图示例输出

影响范围分析:用户积分等级系统

相关真实文件:
  - models/user.go          (User 结构体在此)
  - services/loyalty.go     (现有积分服务)
  - internal/event/         (事件系统)
  - migrations/             (数据库迁移)

真实符号名(可复用):
  - User.Level (enum)
  - LoyaltyService.AddPoints()
  - EventBus.Publish()

现有模式(遵循):
  - 所有 Service 以 *_test.go 结尾的测试文件
  - 错误返回格式:errors.Wrap(err, "context")
  - 事务边界在 Repository 层

验收标准:
  [1] 调用 AddPoints(100) 后 User.Points = 100 且 Level 自动计算
  [2] Level 变更触发 'user.level_changed' 事件
  [3] 历史积分可通过 /api/v1/users/:id/points 查询

为什么这很重要:大多数团队跳过这一步。结果Agent只能猜测文件结构,编造不存在的API端点,产出的代码与现有代码库风格脱节。先给Agent提供基于真实代码库的上下文,产出质量会好得多。


五、三大阵营的技术路线对比

三个团队撞上了同一堵墙,然后各自造了不同的梯子。

5.1 OpenAI:环境优先(Environment First)

核心理念:把环境设计得足够严密,让Agent产出的代码从一开始就具备可审查性。

核心机制

  1. 严格的依赖层次(Types → Config → Repo → Service → Runtime → UI)
  2. 分布式AGENT.md文件
  3. Agent直连CI/CD
# OpenAI Codex 的依赖流规则示例
dependency_rules:
  allowed_dependencies:
    - types: ["config", "errors"]
    - config: ["errors"]
    - repo: ["types", "config", "errors"]
    - service: ["repo", "types", "errors"]
    - runtime: ["service", "repo", "types", "errors"]
    - ui: ["runtime", "service", "repo", "types", "config", "errors"]
  enforcement: "strict"  # 违反则CI失败

适合场景:大型、长期维护的项目,代码质量要求高。

5.2 Anthropic:执行与评审分离(Separation of Duties)

核心理念:自我评估行不通。让生成者和评审者彻底分开。

核心机制:三个专业Agent(Planner/Generator/Evaluator)+ JSON进度追踪

关键原则

  • 一次只做一个sprint
  • 每个sprint必须有明确验收标准
  • Evaluator使用真实环境验证(浏览器自动化、API测试)
# Anthropic 风格的 Evaluator 实现
class BrowserEvaluator:
    """像真实用户一样操作,验证功能是否真正可用"""
    def evaluate(self, feature):
        self.browser.goto(f"http://localhost:{PORT}")

        if feature == "user_level_upgrade":
            # 模拟用户操作流程
            self.login_as("test_user")
            self.purchase_item(sku="premium_999")

            # 验证等级是否真的变了
            level = self.get_user_level()
            assert level > self.BASELINE_LEVEL, f"等级未更新: {level}"

            # 验证事件是否真的触发了
            event = self.wait_for_event("user.level_changed")
            assert event is not None, "事件未触发"

            return "PASS"

适合场景:对输出质量要求极高、需要像真实用户一样验证的场景。

5.3 ThoughtWorks:2×2框架(Feedforward × Feedback)

核心理念:将所有Harness控制沿两个维度分类,形成结构化矩阵。

计算型(确定性,毫秒级)推理型(LLM,秒级)
前馈(行动前)类型系统、Linter、架构规则规格文档、约束描述
反馈(行动后)测试套件、覆盖率分析、变异测试LLM代码审查器、行为验证器

核心洞察:只有前馈或只有反馈都不够,两者都需要。

前馈(Feedforward)= 引导Agent走向正确方向
反馈(Feedback)= 确认Agent没有走偏

没有反馈的Harness只是一个带了额外步骤的prompt。
没有前馈的Harness无法预防,只能事后救火。

适合场景:需要在架构层面建立长期规范的团队。


六、五条共识原则:三个团队殊途同归

三个团队从未协调过,但独立得出了完全相同的结论。

原则一:上下文胜过指令

让Agent看到世界的当前状态,效果始终优于抽象地告诉它该做什么。

❌ 错误做法:
"在这个项目里,User 结构体在 models/user.go,
积分服务在 services/loyalty.go,请遵循现有模式"

✅ 正确做法:
直接给Agent真实文件路径、真实符号名、真实验收标准
让它自己去理解和遵循

基于真实文件路径工作,产出的代码自然能融入代码库。基于模糊描述工作,结果往往是臆造的文件路径和编造的API。

原则二:规划和执行必须分开

让Agent在同一个pass里既规划又执行,产出不可靠。

❌ 错误做法:
"实现一个用户积分系统,请先规划方案再实现"

✅ 正确做法:
先运行独立的规划阶段(Planner Agent / Sprint契约)
产出物经过审查后,才开始实现

规划步骤不一定要人来完成,但它必须是一个独立的环节,产出物在实现开始前需要经过审查。

原则三:反馈回路不可商量

没有反馈的Harness只是一个带了额外步骤的prompt。

前馈(告诉Agent该做什么)
    +
反馈(告诉Agent做对了没有)
    ↓
真正的Harness

OpenAI让Agent接入CI/CD和可观测性系统。Anthropic使用专门的Evaluator Agent通过浏览器自动化进行测试。ThoughtWorks将其形式化为「传感器」。

三种方案,同一条原则。

原则四:一次只做一件事

试图一次做太多的Agent会耗尽上下文,失去连贯性,无声地丢弃需求。

Anthropic的标准流程:

读取进度 → 选一个特性 → 实现 → 提交 → 重复

强制渐进式推进,是每个成功Harness的共性。

原则五:代码库本身就是文档

如果一条规范、约束或架构决策没有写在代码库里,Agent就不会知道。

没有人为Agent单独维护一个知识库。仓库本身就是唯一的事实来源。


七、悖论:为了删除而构建

7.1 Harness衰减(Harness Decay)是真实的

Anthropic从Opus 4.5升级到Opus 4.6时,Sprint分解这个原本不可或缺的环节变得多余了——模型规划能力的提升使它不再必要。

Opus 4.5: Sprint分解 + 逐Sprint评估
Opus 4.6: 去掉Sprint分解 + 单次评估(节省38%成本)
Opus 4.7: 模型开始自验证 → Evaluator角色进一步缩小

这就是Harness衰减。Harness中的每个组件都编码了一个「模型做不到什么」的假设。随着模型能力提升,这些假设逐渐过期,对应的组件变成了负担。

7.2 Build to Delete

Philipp Schmid的建议:Build to delete

设计每个Harness组件时就考虑它是可移除的。
定期关掉某个组件,看输出质量是否有变化。
如果没变化——删掉它。
  • Manus在6个月里重构了5次Harness
  • LangChain一年调整了3次
  • Vercel砍掉80%的工具后性能反而更好

这些频繁的重构不是工程能力不足的表现,而是在快速进步的模型之上构建系统的必然结果。

保留无用的Harness组件,每次运行都会消耗额外的token,却没有任何质量收益。

7.3 成本趋势:更好的模型 = 更简单的Harness = 更便宜

更好的模型
    ↓
模型能力提升,部分Harness组件变多余
    ↓
删掉过时组件
    ↓
运行成本降低,产出速度加快

趋势线:更好的模型 = 更简单的Harness = 更便宜的运行 = 更快的产出


八、工程实战:手写一个最小化Harness系统

理论讲完了,来点实际的。我们手写一个最小化的Harness系统,感受一下它的运作方式。

8.1 核心结构

project/
├── .harness/
│   ├── config.json          # Harness配置
│   ├── progress.json        # 进度追踪
│   └── rules/
│       ├── architecture.md  # 架构规则
│       ├── testing.md       # 测试规范
│       └── git.md           # Git规范
├── agent.py                 # Agent入口
└── session_init.py          # 会话初始化

8.2 Harness配置

// .harness/config.json
{
  "version": "1.0.0",
  "model": "claude-sonnet-4",
  "context": {
    "maxTokens": 180000,
    "strategy": "progressive"  // 渐进式上下文:按需加载skills
  },
  "tools": {
    "allowed": ["read", "edit", "exec", "grep", "test"],
    "denied": ["delete", "trash"],
    "requireConfirmation": ["git push --force", "DROP TABLE"]
  },
  "quality": {
    "minTestCoverage": 80,
    "lintStrict": true,
    "requireReview": true
  },
  "feedback": {
    "preCommit": ["make lint", "make test"],
    "postCommit": ["make build"],
    "onFailure": ["save_context", "log_error"]
  }
}

8.3 Agent入口

#!/usr/bin/env python3
# agent.py - Harness-aware AI Agent入口

import json
import subprocess
from pathlib import Path
from session_init import SessionInit

class HarnessAgent:
    def __init__(self, workspace: str):
        self.workspace = Path(workspace)
        self.harness_dir = self.workspace / ".harness"
        self.config = self._load_config()
        self.progress = self._load_progress()

    def _load_config(self) -> dict:
        with open(self.harness_dir / "config.json") as f:
            return json.load(f)

    def _load_progress(self) -> dict:
        progress_file = self.harness_dir / "progress.json"
        if progress_file.exists():
            with open(progress_file) as f:
                return json.load(f)
        return {"features": []}

    def run(self):
        # 会话初始化
        init = SessionInit(self.workspace, self.config, self.progress)
        session_context = init.execute()

        # 选择下一个工作项
        next_feature = self._select_next_feature()

        if not next_feature:
            print("✅ 所有特性已完成")
            return

        print(f"📋 开始实现: {next_feature['name']}")
        print(f"   验收标准: {next_feature['acceptanceCriteria']}")

        # 实现特性
        self._implement(next_feature, session_context)

        # 反馈验证
        if self._verify(next_feature):
            self._mark_done(next_feature)
            self._commit(next_feature)
        else:
            print("❌ 验证失败,保留工作区供人工介入")

    def _select_next_feature(self) -> dict | None:
        """选择优先级最高且无blockers的未完成特性"""
        for feature in self.progress.get("features", []):
            if feature.get("status") != "done":
                blockers = feature.get("blockers", [])
                if not blockers:
                    return feature
        return None

    def _implement(self, feature: dict, context: dict):
        """实现特性(调用AI模型)"""
        prompt = self._build_prompt(feature, context)
        # 这里调用实际的AI模型(Claude API / OpenAI API等)
        result = self._call_model(prompt)

        # 应用变更
        self._apply_changes(result)

    def _verify(self, feature: dict) -> bool:
        """运行质量门禁"""
        print("🔍 运行质量门禁...")

        # 前馈检查
        checks = self.config.get("quality", {})
        if checks.get("minTestCoverage"):
            coverage = self._run_coverage()
            if coverage < checks["minTestCoverage"]:
                print(f"❌ 覆盖率不足: {coverage}% < {checks['minTestCoverage']}%")
                return False

        # 执行预提交检查
        for cmd in self.config.get("feedback", {}).get("preCommit", []):
            result = subprocess.run(cmd, shell=True, capture_output=True)
            if result.returncode != 0:
                print(f"❌ 前馈检查失败: {cmd}")
                print(result.stderr.decode())
                return False

        print("✅ 质量门禁通过")
        return True

    def _mark_done(self, feature: dict):
        """更新进度文件"""
        for f in self.progress["features"]:
            if f["id"] == feature["id"]:
                f["status"] = "done"
                f["verifiedAt"] = subprocess.run(
                    ["date", "-u", "+%Y-%m-%dT%H:%M:%SZ"],
                    capture_output=True, text=True
                ).stdout.strip()
                break

        with open(self.harness_dir / "progress.json", "w") as f:
            json.dump(self.progress, f, indent=2)

    def _commit(self, feature: dict):
        """提交代码"""
        subprocess.run(["git", "add", "-A"], check=True)
        subprocess.run([
            "git", "commit", "-m",
            f"feat: {feature['name']} ({feature['id']})"
        ], check=True)
        print(f"✅ 已提交: {feature['name']}")


if __name__ == "__main__":
    import sys
    workspace = sys.argv[1] if len(sys.argv) > 1 else "."
    agent = HarnessAgent(workspace)
    agent.run()

8.4 会话初始化

# session_init.py

import subprocess
import json
from pathlib import Path

class SessionInit:
    def __init__(self, workspace, config, progress):
        self.workspace = Path(workspace)
        self.config = config
        self.progress = progress

    def execute(self) -> dict:
        """执行7步会话初始化"""
        print("🔧 Harness会话初始化...")

        # Step 1: 确认工作目录
        self._verify_workspace()

        # Step 2: 读取git日志和进度
        git_log = self._read_git_log()
        last_session = self._get_last_session_info(git_log)

        # Step 3: 分析代码库状态
        codebase_state = self._analyze_codebase()

        # Step 4: 构建上下文摘要
        context = {
            "workspace": str(self.workspace),
            "git_log": git_log,
            "last_session": last_session,
            "codebase_state": codebase_state,
            "config": self.config,
            "progress": self.progress
        }

        # Step 5: 读取架构规则
        rules = self._load_rules()

        # Step 6: 构建Agent上下文提示
        agent_context = self._build_context_prompt(context, rules)

        # Step 7: 验证基线状态
        self._verify_baseline(context)

        print("✅ 初始化完成\n")
        return context

    def _read_git_log(self) -> str:
        """读取最近20条git提交"""
        result = subprocess.run(
            ["git", "log", "--oneline", "-20"],
            capture_output=True, text=True, cwd=self.workspace
        )
        return result.stdout

    def _analyze_codebase(self) -> dict:
        """分析代码库结构"""
        stats = {
            "files": 0,
            "lines": 0,
            "languages": {},
            "test_coverage": 0.0
        }

        # 统计文件
        for ext in ["*.go", "*.py", "*.ts", "*.js"]:
            files = list(self.workspace.rglob(ext))
            stats["files"] += len(files)

        # 运行覆盖率(如果存在)
        coverage_result = subprocess.run(
            ["make", "coverage"],
            capture_output=True, cwd=self.workspace
        )
        if coverage_result.returncode == 0:
            # 解析覆盖率输出
            stats["test_coverage"] = self._parse_coverage(coverage_result.stdout)

        return stats

    def _load_rules(self) -> dict:
        """加载Harness规则文件"""
        rules_dir = self.workspace / ".harness" / "rules"
        rules = {}
        for md_file in rules_dir.glob("*.md"):
            rules[md_file.stem] = md_file.read_text()
        return rules

    def _build_context_prompt(self, context: dict, rules: dict) -> str:
        """构建注入给AI模型的上下文"""
        lines = [
            "# 会话上下文",
            "",
            f"工作目录: {context['workspace']}",
            f"代码库统计: {context['codebase_state']['files']} 文件, "
            f"{context['codebase_state']['test_coverage']}% 测试覆盖率",
            "",
            "## 最近Git提交",
            context["git_log"],
            "",
            "## Harness规则",
        ]

        for name, content in rules.items():
            lines.append(f"\n### {name}.md")
            lines.append(content)

        return "\n".join(lines)

九、2026年的工程现实:这套方法论值多少钱?

9.1 成本-质量权衡

Anthropic的A/B测试数据非常清晰:

方案成本产出质量
无Harness$9/次Demo级(看起来能用,上线就崩)
完整Harness$200/次生产级(功能完备,可交付)

22倍成本差距换来的是从不可用到可交付的质变。

对于核心业务系统,一次生产故障的代价远超$191。对于快速迭代的创业项目,无Harness的快速产出反而更划算。

9.2 模型升级的影响

模型升级(如Opus 4.5 → 4.6)
    ↓
Harness成本下降(部分组件不再必要)
    ↓
但绝对成本仍在上升(更好的模型更贵)
    ↓
最终趋势:
  更好的模型 + 更简单的Harness = 性价比持续提升

9.3 哪些团队真正需要这套方法论?

需要Harness Engineering的团队

  • 大型、长期维护的代码库(>10万行)
  • 对代码质量要求高的团队(金融、医疗、航空)
  • 需要无人值守AI Agent的场景(CI/CD流水线)
  • 多团队协作的大型项目

不一定需要的团队

  • 快速MVP验证阶段
  • 小型一次性项目
  • 高度临时的实验代码

十、总结:环境比模型更重要

2026年,Harness Engineering之所以重要,是因为它揭示了一个被长期忽视的真相:

AI编程的瓶颈,从来不在模型多聪明,而在你围绕模型搭建的那套缰绳够不够好。

LangChain用同一个模型,从30名开外跃升至前5名,靠的不是换模型。

OpenAI用3人团队交付100万行生产代码,靠的不是雇更多程序员。

Anthropic用$200成本做出真正可交付的产品,靠的不是用最强的模型。

他们共同做的一件事是:停止追逐更好的模型,开始设计更好的环境。

对于正在择业、想提升或刚入门的程序员来说,这个趋势意味着什么?

2026年的核心竞争力,不是「会写代码」,而是「会设计让AI可靠工作的环境」。

你会写prompt不等于你懂Harness。你会调用API不等于你能构建可靠的反馈回路。

Harness Engineering是AI工程时代的第一性原理。它不是某个框架,不是某个工具,而是理解AI Agent系统如何真正运作的底层逻辑。

现在学它,你领先半步。
等所有人都在谈的时候,你已经在设计下一代Harness了。


附录:Harness Engineering快速检查清单

□  每个仓库有 AGENT.md / CLAUDE.md(<60行,人类编写)
□  有 JSON 格式的进度追踪器
□  有固定的会话初始化流程
□  规划和执行是分离的(独立评审环节)
□  有明确的反馈回路(测试、CI/CD、可观测性)
□  一次只做一个sprint/特性
□  定期运行 Build-to-Delete 检查
□  代码库结构本身就是文档(无需额外知识库)

本文覆盖的五大核心制品、三个技术阵营、五条共识原则,均基于2026年真实工程实践数据。如有疏漏,欢迎指正。

推荐文章

MCP 测试文章 17812
2026-08-13 06:21:50 +0800 CST
【SQL注入】关于GORM的SQL注入问题
2024-11-19 06:54:57 +0800 CST
程序员茄子在线接单