Architecture Drift Score:你的文档在说实话吗? - Archyl Blog

架构文档会撒谎。不是故意的——只是代码一变,文档就不再真实了。今天我们发布 Architecture Drift Score:一个数字就能告诉你 C4 model 与实际代码库的匹配程度。几秒内计算完成,可随时间追踪,并可在 CI 中强制执行。

Architecture Drift Score:你的文档在说实话吗?

软件架构有一个不为人知的秘密:大多数文档都是错的。

不是"包含错误"那种错。而是"描述了一个不再存在的系统"那种错。图表显示的是一个六个月前就已合并到另一个服务的微服务。C4 model 列出的是一个在周末事故中被 Memcached 替换掉的 Redis 缓存。组件图引用的是一个在重构中被重命名为 BillingServicePaymentGateway——而没有人告诉架构师这件事。

这不是纪律问题,而是结构性问题。代码持续变化。文档只在有人想起来时才更新。现实与文档之间的差距——我们称之为架构漂移——悄无声息地扩大,直到墙上的图表与生产中的系统毫无相似之处。

我们构建了 Drift Score 来让这个差距可见、可量化、可操作。

一个数字:0 到 100

Architecture Drift Score 回答一个问题:文档化的架构中,实际存在于代码库中的占多少百分比?

在 Archyl 中打开任意项目,点击顶部栏的心跳图标,然后点击 "Compute Drift Score"。几秒钟后,你会看到一个 0 到 100 之间的数字:

  • 90-100% — 优秀。你的文档与代码库高度吻合。
  • 70-89% — 良好。大体准确,有一些差距需要弥补。
  • 50-69% — 一般。检测到明显漂移。是时候更新了。
  • 低于 50% — 你的文档是虚构的。

就这么简单。不需要阅读冗长的报告。没有主观评估。一个你可以追踪、分析趋势、强制执行的数字。

实际检查了什么

漂移分析在设计上是轻量级的——只需向 git 提供者发起一次 API 调用,无需 AI,无需获取文件内容。它从五个维度验证你的架构:

Systems — 你的仓库名称是否与文档化的系统匹配?我们使用与 AI 发现管道相同的 PascalCase 命名约定,并通过模糊匹配使 EkoAuthz 能够匹配名为 authz 的仓库。

Containers — 仓库中的顶层目录是否对应文档化的 Container?frontend/ 匹配 FrontendWebAppbackend/ 匹配 BackendApiServer。没有源码目录的基础设施 Container(数据库、队列、监控)会被正确排除——它们是外部服务的有效文档,不是漂移。

Components — 每个 Container 下的组件是否仍然有效?如果父 Container 的目录存在,其组件被视为有效。如果 Container 目录消失了,其所有组件都会被标记。

Code Elements — 这是最精确的检查。C4 model 中的每个代码元素都有一个 filePath。我们验证每个文件是否仍然存在于仓库中。文件被重命名了?类被删除了?模块被移动了?Drift Score 会立即捕获。

Relationships — 如果关系的源元素和目标元素都通过了验证,则该关系有效。如果任一端点发生了漂移,该关系会被标记。

结果是按元素的详细分类,精确显示什么匹配了、什么缺失了、什么是新的——不是一个不透明的分数,而是一份可操作的报告。

为什么轻量级很重要

我们有意选择不运行完整的 AI 发现管道来检测漂移。原因如下:

速度。 AI 分析大型仓库需要几分钟。漂移评分只需几秒。你可以在每次 push 时运行,而不会拖慢你的管道。

确定性。 AI 可能因模型温度、提示变化和 token 限制的不同,在同一代码库上产生不同的结果。文件路径的存在是二元的——文件要么在,要么不在。你的分数是可复现的。

成本。 不消耗 AI token。不触及 API 速率限制。想运行一百次就运行一百次。

简单性。 算法是可审计的。检查文件路径,匹配目录名称,验证关系。没有黑盒。

追踪趋势,而非快照

单个分数是有用的。趋势是强大的。

每次漂移计算都会连同完整分类一起存储。Overview 标签页显示你的分数随时间变化的柱状图。点击任意柱子加载该历史报告,精确查看发生了什么变化。

这将漂移评分从一次性审计转变为持续的健康指标。你可以看到:

  • 上周的重构是改善了还是降低了文档准确性?
  • 漂移是否随时间恶化?(剧透:没有自动化,总是会恶化。)
  • 哪个迭代引入了最多未记录的变更?

在 CI 中强制执行

不强制执行的指标就是你会忽视的指标。这就是为什么我们构建了一个 GitHub Action。

on:
  push:
    branches: [main]

