# 核心概念速查

## Harness Engineering 三大支柱

### Context Engineering（上下文工程）

管理信息的可访问性、结构和时机。核心原则：**"Agent 无法在上下文中访问的信息不存在。"**

**静态上下文：**
- CLAUDE.md / AGENTS.md: 项目级持久上下文
- 设计文档: 架构决策、约束条件
- 代码规范: 命名约定、风格指南

**动态上下文：**
- 日志与指标: 运行时状态
- Git 状态: 分支、变更、提交历史
- CI/CD 状态: 构建结果、部署状态

**上下文压缩（四级管道）：**

```
Level 1: Snip（历史截断）
  - 成本：极低 | 延迟：~0ms
  - 释放少量 token

Level 2: Microcompact（老化工具结果缩减）
  - 成本：低 | 延迟：~1ms
  - 边界消息延迟到 API 响应后

Level 3: Context-Collapse（读时投射，不修改数组）
  - 成本：中 | 延迟：~5ms
  - summary messages live in collapse store
  - 完全可逆，跨轮次持久化

Level 4: Autocompact（LLM 全对话摘要）
  - 成本：高 | 延迟：~2s
  - 仅在前面三级无法解决问题时触发
```

**渐进式压缩经济学**：四级本质是成本阶梯，每一级仅在前一级不足时触发。90% 的日常情况由 Snip 解决，避免"用大炮打蚊子"。

### Architectural Constraints（架构约束）

通过机械执行而非建议来建立边界。防御不依赖于"Agent 听话"，而是依赖于"Agent 无法突破"。

**权限模型：**
- 5 种权限模式 × 7 级规则层级（详见安全模型章节）
- Schema 验证、并发安全标记
- 工具约束：只读 / 写入 / 破坏性分类

**安全边界：**
- 沙盒隔离：文件系统、网络、进程
- 硬编码拒绝：不可绕过的安全规则
- 纵深防御：6 层叠加使绕过概率指数下降

### Entropy Management（熵管理）

定期清理 Agent 解决代码退化。"代码不写会腐化，Agent 不治会退化。"

- 文档一致性验证
- 约束违规扫描
- 模式强制执行
- 依赖审计
- 性能监控
- 覆盖率守卫

---

## 三组件虚拟化架构

### Session（会话）—— 系统唯一事实来源

**Session-WAL 类比深解：**

Session 日志的设计理念直接借鉴数据库 Write-Ahead Log（WAL）和 git reflog —— 三者共享同一范式：

| 特性 | Database WAL | Git Reflog | Session Log |
|------|-------------|------------|-------------|
| 写入模式 | Append-only | Append-only | Append-only |
| 可变性 | 不可变 | 不可变 | 不可变 |
| 回放性 | 可重建数据库状态 | 可回溯所有 HEAD 变更 | 可重建完整对话状态 |
| 时序保证 | 严格有序 | 严格有序 | 严格有序 |
| 事实来源 | 数据库唯一真相 | Git 引用唯一真相 | 对话唯一真相 |
| 截断策略 | Checkpoint 后可截断 | GC 后可清理 | Autocompact 后可压缩 |

**为什么 Session 必须是 Append-only？**

```
┌──────────────────────────────────────────────────────────────┐
│  Session Log (JSONL, append-only)                            │
├──────────────────────────────────────────────────────────────┤
│  {"event":"turn_start","ts":"T0"}                            │
│  {"event":"user_message","ts":"T1","content":"帮我重构模块A"} │
│  {"event":"assistant_text","ts":"T2","content":"好的，我..."} │
│  {"event":"tool_use","ts":"T3","tool":"read","args":{...}}   │
│  {"event":"tool_result","ts":"T4","content":"..."}           │
│  {"event":"turn_end","ts":"T5"}                              │
│  ─── 不可逆边界：以上事件永不修改 ───                         │
│  {"event":"turn_start","ts":"T6"}                            │
│  ...                                                         │
└──────────────────────────────────────────────────────────────┘
```

