Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

第五章:垃圾收集 —— 与熵的持久战

即使有了完善的上下文工程和严格的架构约束,熵增仍然是不可避免的。驾驭工程的第三根支柱,是一套持续对抗熵增的机制。

熵增是不可避免的

漂移的本质

Agent 会复现代码库中已存在的模式。随着代码量增长:

时间 → 代码量 → 模式多样度 → 不一致性 → 熵

每个模式单独看都是合理的
但它们的组合可能产生不一致
再加上 Agent 偶尔引入的不理想模式
代码库逐渐漂移,偏离预期架构和风格

手动清理无法扩展

OpenAI 团队的惨痛教训:

手动清理的死循环

他们最初安排每周五(20% 时间)手动清理 Agent 引入的不一致。

结果: ├── 你清理的速度 << Agent 引入偏差的速度 ├── 清理期间 Agent 还在继续产出 └── 最终 → 清理只是杯水车薪

在 Agent 的高吞吐量下(每人每天 3.5 个 PR), 手动清理完全无法扩展 [1]。

用 Agent 对抗 Agent 的熵

自动化对抗自动化

解决方案是用自动化对抗自动化

graph TB
    subgraph "熵增循环"
        A1[编码 Agent] -->|产出代码| A2[代码库]
        A2 -->|积累偏差| A3[熵增]
    end
    
    subgraph "垃圾收集循环"
        B1[后台扫描 Agent] -->|检测偏差| A2
        B1 -->|发起重构 PR| B2[小而聚焦的 PR]
        B2 -->|快速审查| B3[自动合并]
        B3 -->|清理偏差| A2
    end
    
    A3 -.->|触发| B1

垃圾收集循环

OpenAI 团队建立的"垃圾收集"循环 [1]:

定期运行后台 Codex 任务
    ↓
扫描代码库中的偏差
    ├── 不一致的错误处理模式
    ├── 重复代码
    ├── 过时的文档
    └── 违反编码规范的地方
    ↓
更新质量等级
    ↓
发起有针对性的重构 Pull Request
    ↓
快速审查(通常 1 分钟内)
    ↓
自动合并

文档花园

垃圾收集也覆盖文档维护:

文档花园维护系统:
├── 专职 linter 验证知识库更新状况
├── CI 作业检查交叉链接和结构正确性
└── "doc-gardening" Agent 定期扫描过时文档并自动发起修复 PR

技术债务如同高息贷款

两种偿还策略

策略 A:持续小额偿还
├── 每天发现并解决不良模式
├── 在它们传播之前消灭
└── 成本:低,持续

策略 B:债务累积后痛苦偿还
├── 等到问题大到不可忽视
├── 批量处理
└── 成本:极高,阵痛期长

高 Agent 吞吐量下的债务复利

在低吞吐量环境中,策略 B 可能勉强可行。

但在高 Agent 吞吐量环境中(每人每天 3.5 个 PR), 让债务累积意味着灾难。

债务的复利会迅速吞噬你从 Agent 获得的所有效率增益。

合并策略的转变

吞吐量改变了合并的理念:

维度低吞吐量(传统)高吞吐量(Agent)
等待成本极高(阻塞大量后续 PR)
纠错成本低(Agent 可快速修复)
合并策略确保万无一失再合并最小化合并阻塞
修复方式人工审查后合并快速合并 + 后台修复
传统:最小化测试失败
Agent:最小化合并阻塞

实现垃圾收集系统

质量扫描器