jobs:
  drift:
    runs-on: ubuntu-latest
    steps:
      - uses: archyl-com/actions/drift-score@v1
        with:
          api-key: ${{ secrets.ARCHYL_API_KEY }}
          organization-id: ${{ secrets.ARCHYL_ORG_ID }}
          project-id: 'your-project-uuid'
          threshold: '70'

设置 threshold: '70',当架构文档准确率低于 70% 时,action 将失败。作业摘要会显示包含完整分类的格式化表格——直接在你的 PR 检查中可见。

你还可以将分数作为 PR 评论发布:

- uses: archyl-com/actions/drift-score@v1
  id: drift
  with:
    api-key: ${{ secrets.ARCHYL_API_KEY }}
    organization-id: ${{ secrets.ARCHYL_ORG_ID }}
    project-id: 'your-project-uuid'

- uses: actions/github-script@v7
  if: github.event_name == 'pull_request'
  with:
    script: |
      github.rest.issues.createComment({
        issue_number: context.issue.number,
        owner: context.repo.owner,
        repo: context.repo.repo,
        body: '## Architecture Drift: ' +
              '${{ steps.drift.outputs.score }}%\n' +
              'Matched: ${{ steps.drift.outputs.matched-count }}' +
              ' / ${{ steps.drift.outputs.total-elements }}'
      })

每位开发者在合并前都能看到自己的变更对漂移的影响。架构文档与测试、代码检查和安全扫描一起,成为 CI 管道中的一等公民。

MCP:知道自身准确度的 AI 代理

如果你使用 Claude Code、Cursor 或任何 MCP 兼容的 AI 代理配合 Archyl 的 MCP 服务器,漂移评分可作为工具使用:

compute_drift_score({ projectId: "..." })
get_drift_score({ projectId: "..." })
get_drift_history({ projectId: "..." })
get_drift_details({ scoreId: "..." })

这意味着 AI 代理可以在开始工作之前检查文档准确度。get_agent_context 工具已经提供完整的 C4 model、ADR 和合规规则。现在它还可以检查这些文档有多可信。

看到 45% 漂移分数的代理知道应该对收到的架构上下文保持谨慎。看到 95% 的代理可以自信地依赖文档化的结构。这是自我感知 AI 代理的基础——它们根据文档质量调整自身行为。

Webhook 警报:在漂移发生时获得通知

两个新的 Webhook 事件让你无需查看仪表板就能保持信息同步:

  • drift.score_computed — 每次漂移分数计算完成时触发。推送到 Slack 频道以提高可见性。
  • drift.score_degraded — 当分数比上次计算下降 10 分或更多时触发。这是你的预警系统——架构正在快速漂移。

在 Archyl 的 Webhook 设置中配置这些事件。它们支持 Slack、Microsoft Teams、Discord 以及任何通用 HTTP 端点。

REST API

对于需要完全编程控制的团队:

# 触发计算
curl -X POST https://api.archyl.com/api/v1/drift/compute \
  -H "X-API-Key: $API_KEY" \
  -H "X-Organization-ID: $ORG_ID" \
  -H "Content-Type: application/json" \
  -d '{"projectId": "your-project-uuid"}'

# 获取最新分数
curl https://api.archyl.com/api/v1/drift/latest?projectId=...

# 获取分数历史
curl https://api.archyl.com/api/v1/drift/history?projectId=...&limit=20

计算是异步的——POST 立即返回一个分数 ID,你轮询直到 status 变为 completed。GitHub Action 会自动处理这一切。

这对代理时代意味着什么

我们正在进入一个 AI 代理编写大量生产代码的时代。这些代理速度快、能力强,但对上下文一无所知。它们不知道 AuthService 上个月被拆分成了 IdentityServiceAccessControl。它们不知道 frontend/ 目录被重命名为 web/

漂移分数创建了一个反馈循环:

  1. AI 代理在编写代码前通过 MCP 读取 C4 model。
  2. 代码变更发生(由人类或代理完成)。
  3. 漂移分数检测文档与现实之间的差距。
  4. CI 门禁阻止差距超过阈值增长。
  5. Webhook在漂移加速时警告团队。
  6. 团队更新文档(或运行发现功能自动更新)。
  7. AI 代理读取更新后的模型。循环闭合。

没有第 3 步,循环就是开放的。文档漂移。代理依赖过时的上下文。错误的决策不断累积。

漂移分数闭合了循环。

开始使用

  1. 在 Archyl 中打开任意项目
  2. 点击顶部工具栏的心跳图标
  3. 点击 "Compute Drift Score"
  4. 设置 GitHub Action 进行持续监控
  5. 配置 Slack Webhook 接收 drift.score_degraded 警报

你的架构文档要么反映现实,要么不反映。现在你有了一个数字来告诉你到底是哪种情况。