任何时刻，完整对话状态可以通过**从头回放** Session 日志重建。这带来了三个关键能力：

1. **崩溃恢复**：Harness 崩溃后，重新加载 Session 日志，从最后 `turn_end` 之后继续执行——无状态丢失。
2. **审计追踪**：每次权限检查、每个工具调用、每轮 LLM 交互都被记录，不可篡改。
3. **跨实例迁移**：Session 可以序列化到磁盘，重新加载到另一个进程/机器，无缝继续。

**事件类型全集：**
- `user_message`: 用户输入
- `assistant_text`: 模型生成文本
- `tool_use`: 工具调用请求
- `tool_result`: 工具执行结果
- `turn_start` / `turn_end`: 轮次边界
- `compact_event`: 压缩标记（压缩后的摘要锚点）
- `error_event`: 错误记录（含恢复路径）

### Harness（编排器）—— 无状态性证明

Harness 的无状态性不是"设计选择"，而是**架构必然性**——如果 Harness 持有本地状态，则崩溃恢复和跨实例迁移都需要额外的状态同步机制。

**无状态性证明：**

```
前提 1: Harness 的全部输入来自 Session 日志（已证明）。
前提 2: Session 日志是 Append-only + 完全可回放（已证明）。
前提 3: LLM API 是纯函数（相同的 messages + system_prompt + tools → 相同的统计分布输出）。

结论: 给定同样的 Session 日志文件，任何 Harness 实例都会做出同样的编排决策。
```

**核心循环（抽象表示，非可执行代码）：**

```
┌──────────────────────────────────────┐
│  ENTRY: session = SessionLog.load()  │  ← 全量加载，重建状态
│        messages = session.replay()   │
├──────────────────────────────────────┤
│  LOOP:                               │
│    1. 压缩管道评估                   │  ← 四级压缩判定
│    2. 构建系统提示 + 规范化消息       │  ← 提示注入 + 缓存前缀
│    3. 调用 LLM API（流式）           │  ← 模型推理
│    4. 收集 tool_use 块               │  ← 工具调用收集
│    5. 错误恢复（7 个 continue 站点）  │  ← 容错路径
│    6. 权限检查 → 工具执行            │  ← 6 层防御链
│    7. Stop Hook → 终止或继续         │  ← 退出门控
│    8. 追加事件到 Session → CONTINUE  │  ← 持久化，然后循环
└──────────────────────────────────────┘
  Key invariant: Harness 不持有任何可变本地状态。
  session.append(event) 是 Harness 唯一的"副作用"。
```

**崩溃→重启→恢复证明：**

```
Step 0: Harness 执行到 Loop 第 4 步（正在收集 tool_use 块）
Step 1: 进程崩溃（OOM / kill -9 / 断电）
Step 2: Session 日志中最后一条记录：turn_start (ts=T6)
Step 3: 新 Harness 实例启动
Step 4: session.replay() → 重建到 T6 的完整消息列表
Step 5: Harness 重新构建 system prompt + messages
Step 6: 再次调用 LLM API —— 由于同样输入，模型返回同样（分布）输出
Step 7: 从 T6 继续执行，好像什么都没发生过
```

**跨实例迁移证明：**
Harness-A 写入 Session → 序列化到磁盘 → Harness-B 在同一文件上执行 `replay()` → 状态完全一致。迁移开销仅为 JSONL 文件的 I/O 时间。

### Sandbox（沙箱）—— 隔离执行环境

**三层隔离：**
1. **文件系统隔离**: Agent 只能访问为其分配的工作目录。路径解析消除符号链接和 `..` 逃逸。
2. **网络隔离**: 默认禁止出站网络，通过白名单控制。
3. **进程隔离**: 子进程在受限环境中运行，禁止 `fork`/`exec` 链，管道和重定向受限。

**凭证生命周期：**
```
创建 → 存储（加密）→ 注入（只读挂载）→ 使用 → 轮换 → 吊销
```

