附录 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()):

// 自动启用:测试环境
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 保护机制

// CI 环境下缺少 fixture → 立即报错,而不是静默跳过
if (env.isCI && !isEnvTruthy(process.env.VCR_RECORD)) {
  throw new Error(`Fixture missing: ${filename}. Re-run tests with VCR_RECORD=1...`)
}

关键常量/配置

# 录制新 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()

数据结构

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()),确保设置更新后立即生效。

隐私优先设计

// 隐私优先模式下跳过 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 资格检查、兑换查询、缓存管理

资格门控

// 仅 max 订阅 + Claude.ai 订阅者 + 有组织 UUID 的用户可发 Guest Pass
function shouldCheckForPasses(): boolean {
  return !!(
    getOauthAccountInfo()?.organizationUuid &&
    isClaudeAISubscriber() &&
    getSubscriptionType() === 'max'
  )
}

核心 API

// 检查是否有资格发送邀请(默认活动:claude_code_guest_pass)
fetchReferralEligibility(campaign?: ReferralCampaign): Promise<ReferralEligibilityResponse>

// 查询已发送邀请的兑换情况
fetchReferralRedemptions(campaign?: string): Promise<ReferralRedemptionsResponse>

// 获取邀请者奖励信息(如有)
type ReferrerRewardInfo = { ... }

本地缓存策略

  • 资格结果缓存于 ~/.claude/settings.jsonpassesEligibilityCache 字段,以组织 UUID 为 key
  • 缓存有效期:24 小时(资格仅在订阅变化时才改变,高频检查意义不大)
  • checkCachedPassesEligibility() 返回三元状态:{ eligible, needsRefresh, hasCache }

API 请求超时

// 资格检查: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,额外成本极低。

关键常量

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() 处理一次性迁移。

关键常量/配置

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)