# 附录 VII:测试基础设施与数据治理
> 可重复性是工程的基础——能被录制的行为,才能被可靠地测试和审计。
---
## 附录 VII-A:VCR 录制回放(API Fixture 系统)
### 功能描述
VCR(Video Cassette Recorder)是 Claude Code 的**测试 API 录制回放系统**:在录制模式下捕获真实 API 调用并存储为 fixture 文件;在回放模式下(CI/测试环境)从 fixture 中还原响应,无需真实 API 调用。这使得测试既可离线运行,又能与真实 API 输出完全一致。
### 核心文件
| 文件 | 说明 |
|------|------|
| `src/services/vcr.ts` | 完整 VCR 实现:脱水/水化、Fixture 读写、hash 生成 |
### 工作机制
**启用条件**(`shouldUseVCR()`):
```typescript
// 自动启用:测试环境
process.env.NODE_ENV === 'test'
// 手动强制(仅 Anthropic 内部用户)
process.env.USER_TYPE === 'ant' && process.env.FORCE_VCR === '1'
```
**核心数据流**:
```
录制模式(VCR_RECORD=1):
输入消息 → dehydrateValue() → SHA1 hash → fixtures/<hash>.json(不存在则调用 API 并写入)
回放模式(默认/CI):
输入消息 → dehydrateValue() → SHA1 hash → 读取 fixtures/<hash>.json → hydrateValue() → 返回缓存响应
```
**两种 Fixture 类型**:
| Fixture 类型 | 入口函数 | 文件名格式 | 用途 |
|-------------|---------|-----------|------|
| LLM 对话 | `withVCR()` | `fixtures/<hash1>-<hash2>-....json` | 捕获 API 对话响应 |
| 通用数据 | `withFixture()` | `fixtures/<fixtureName>-<hash>.json` | 捕获 token 计数等其他 API |
**脱水(Dehydrate)**:`dehydrateValue()` 在存储/哈希前将 fixture 中的动态值(文件路径、cwd、临时目录、时间戳等)替换为占位符,确保同一逻辑输入在不同机器/目录上产生**相同 hash**。
**哈希策略**:LLM fixture 使用每条消息的 SHA1 前 6 位拼接(`hash1-hash2-...`),保留消息粒度以便定位变更位置。
**CI 保护机制**:
```typescript
// CI 环境下缺少 fixture → 立即报错,而不是静默跳过
if (env.isCI && !isEnvTruthy(process.env.VCR_RECORD)) {
throw new Error(`Fixture missing: ${filename}. Re-run tests with VCR_RECORD=1...`)
}
```
### 关键常量/配置
```bash
# 录制新 fixture(会调用真实 API)
VCR_RECORD=1
# 指定 fixture 存储根目录(默认为 cwd)
CLAUDE_CODE_TEST_FIXTURES_ROOT=/path/to/fixtures
# Anthropic 内部强制启用 VCR(非测试环境)
FORCE_VCR=1
```
---
## 附录 VII-B:Grove 数据治理
### 功能描述
Grove 是 Claude Code 的**数据使用同意管理**系统。它控制用户是否同意将对话数据用于模型训练改进,并在用户首次使用时展示知情通知(带有宽限期机制)。
### 核心文件
| 文件 | 说明 |
|------|------|
| `src/services/api/grove.ts` | Grove 设置读取/更新 API,`getGroveSettings()`、`markGroveNoticeViewed()` |
### 数据结构
```typescript
type AccountSettings = {
grove_enabled: boolean | null // null = 未设置(首次使用)
grove_notice_viewed_at: string | null // ISO 时间戳,首次查看通知时间
}
type GroveConfig = {
grove_enabled: boolean
domain_excluded: boolean // 该域名/组织是否豁免
notice_is_grace_period: boolean // 当前是否在宽限期内
notice_reminder_frequency: number | null // 提醒频率(天)
}
```
### 工作机制
1. **启动时检查**:`getGroveSettings()` 从 API 拉取当前账户的 Grove 设置(带 24 小时 session 级内存缓存)。
2. **宽限期(Grace Period)**:新用户首次看到 Grove 通知时,有一段时间不会被反复打扰;`notice_is_grace_period=true` 时仅展示一次通知,不阻塞使用。
3. **查看标记**:`markGroveNoticeViewed()` 向 API 发送 POST 请求,记录用户已查看通知的时间戳。
4. **缓存失效**:`updateGroveSettings()` 调用后立即清除内存缓存(`getGroveSettings.cache.clear()`),确保设置更新后立即生效。
### 隐私优先设计
```typescript
// 隐私优先模式下跳过 Grove 请求(确保最小必要流量)
if (isEssentialTrafficOnly()) {
return { success: false }
}
```
API 失败时**不缓存失败结果**——避免网络抖动导致用户在整个 session 中无法访问隐私设置(死锁保护)。
### 关键 API 端点
```
GET /api/oauth/account/settings → 获取 grove_enabled 状态
POST /api/oauth/account/grove → 更新 grove_enabled 开关
POST /api/oauth/account/grove_notice_viewed → 标记通知已查看
```
---
## 附录 VII-C:Referral 邀请系统(Guest Pass)
### 功能描述
Referral 系统让 Claude Code max 订阅用户可以向他人发送 **Guest Pass**(访客通行证),被邀请者可以免费试用 Claude Code 有限次数。系统包含资格检查、兑换跟踪和本地缓存三层机制。
### 核心文件
| 文件 | 说明 |
|------|------|
| `src/services/api/referral.ts` | 资格检查、兑换查询、缓存管理 |
### 资格门控
```typescript
// 仅 max 订阅 + Claude.ai 订阅者 + 有组织 UUID 的用户可发 Guest Pass
function shouldCheckForPasses(): boolean {
return !!(
getOauthAccountInfo()?.organizationUuid &&
isClaudeAISubscriber() &&
getSubscriptionType() === 'max'
)
}
```
### 核心 API
```typescript
// 检查是否有资格发送邀请(默认活动:claude_code_guest_pass)
fetchReferralEligibility(campaign?: ReferralCampaign): Promise<ReferralEligibilityResponse>
// 查询已发送邀请的兑换情况
fetchReferralRedemptions(campaign?: string): Promise<ReferralRedemptionsResponse>
// 获取邀请者奖励信息(如有)
type ReferrerRewardInfo = { ... }
```
### 本地缓存策略
- 资格结果缓存于 `~/.claude/settings.json` 的 `passesEligibilityCache` 字段,以组织 UUID 为 key
- 缓存有效期:**24 小时**(资格仅在订阅变化时才改变,高频检查意义不大)
- `checkCachedPassesEligibility()` 返回三元状态:`{ eligible, needsRefresh, hasCache }`
### API 请求超时
```typescript
// 资格检查:5 秒超时(后台 fetch,可容忍)
timeout: 5000
// 兑换查询:10 秒超时(用户可见,允许稍长)
timeout: 10000
```
---
## 附录 VII-D:Agent Summary(子 Agent 进度摘要)
### 功能描述
在 Coordinator 模式下,每个子 Agent 每隔 30 秒自动生成一句话的**实时进度摘要**(如 `"Reading runAgent.ts"`),供父 Agent / 用户界面展示当前正在做什么,而无需查看完整的对话流。
### 核心文件
| 文件 | 说明 |
|------|------|
| `src/services/AgentSummary/agentSummary.ts` | 定时器、forked Agent 查询、摘要更新 |
| `src/utils/forkedAgent.ts` | `runForkedAgent()`:共享 prompt cache 的轻量 Agent fork |
### 工作机制
```
startAgentSummarization(taskId, agentId, cacheSafeParams)
│
├── 每 30 秒触发一次 runSummary()
│ │
│ ├── getAgentTranscript(agentId) ← 读取子 Agent 当前消息历史
│ ├── filterIncompleteToolCalls() ← 过滤不完整的 tool call
│ ├── runForkedAgent(params, summaryPrompt) ← fork 出轻量查询
│ │ └── 复用父 Agent 的 prompt cache(零额外 cache fill 成本)
│ └── updateAgentSummary(taskId, summaryText) ← 写入 UI 状态
│
└── stop() → 取消定时器,中止进行中的 fork
```
**摘要 Prompt 规范**:
```
Describe your most recent action in 3-5 words using present tense (-ing).
Name the file or function, not the branch. Do not use tools.
Good: "Reading runAgent.ts"
Good: "Fixing null check in validate.ts"
Bad (past tense): "Analyzed the branch diff"
Bad (too vague): "Investigating the issue"
```
**最小消息数保护**:消息数 < 3 时跳过摘要(上下文太少,摘要无意义)。
**Cache 共享**:`runForkedAgent()` 使用与父 Agent 相同的 `CacheSafeParams`,摘要查询复用已有 prompt cache,额外成本极低。
### 关键常量
```typescript
const SUMMARY_INTERVAL_MS = 30_000 // 30 秒摘要间隔
```
---
## 附录 VII-E:Release Notes(更新日志展示)
### 功能描述
Claude Code 在版本更新后会在下次启动时展示更新日志,采用**后台预取 + 文件缓存**策略,确保启动时日志立即可用(不阻塞 UI 渲染)。
### 核心文件
| 文件 | 说明 |
|------|------|
| `src/utils/releaseNotes.ts` | 日志获取、缓存管理、展示条件判断 |
### 工作机制
```
版本更新检测 → 后台 fetch GitHub 原始 CHANGELOG.md
│
├── 写入 ~/.claude/cache/changelog.md(文件缓存)
│
下次启动时:
├── 同步读取内存缓存 changelogMemoryCache
└── 展示最近 MAX_RELEASE_NOTES_SHOWN(5)条更新
```
**缓存迁移**:历史版本将 changelog 存储于 `settings.json` 中,现已迁移到独立文件(`~/.claude/cache/changelog.md`),`migrateChangelogFromConfig()` 处理一次性迁移。
### 关键常量/配置
```typescript
const MAX_RELEASE_NOTES_SHOWN = 5 // 最多展示 5 条更新记录
// Changelog 源地址
const RAW_CHANGELOG_URL =
'https://raw.githubusercontent.com/anthropics/claude-code/refs/heads/main/CHANGELOG.md'
// 本地缓存路径
~/.claude/cache/changelog.md
```
---
## 附录 VII-F:Session Backfill
### 功能描述
`/backfill-sessions` 命令将历史本地会话(存储于 `~/.claude/projects/` 的 JSONL 文件)批量上传到 Claude.ai 账户的云端会话历史中,实现本地旧会话与云端同步。
### 核心文件
| 文件 | 说明 |
|------|------|
| `src/commands/backfill-sessions/index.js` | 命令入口(编译产物) |
---
## 附录 VII 源码快速导航
```
测试基础设施与数据治理
│
├── VCR 录制回放
│ └── src/services/vcr.ts ← dehydrate/hydrate + SHA1 fixture hash
│ ├── withVCR() ← LLM API 对话级录制
│ └── withFixture() ← 通用 API 调用录制(token count 等)
│
├── Grove 数据治理
│ └── src/services/api/grove.ts ← grove_enabled 同意开关,宽限期通知
│
├── Referral 邀请系统
│ └── src/services/api/referral.ts ← Guest Pass 资格检查 + 24h 本地缓存
│
├── Agent Summary
│ └── src/services/AgentSummary/ ← 30s 定时 fork,1 句话进度摘要
│ └── agentSummary.ts
│
├── Release Notes
│ └── src/utils/releaseNotes.ts ← 后台预取 + 文件缓存,最多展示 5 条
│
└── Session Backfill
└── src/commands/backfill-sessions/ ← 历史本地会话上传到云端
```
---
*附录系列到此结束。*
本系列文档覆盖了 Claude Code 源码的全部主要模块:
- **第 0–16 章**:从系统概览到后台 Agent,逐层拆解核心执行链路
- **附录 I**:基础设施(Bridge/IDE、Computer Use、Worktree、Swarm)
- **附录 II**:后台智能(Magic Docs、Away Summary、投机预加载、设置同步)
- **附录 III**:安全与合规(LSP、OAuth、MDM、自动更新)
- **附录 IV**:自动化扩展(Cron、Todo、Voice、Vim)
- **附录 V**:工作区模式(Plan V2、Sandbox、Rewind、ultraplan、Teleport、Asciicast)
- **附录 VI**:用户体验(Buddy、Effort、Chrome 集成、/btw、彩蛋)
- **附录 VII**:测试与数据治理(VCR、Grove、Referral、Agent Summary)