Agent 不持有原始凭证。Agent 通过 `credentials_request` 请求，宿主环境注入一次性环境变量。

---

## 权限与安全模型（完整版）

### 5 种权限模式

| 模式 | 含义 | 适用场景 |
|------|------|----------|
| `default` | 继承 `settings.json` 全局设置 | 普通操作 |
| `accept_edits` | 自动接受文件编辑，其他仍需确认 | 可信仓库开发 |
| `bypass_permissions` | 跳过所有权限检查（仅限 IDE 集成场景） | IDE 内可信环境 |
| `plan` | 只读模式，仅允许分析类操作 | 调研 / 代码审查 |
| `accept_all` | 自动批准所有（最高危，不推荐） | 无人值守 CI |

### 7 级规则层级（优先级递减）

1. **Hardcoded Deny** — 编译期注入，运行时不可变。覆盖一切。
2. **Settings Deny** — 用户配置的显式拒绝，高于所有 allow。
3. **Settings Ask** — 需要弹窗确认，用户交互后决策。
4. **Hook Allow** — Hook 建议 allow，但不可覆盖 deny（安全不可变量）。
5. **Hook Deny** — Hook 建议拒绝，低于 settings deny。
6. **YOLO Auto-Approve** — AI 分类器对低风险操作自动放行，不可否决 deny。
7. **Default Fallback** — 无规则命中时取 `settings.json` 中 `permissions.defaultMode`。

**不可变量：** `Deny (Layer 1-2) > Hook Allow (Layer 4) > YOLO (Layer 6)` —— 任何代码路径都不能打破此优先级链。

### 13 项保护规则参考模型（Claude Code 级别）

以下 13 项规则构成 Harness 的硬编码保护基线。每项规则对应实际的攻击向量和防御策略：

| # | 保护规则 | 攻击向量 | 防御策略 |
|---|---------|---------|---------|
| 1 | `settings.json` 不可写 | Agent 修改配置关闭沙箱 | 路径硬编码 + 只读挂载 |
| 2 | `.claude/` 目录不可写 | Agent 修改系统提示 / skills | 目录级 deny，不可配置 |
| 3 | 沙箱配置路径只读 | Agent 修改沙箱启动参数 | 编译期常量，运行时不可变 |
| 4 | 审计日志目录不可写 | Agent 删除违规证据 | append-only 文件系统权限 |
| 5 | 系统提示不可被 Agent 修改 | 自我提权 | 提示模板在 Harness 内部管理 |
| 6 | MCP 工具默认 `always_ask` | 第三方工具被自动信任 | 注册时强制 `level: ask` |
| 7 | 凭证不可进入沙箱 | API Key 泄露 | 凭证外置 + 环境变量注入 |
| 8 | `rm -rf /` 等效命令拦截 | 破坏宿主机 | 命令解析 + 危险模式匹配 |
| 9 | 管道 / 重定向受限 | 绕过命令拦截 | 命令解析阶段限制 `\|`、`>`、`<` |
| 10 | 网络出站默认阻断 | 数据外泄 | 白名单域名显式声明 |
| 11 | 符号链接逃逸拦截 | 访问沙箱外文件 | `realpath` 解析后再判定 |
| 12 | 进程 fork / exec 链禁止 | 提权逃逸 | 沙箱内禁止 fork |
| 13 | 自我保护完整性校验 | 启动时检测代码被篡改 | 启动时哈希校验 |

### 6 层纵深防御——绕过概率量化

单一防御层对 AI Agent 形同虚设——LLM 的创造性意味着任何单点校验都可能被绕过。6 层叠加使绕过概率指数下降：

