# Auto Fix — 自动修复系统

> **Status**: Beta
> **Author**: Investibook Team
> **Date**: 2026-04-22
> **Scope**: Automated issue fixing, parallel worktree execution, PR creation

---

## 目录

- [1. 问题定义](#1-问题定义)
- [2. 系统架构](#2-系统架构)
- [3. 执行流程详解](#3-执行流程详解)
- [4. 并发模型](#4-并发模型)
- [5. Fixability 评估](#5-fixability-评估)
- [6. 与 Replayer 的关系](#6-与-replayer-的关系)
- [7. 使用方式](#7-使用方式)

---

## 1. 问题定义

### 1.1 核心挑战

Replayer 持续产出 issue（目前 34+ open），但修复依赖人工：

- 开发者需要读 issues.yaml、找 plan.md、理解上下文、手动实现修复
- 大量 issue 是 SKILL.md 的规则调整或简单的 UX 修复，模式固定
- 人工逐个修复效率低，issue 积压越来越多

### 1.2 Autofix 解决什么

Autofix 是 Replayer 闭环的**下半段**——自动消化 Replayer 产出的 issue：

```
Replayer                              Autofix

GitHub Issue --> Postmortem -->      issues.yaml --> Assess --> Fix --> PR
                 Score              (34 open)       |
                 Issue triage                       Skip if unclear
                 plan.md                            Draft if risky
```

核心价值：**将 P1/P2 的简单修复从"天级人工"降到"分钟级自动"。**

### 1.3 设计边界

Autofix 不试图修所有问题。它有明确的**能力边界**：

| 自动修复 | 需要人工审核 (Draft PR) | 跳过 |
|----------|------------------------|------|
| 单文件 SKILL.md 规则调整 | 多文件交叉依赖 | 无 fix_plan |
| 简单 UX 修复 | REASONING 类型 | fix_plan 说"investigate" |
| 内联 fix_plan 的 TOOLING 修复 | 修改 acp.py（高爆炸半径） | affects 文件不存在 |

**保守策略**：宁可不修、创建 Draft PR 让人审核，也不要引入新 bug。

---

## 2. 系统架构

### 2.1 端到端流程

```
issues.yaml (34 open)
     |
     | filter: status=open, has fix_plan, type eligible
     v
+--------------------------------------------+
| Phase 1: Load Issue                        |
|   Read issues.yaml, find ISS-NNNN          |
|   Extract: title, type, severity,          |
|     affects, fix_plan, github_issue        |
+-------------------+------------------------+
                    |
+-------------------v------------------------+
| Phase 2: Assess Fixability                 |
|                                            |
|   Auto-fixable  --> proceed                |
|   Needs review  --> proceed (draft=true)   |
|   Skip          --> abort with reason      |
+-------------------+------------------------+
                    |
+-------------------v------------------------+
| Phase 3: Create Branch                     |
|   git checkout -b fix/ISS-NNNN origin/main |
|   (or use existing worktree branch)        |
+-------------------+------------------------+
                    |
+-------------------v------------------------+
| Phase 4: Implement Fix                     |
|   Read affected files                      |
|   Follow fix_plan steps exactly            |
|   Match existing code style                |
+-------------------+------------------------+
                    |
+-------------------v------------------------+
| Phase 5: Validate                          |
|   Frontend: pnpm build                     |
|   Backend: py_compile                      |
|   SKILL.md: syntax check                   |
|   Max 3 attempts, then abort               |
+-------------------+------------------------+
                    |
+-------------------v------------------------+
| Phase 6: Commit & Push                     |
|   git add <specific files>                 |
|   git commit (conventional format)         |
|   git push -u origin fix/ISS-NNNN         |
+-------------------+------------------------+
                    |
+-------------------v------------------------+
| Phase 7: Create PR                         |
|   GitHub API: POST /repos/.../pulls        |
|   Regular or Draft based on Phase 2        |
|   Body: summary + fix_plan + validation    |
+-------------------+------------------------+
                    |
+-------------------v------------------------+
| Phase 8: Update issues.yaml                |
|   status: in_progress                      |
|   fixed_in: PR#xxx                         |
|   fix_source: autofix                      |
+--------------------------------------------+
```

### 2.2 与 Replayer 闭环

```
                    Replayer (发现问题)
                         |
                         v
User feedback ----> issues.yaml <---- Autofix Phase 8 (更新状态)
                         |
                         v
                    Autofix (修复问题)
                         |
                         v
                    PR merged
                         |
                         v
                    Regression (验证修复)
                         |
                         v
                    Issue status: fixed
```

完整日循环设想：

```
Daily cron
  |
  +--> Replayer Phase 0-8: postmortem 新的 GitHub issues --> 发现 issues
  |
  +--> Autofix: 修复 eligible issues --> 创建 PRs
  |
  +--> Human review: merge PRs
  |
  +--> Replayer regression: 验证修复不退化
```

---

## 3. 执行流程详解

### 3.1 Phase 1: Load Issue

从 `tools/replayer/issues/issues.yaml` 读取目标 issue。

```yaml
- id: ISS-0039
  title: Agent should check Activity Hub on node restart
  type: FLOW
  severity: P1-high
  status: open
  affects:
    - skill: tidb-clinic-diagnosis
      file: agentkit/skills/builtin/tidb-clinic-diagnosis/SKILL.md
  fix_plan: ISS-0039/plan.md
  found_in:
    - case: TCOC-5140
      ws: ws-1776646913272-b0d2b9b99
```

**中止条件**：
- `status` 不是 `open`
- `fix_plan` 为空或写着 "TODO"

如果 `fix_plan` 指向 `ISS-NNNN/plan.md`，读取完整计划。Plan 包含：背景、错误现象、根因分析、具体修复步骤、验证方法。

### 3.2 Phase 2: Assess Fixability

根据 issue 类型、影响范围、fix_plan 质量判断是否可以自动修复。

| 信号 | 判定 | 动作 |
|------|------|------|
| 单文件 + 内联 fix_plan | Auto-fixable | 正常 PR |
| `type: UX` + 明确 fix_plan | Auto-fixable | 正常 PR |
| `type: TEMPLATE/KNOWLEDGE` 改 SKILL.md | Auto-fixable | 正常 PR（需回归） |
| `type: TOOLING` + plan.md | Auto-fixable | 正常 PR |
| 多文件 + 交叉依赖 | Needs review | Draft PR |
| `type: REASONING` | Needs review | Draft PR |
| affects `acp.py` | Needs review | Draft PR（高爆炸半径） |
| 无 fix_plan / 写着 "investigate" | Skip | 不处理 |

### 3.3 Phase 4: Implement Fix

**核心原则**：

1. **Follow plan exactly** — fix_plan 说改什么就改什么，不自由发挥
2. **Minimal changes** — 只修 plan 指定的内容，不做"顺便优化"
3. **Read before write** — 先读完所有 affects 文件，理解现有代码再动手
4. **Match style** — 缩进、命名、模式与现有代码一致

```
Plan says:                          Agent does:
"Add rule after Node C"       -->  Read SKILL.md, find Node C, add rule inline
"Add error handling for X"    -->  Find the specific function, add minimal handling
"Fix URL template"            -->  Find the template, replace the URL
```

**不做的事**：
- 不加额外注释、docstring
- 不重构周围代码
- 不新建顶级 section（SKILL.md）
- 不添加 plan 未提及的功能

### 3.4 Phase 5: Validate

| 改了什么 | 验证命令 |
|----------|----------|
| Frontend `*.tsx` | `cd frontend && pnpm build` |
| Backend `*.py` | `python -m py_compile <file>` |
| SKILL.md | YAML/Markdown syntax check |

验证失败 → 修复 → 重新验证，最多 3 次。3 次后仍失败则放弃该 issue。

### 3.5 Phase 6-7: Commit → PR

Commit message 格式：

```
fix(ISS-NNNN): <title from issues.yaml>

<one-line description of what was changed>

Closes <github_issue URL>

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
```

PR body 包含：Summary、Fix Plan 摘要、Validation checklist、回归 case 列表（如果改了 SKILL.md）。

---

## 4. 并发模型

### 4.1 为什么用 Worktree

多个 issue 可能改同一个文件。如果在同一个 checkout 里串行修复，会有 merge 冲突。

Git worktree 提供**独立的工作目录**，共享同一个 `.git`：

```
.worktree/
  ISS-0026/    <-- branch fix/ISS-0026, 独立目录
  ISS-0028/    <-- branch fix/ISS-0028, 独立目录
  ISS-0035/    <-- branch fix/ISS-0035, 独立目录
```

每个 worktree 有独立的 Claude Code session，互不干扰。

### 4.2 为什么不用 Subagent

考虑过用 Claude Code 的 subagent（`Agent` tool）并发修复，但：

| 方案 | 优点 | 缺点 |
|------|------|------|
| Subagent | 共享 context，调度简单 | 文件冲突、共享 git 状态、agent 并发安全未知 |
| Worktree + 独立 session | 完全隔离、无冲突 | 需要外部编排、多个 Claude 实例 |

选择 worktree：**完全隔离更安全**，代价是多用几个 Claude session，但避免了并发写同一文件的风险。

### 4.3 run.sh 编排流程

```bash
tools/autofix/run.sh ISS-0026 ISS-0028 ISS-0035
```

```
run.sh
  |
  +-- for each ISS-NNNN:
  |     git worktree add .worktree/ISS-NNNN -b fix/ISS-NNNN origin/main
  |     cp .github_token to worktree
  |     claude -p "Fix ISS-NNNN ..." &   (background)
  |
  +-- wait all PIDs
  |
  +-- clean up worktrees (keep branches, they've been pushed)
  |
  +-- report: N issues processed, M failed
       logs at .worktree/*.log
```

---

## 5. Fixability 评估

### 5.1 Issue 选择标准

当被要求"修复所有可修的 issue"时，选择逻辑：

```
issues.yaml
  |
  | filter: status == open
  | filter: fix_plan not empty, not "TODO", not "investigate"
  | filter: type in [UX, TEMPLATE, TOOLING, KNOWLEDGE, FLOW]
  | filter: affects files exist on disk
  |
  | sort: severity desc (P0 > P1 > P2 > P3)
  | sort: type priority (TOOLING > UX > TEMPLATE > FLOW > KNOWLEDGE > REASONING)
  |
  v
Eligible issues
```

**跳过**：
- `type: REASONING` 且无具体 fix_plan（太抽象）
- `fix_plan` 写着 "investigate" 或 "evaluate"（研究性质，不是修复）
- `affects` 指向不存在的文件

### 5.2 P-Level 标准

| 级别 | 含义 | Autofix 优先级 |
|------|------|----------------|
| P0-critical | 系统不可用 | 立即修复 |
| P1-high | 核心功能缺陷 | 优先修复 |
| P2-medium | 体验或效率问题 | 正常修复 |
| P3-low | 改善建议 | 低优先级 |

实际使用中主要是 P1 和 P2。

---

## 6. 与 Replayer 的关系

```
Replayer                           Autofix
--------                           -------
产出 issues.yaml          <----->  消费 issues.yaml
产出 plan.md               ----->  读取 plan.md 实施修复
产出 expected.md           ----->  PR 描述引用回归 case
Phase 8 创建 GitHub issue  ----->  PR body links back
                                   Autofix 更新 issues.yaml status
```

**数据流向**：Replayer 写 → Autofix 读 → Autofix 写回状态

**时序**：
1. Replayer 先跑，发现问题、写 plan
2. Autofix 后跑，消费 plan、实施修复
3. PR merge 后，Replayer regression 验证修复

**不循环**：Autofix 只修 Replayer 发现的问题，不会自己创建新 issue。

---

## 7. 使用方式

### 7.1 单个 Issue（交互式）

在 Claude Code 中：

```
Fix ISS-0026
```

Agent 读取 SKILL.md，按 8 个 phase 执行。适合单个修复或需要人工介入的场景。

### 7.2 批量 Issue（串行）

```
Fix ISS-0026 ISS-0028 ISS-0035
```

在同一个 session 中依次修复，共享 branch。适合不冲突的 issue。

### 7.3 并行 Issue（推荐）

```bash
tools/autofix/run.sh ISS-0026 ISS-0028 ISS-0035
```

每个 issue 独立 worktree + 独立 session，完全隔离。适合批量修复。

日志输出到 `.worktree/ISS-NNNN.log`。

### 7.4 目录结构

```
tools/autofix/
|
+-- SKILL.md       # Agent instructions - 8 phase execution flow
+-- README.md      # This file - system design doc
+-- run.sh         # Parallel orchestrator (worktree + background sessions)
```