# tools/quality_scanner.py
class QualityScanner:
    """代码库质量扫描器"""
    
    def __init__(self, config: Dict):
        self.rules = self._load_rules(config["rules_path"])
        self.thresholds = config["thresholds"]
    
    async def scan(self) -> ScanReport:
        """
        扫描代码库,检测偏差
        """
        findings = []
        
        # 1. 一致性检查
        consistency = await self._check_consistency()
        findings.extend(consistency)
        
        # 2. 模式偏差检测
        pattern_drift = await self._detect_pattern_drift()
        findings.extend(pattern_drift)
        
        # 3. 文档新鲜度
        doc_freshness = await self._check_documentation()
        findings.extend(doc_freshness)
        
        # 4. 死代码检测
        dead_code = await self._detect_dead_code()
        findings.extend(dead_code)
        
        return ScanReport(
            findings=findings,
            quality_score=self._compute_score(findings),
            auto_fixable=[f for f in findings if f.auto_fix],
        )
    
    async def _check_consistency(self) -> List[Finding]:
        """检查代码一致性"""
        findings = []
        
        # 检查错误处理风格是否统一
        error_styles = await self._detect_error_handling_styles()
        if len(error_styles) > 2:
            findings.append(Finding(
                type="consistency",
                severity="warning",
                message=f"发现 {len(error_styles)} 种错误处理风格",
                auto_fix=True,
                fix_description="统一为推荐的错误处理风格",
            ))
        
        return findings
    
    async def _detect_pattern_drift(self) -> List[Finding]:
        """检测模式漂移"""
        findings = []
        
        # 检查是否偏离了推荐的实现模式
        patterns = await self._analyze_patterns()
        for pattern in patterns:
            if pattern.drift_score > self.thresholds["drift"]:
                findings.append(Finding(
                    type="drift",
                    severity="info",
                    message=f"模式 '{pattern.name}' 出现漂移",
                    affected_files=pattern.files,
                ))
        
        return findings

自动重构 PR 生成

# tools/auto_refactor.py
class AutoRefactor:
    """自动重构 PR 生成器"""
    
    async def generate_refactor_pr(self, finding: Finding) -> PR:
        """
        根据发现的问题生成重构 PR
        """
        if not finding.auto_fix:
            return None
        
        # 生成修复代码
        fix = await self._generate_fix(finding)
        
        # 创建分支
        branch = f"gc/{finding.type}/{finding.id}"
        
        # 应用修复
        for file_path, changes in fix.changes.items():
            await self._apply_changes(file_path, changes)
        
        # 创建 PR
        pr = await self._create_pr(
            branch=branch,
            title=f"[GC] {finding.message}",
            body=self._generate_pr_description(finding, fix),
            labels=["auto-generated", "garbage-collection"],
        )
        
        return pr
    
    def _generate_pr_description(self, finding: Finding, fix: Fix) -> str:
        return f"""
## 垃圾收集自动修复

### 问题
{finding.message}

### 影响范围
{', '.join(finding.affected_files)}

### 修复方案
{fix.description}

### 变更
{fix.diff_summary}

---
此 PR 由垃圾收集系统自动生成。通常可在 1 分钟内完成审查。
"""

质量等级系统

# tools/quality_score.py
class QualityScorer:
    """代码库质量评分"""
    
    DIMENSIONS = {
        "consistency": {
            "weight": 0.3,
            "checks": ["error_handling_style", "naming_convention", "log_format"]
        },
        "architecture": {
            "weight": 0.3,
            "checks": ["dependency_direction", "module_boundary", "layer_separation"]
        },
        "documentation": {
            "weight": 0.2,
            "checks": ["doc_coverage", "doc_freshness", "cross_reference"]
        },
        "test_coverage": {
            "weight": 0.2,
            "checks": ["unit_coverage", "integration_coverage", "critical_path"]
        }
    }
    
    def compute_overall_score(self, scan_result: ScanReport) -> QualityReport:
        scores = {}
        
        for dim, config in self.DIMENSIONS.items():
            dim_findings = [f for f in scan_result.findings 
                          if any(c in f.type for c in config["checks"])]
            scores[dim] = self._score_dimension(dim_findings)
        
        overall = sum(
            scores[dim] * config["weight"]
            for dim, config in self.DIMENSIONS.items()
        )
        
        return QualityReport(
            overall=overall,
            dimensions=scores,
            trend=self._compute_trend(),
            recommendation=self._generate_recommendation(scores),
        )