```
假设每层独立绕过概率为 p：

单层防御：P(绕过) = p                              （p = 5%，即 1/20）
双层防御：P(绕过) = p²                             （0.25%，即 1/400）
三层防御：P(绕过) = p³                             （0.0125%，即 1/8,000）
四层防御：P(绕过) = p⁴                             （0.000625%，即 1/160,000）
五层防御：P(绕过) = p⁵                             （0.000031%，即 1/3,200,000）
六层防御：P(绕过) = p⁶                             （0.00000156%，即 1/64,000,000）

┌──────────────────────────────────────────────────────┐
│ Layer 6: Hardcoded Denies          ← 物理不可绕过   │
│ Layer 5: Audit Logging             ← 操作不可删除   │
│ Layer 4: Sandbox                   ← 逃逸需穿透 3 向隔离 │
│ Layer 3: Hook System               ← 26 事件 × 4 类型覆盖 │
│ Layer 2: AI Classifier (YOLO)      ← 二次风险判定   │
│ Layer 1: Permission Model          ← 5 模式 × 7 层级 │
└──────────────────────────────────────────────────────┘
  实际绕过概率 = p₁ × p₂ × p₃ × p₄ × p₅ × p₆ → 趋近于 0
```

注意：各层不是严格独立的——Layer 4 逃逸可能会绕过 Layer 1-3。这是为什么 Layer 6（硬编码拒绝）必须存在：它是最后的绝对防线，不依赖前 5 层的正确性。

### YOLO 分类器（两阶段 AI 自动审批）

YOLO（You Only Look Once）是权限模型 Layer 2 的二阶段 AI 分类器。当 Layer 1 返回 `ask`（需要用户确认）时，YOLO 介入做自动化风险判定：

**阶段一：特征提取**

```
输入维度：
  ├── 工具名 ─────────── 操作语义类别（read/write/execute/network/process）
  ├── 参数摘要 ───────── 参数规模、是否含路径、是否含命令字符串
  ├── 会话上下文 ─────── 前 N 轮对话的语义摘要
  └── 历史特征 ───────── 同类操作是否曾被拒绝过
```

**阶段二：风险分类**

```
输出三分类：
  ├── safe:   风险低于阈值 τ_low → 自动放行（绕过用户确认）
  ├── unknown: 风险在 [τ_low, τ_high] 区间 → 回退到 ask（强制用户确认）
  └── unsafe: 风险高于 τ_high → 强制 deny（等同于 settings deny 效果）

分类特征维度：
  ├── 操作类型（读/写/执行/网络/进程）
  ├── 目标路径是否在 worktree 内
  ├── 命令中是否含危险模式（pipe、redirect、delete、sudo）
  └── 历史类似操作是否被拒绝过
```

**关键约束（安全不可变量）：**

1. **YOLO 不得否决 deny 规则**：YOLO 的 `safe` 判定仅在 Layer 1 返回 `allow` 或 `ask` 时才生效。若 Layer 1 返回 `deny`，YOLO 根本不被调用。
2. **YOLO 使用的模型应独立于 Agent 的 LLM**：防止模型对抗——Agent 的 LLM 不应知道 YOLO 的决策逻辑。
3. **每次 YOLO 决策写入审计日志**：含分类依据、置信度分数，用于事后审查和分类器调优。
4. **保守的阈值设定**：`τ_low` 应保守，宁可多问用户一次，不可误放一个高危操作。

---

## Prompt Cache 稳定性机制

### 缓存前缀稳定性原理

LLM API（Anthropic Claude、OpenAI 等）的 Prompt Cache 按照**消息前缀**进行缓存匹配。如果消息列表的前缀部分发生变化，整个缓存失效。

```
正确做法（稳定前缀）：
┌────────────────────────────────────┐
│ [system_prompt]        ← 角色定义   │  这两个块构成稳定前缀，
│ [built-in tools defs]  ← 内置工具   │  只要它们不变，缓存就命中
├────────────────────────────────────┤  缓存边界在此 ── 以下不参与前缀匹配
│ [MCP tools defs]       ← MCP 工具   │
│ [messages...]          ← 对话消息   │
└────────────────────────────────────┘

错误做法（不稳定前缀）：
┌────────────────────────────────────┐
│ [system_prompt]        ← 角色定义   │
│ [built-in tools defs]  ← 内置工具   │
│ [MCP tools defs]       ← MCP 工具   │  ← MCP 工具变化 → 前缀破坏 → 缓存全失
│ [messages...]          ← 对话消息   │
└────────────────────────────────────┘
```

**核心策略：** 内置工具按名称排序后作为稳定前缀发送，MCP 工具定义追加在缓存边界之后。这样即使用户增删 MCP 服务器，内置工具的缓存前缀仍然命中。

**实现要点：**
- 内置工具列表编译时固定，排序算法确定（字典序或其他确定性排序）
- MCP 工具在每次 API 调用时动态追加，不参与前缀匹配
- Prompt Cache 有最小长度要求（约 1024 token），太短的前缀不会被缓存
- 在 Claude API 中通过标记 `cache_control` 块显式划定缓存边界

---

## 系统提示工程

### 四维框架

| 维度 | 核心问题 | 缺失后果 |
|------|---------|---------|
| 角色 (Role) | 我是谁？ | 回答风格不稳定 |
| 能力 (Capability) | 我能做什么？ | 过度承诺或过度保守 |
| 约束 (Constraint) | 我不能做什么？ | 越界操作，安全风险 |
| 输出格式 (Format) | 我如何表达？ | 输出不一致，下游解析失败 |

### 约束的三个层次

- **硬约束**: 绝对不能违反的规则（"永远不要执行 rm -rf /"）—— 由 Hardcoded Deny 强制执行
- **软约束**: 默认遵守但可被用户显式覆盖（"默认创建新 commit 而不是 amend"）—— 由 Settings 管理
- **条件约束**: 在特定场景下触发的规则（"如果检测到敏感信息，立即停止"）—— 由 Hook 系统 + YOLO 联合实现

---

## 十大设计哲学

1. **Async Generator 流式架构**: 不是返回最终结果，而是 yield 每一个中间事件。上层消费方可以选择性订阅。
2. **通过 Continue 站点实现状态机**: `while(true)` + 7 个 continue 站点，每个站点是错误恢复的锚点。
3. **编译时特性门控**: `if (feature('FEATURE_X'))` // bundler 编译时求值，生产构建移除死代码。
4. **缓存前缀稳定性**: 内置工具排序后作为稳定前缀，MCP 工具变化不影响缓存命中率。
5. **纵深防御**: 6 层叠加使绕过概率指数下降——不是"信任 Agent"，而是"限制 Agent"。
6. **数据驱动的可扩展性**: `settings.json` + `agents/*.md` + `skills/*.md` + hooks —— 配置即代码。
7. **上下文即稀缺资源**: 工具延迟加载、记忆按需附加、四级压缩管道——上下文预算严格执行。
8. **层级化配置覆盖**: 7 级设置，CLI > Flag > Policy > Managed > Local > Project > User。
9. **隔离的子 Agent 上下文**: 子 Agent 从空白消息列表开始，完成后只返回摘要——Token 节省 96%。
10. **可逆性优先**: 文件编辑通过 Edit（替换字符串），不是 Write（覆盖）—— git diff 友好。

---

## 常见陷阱

1. **不要在 Stop hook 中做太重的操作**: 可能触发 prompt-too-long 错误，导致逻辑被静默跳过。
2. **Hook allow 不能绕过 deny 规则**: `deny > settings rules > hook allow` 是安全不可变量。
3. **hasAttemptedReactiveCompact 不重置**: 防止 compact → 仍然太长 → error → stop hook → compact 的无限循环。
4. **数组合并策略是连接 + 去重，而非替换**: 权限规则需要累加而非覆盖。
5. **沙盒设置文件被硬编码为不可写**: 防止 Agent 通过修改 settings.json 来关闭沙盒。
6. **MCP 工具默认使用 always_ask**: 第三方工具不应被自动信任。
7. **Prompt Cache 有最小长度要求**: 约 1024 token，太短的前缀不会被缓存。
8. **上下文压缩后必须主动恢复关键状态**: 文件内容、Skill 上下文、Plan、任务列表——压缩后的恢复提示必须精确。