监控熵的趋势

行业案例:Harness 迭代的必然性

垃圾收集不仅是代码层面的维护,更涉及整个 Harness 体系的持续迭代。以下案例说明了这一点:

Manus:6 个月,5 次 Harness 重写
├── 第 1 版:基础 Prompt → 迅速发现不够用
├── 第 2 版:加入 RAG → 上下文管理失控
├── 第 3 版:引入工具系统 → 工具间交互混乱
├── 第 4 版:分层架构 → 约束执行不够自动化
├── 第 5 版:完整的 Harness 体系 → 终于稳定
└── 启示:Harness 本身也会积累技术债务

LangChain:1 年,3 次架构重构
├── v1:单链式 Agent → 复杂任务无法处理
├── v2:Multi-Agent → Agent 间协调困难
├── v3:Harness + 规范化接口 → 走向成熟
└── 启示:不重构的 Harness 会成为新的瓶颈

Build to Delete 原则

一个健康的 Harness 应该被设计为可删除的

这不是说你会删除它,而是说: ├── 每个约束都有明确的存活条件 ├── 当约束不再需要时,应该能干净地移除 ├── Harness 自身也在被垃圾收集的范围内

如果你不敢删除某个约束,说明它还没有被正确编码。 如果你永远不删除约束,Harness 本身就会变成技术债务。

质量趋势追踪

质量得分趋势:

Week 1: ████████████████████ 0.95 (初始)
Week 2: ██████████████████░░ 0.88 (开始漂移)
Week 3: █████████████████░░░ 0.85 (GC 启动)
Week 4: ███████████████████░ 0.91 (GC 生效)
Week 5: ████████████████████ 0.94 (恢复)
Week 6: ████████████████████ 0.95 (稳定)

关键信号:
├── 连续 2 周下降 → 触发 GC 扫描
├── 单周下降 > 5% → 紧急扫描
└── 恢复后稳定 → GC 频率降低

告警规则

# 告警配置
alerts:
  - name: quality_drop
    condition: "quality_score < prev_week_score - 0.03"
    action: "trigger_gc_scan"
    
  - name: drift_accumulation
    condition: "drift_findings > 20"
    action: "schedule_refactor_batch"
    
  - name: doc_stale
    condition: "doc_freshness_score < 0.7"
    action: "trigger_doc_gardening"

实践指南

垃圾收集策略选择

项目阶段推荐策略频率
初始阶段手动清理 + 基础 linter每周
成长阶段半自动扫描 + 人工审查 PR每日
成熟阶段全自动扫描 + 自动 PR + 自动合并持续

关键指标

✅ 代码库质量得分趋势(目标:持续 > 0.85)
✅ GC 扫描发现的问题数(目标:持续下降)
✅ 自动修复 PR 的合并率(目标:> 90%)
✅ 文档新鲜度得分(目标:> 0.8)
✅ 模式一致性得分(目标:> 0.9)

快速检查清单

✅ 是否有自动化的代码库质量扫描?
✅ 是否有后台 Agent 定期扫描偏差?
✅ 扫描发现是否能自动生成修复 PR?
✅ 文档是否有自动新鲜度检查?
✅ 质量趋势是否有监控和告警?
✅ 合并策略是否适应高吞吐量?

小结

垃圾收集 Checklist

✅ 熵增不可避免,但可以控制 ✅ 用自动化对抗自动化 ✅ 技术债务持续小额偿还 ✅ 合并策略:最小化阻塞,而非最小化失败 ✅ 质量趋势监控 + 自动告警 ✅ 文档花园需要持续维护

参考文献:

  • [1] Ryan Lopopolo, "Harness engineering: leveraging Codex in an agent-first world", OpenAI, 2026
  • [2] Birgitta Böckeler, "Harness Engineering", martinfowler.com, 2026
  • [3] "模型不是关键,Harness 才是", 微信公众号, 2026

下一章,我们将进入方法论篇,深入探讨评估体系设计。