Architecture Drift Score: あなたのドキュメントは真実を語っていますか? - Archyl Blog

Architecture Drift Scoreは、ドキュメント化されたアーキテクチャのうちどれだけがコードベースにまだ存在するかを示す0から100の数値です。この記事はその仕組みそのものです。計算式、分母に入るもの、意図的に除外されるもの、このチェックに見えないもの、そしてCIで強制する方法。

Architecture Drift Score: あなたのドキュメントは真実を語っていますか?

誰にも監査できないメトリクスは、誰も行動の根拠にすべきでないメトリクスです。ですからこの記事は算術そのものです。Architecture Drift Scoreがどう算出されるのか、何が分母に入るのか、何を意図的に除外しているのか、そしてこのチェックに見えない4つのこと。

このスコアは一つの質問に答えます。ドキュメント化されたアーキテクチャのうち、コードベースにまだ存在するのは何パーセントか? 0から100までの数値で、Gitプロバイダーへの単一のリクエストから計算されます。経路にAIはなく、ファイルの内容も読み込みません。

算術ではなく問題そのものを求めているなら、アーキテクチャドリフトのガイドがドリフトとは何か、なぜ起きるのか、そして他の検出方法を扱っています。まずそちらから読んで、それから戻ってきてください。このページは、あなたがすでに数値を求めていて、それを信じてよいかどうかを知りたいことを前提としています。

数値の読み方

Archylで任意のプロジェクトを開き、ヘッダーのハートビートアイコンをクリックして、「Compute Drift Score」を押してください。数秒で数値が得られます:

  • 90-100% — 優秀。ドキュメントはコードベースと正確に一致しています。
  • 70-89% — 良好。ほぼ正確ですが、いくつかのギャップがあります。
  • 50-69% — 普通。重大なドリフトが検出されました。更新の時期です。
  • 50%未満 — あなたのドキュメントはフィクションです。

これらの区分は、何に対処する価値があるかについての私たちの判断であって、何かを測定したものではありません。その下にある数値は正確です。

数値の計算方法

モデル内のすべての要素はいずれかのバケットに振り分けられ、スコアは生き残った割合です:

score = floor( (matched + 0.5 × partial) / total × 100 )

total = matched + partial + missing_in_code + new_in_code
  • matched — モデルが存在すると言い、リポジトリもそれに同意する。
  • missing_in_code — ドキュメント化されているのに、見つからない。ディレクトリが消えたContainer、ファイルが削除されたコード要素。
  • new_in_code — リポジトリにはあるが、モデルにはない。ドキュメント化されていないということであり、これは逆方向のドリフトで、まったく同じ重さであなたに不利に働きます。

partialは半分のクレジットを持ち、差異を伴って一致する要素のために予約されています。現在のチェックはこれを生成しません。すべての要素は他の3つのいずれかに振り分けられるため、実際にはスコアはmatchedの割合です。決して発火しない項を含む計算式というのは、あなたが自分で発見するのではなく私たちから聞かされるべき類のものなので、お伝えしています。

2回の実行を比較するときに重要になる詳細が2つあります。結果は四捨五入ではなく切り捨てられるため、89.9は89として報告されます。そしてドキュメント化されていない要素は分母を大きくします。新しいサービスを3つ追加してドキュメント化しなければ、それまでに書いたものが偽になったわけでもないのにスコアが下がるのは、このためです。

実際に何をチェックするのか

ドリフト分析は設計上軽量です。Gitプロバイダーへの再帰的なツリーリクエストが1回だけで、AIはなく、ファイル内容も取得しません。5つの次元でアーキテクチャを検証します:

Systems — リポジトリ名がドキュメント化されたシステムと一致するか?AIディスカバリーパイプラインと同じPascalCase命名規則を使用し、ファジーマッチングによりEkoAuthzauthzという名前のリポジトリと一致します。

Containers — リポジトリのトップレベルディレクトリがドキュメント化されたContainersに対応するか?frontend/FrontendWebAppに一致します。backend/BackendApiServerに一致します。ソースディレクトリを持たないインフラストラクチャContainer(データベース、キュー、モニタリング)は除外されます。これらはドリフトではなく、外部サービスの有効なドキュメントだからです。この除外が何を犠牲にするのかは、次のセクションで扱います。

Components — 各Container配下のコンポーネントはまだ有効か?親Containerのディレクトリが存在すれば、そのコンポーネントは有効とみなされます。Containerディレクトリが消えた場合、そのすべてのコンポーネントがフラグ付けされます。

Code Elements — これが最も精密なチェックです。C4 model内のすべてのコード要素にはfilePathがあります。各ファイルがリポジトリ内にまだ存在するかを検証します。ファイルがリネームされた?クラスが削除された?モジュールが移動された?Drift Scoreは即座に検出します。

Relationships — リレーションシップは、ソースとターゲットの両方の要素が検証を通過した場合に有効です。どちらかのエンドポイントがドリフトした場合、そのリレーションシップはフラグ付けされます。

結果は要素ごとの内訳で、何が一致し、何が欠けており、何が新しいかを正確に示します——不透明なスコアではなく、対処可能なレポートです。

分母から除外されるもの

スコアは、それが数えることを拒むものの分だけしか誠実ではありません。除外は3つ、いずれも意図的なものです:

外部システムと人。 外部システムまたは人としてタイプ付けされたものはすべて、比較の前に両側から取り除かれます。Stripe、あなたのアイデンティティプロバイダー、そして「顧客」はSystem Context図に属するものであり、そのいずれもあなたのリポジトリに現れることはありません。これらを欠落として数えることは、正しい図を描いたことへの罰になってしまいます。

ソースディレクトリを持たないインフラストラクチャContainer。 どのディレクトリにも一致しないドキュメント化されたContainerは、ドリフトとして数えられるのではなく、Containerの集計から取り除かれます。PostgreSQLインスタンス、Kafkaクラスタ、Datadogアカウントはいずれも正当なContainerであり、そのどれもフォルダではありません。

このルールには代償があり、それを知っておくべきです。あなたが削除した実在のサービスディレクトリもまたContainerの集計から除外されます。チェックは「データベース」と「先のスプリントで削除したサービス」を区別できないからです。そのコンポーネントは除外されません。親Containerが一致しなかったため、依然として欠落として解決されます。つまり削除されたサービスはスコアにきちんと現れます——ただし、あなたが探すであろう場所より1つ下の階層で。

記録されたファイルパスを持たないコード要素。 モデル内のコード要素にfilePathがない場合、検証すべきものが何もないため、推測されるのではなくスキップされます。あなたにとって有利にも不利にも働きません。生成されたパスやベンダーのパス(vendor/node_modules/dist/target/__pycache__/、その他おなじみのリスト)は、これらすべてが実行される前にファイルツリーから除外されます。

なぜ軽量であることが重要なのか

ドリフト検出に完全なAIディスカバリーパイプラインを実行しないことを意図的に選択しました。その理由は以下の通りです:

スピード。 AI分析は大規模なリポジトリでは数分かかります。ドリフトスコアリングは数秒です。パイプラインを遅くすることなく、すべてのpushで実行できます。

決定論性。 AIはモデルの温度、プロンプトの変動、トークン制限に応じて、同じコードベースで異なる結果を生成する可能性があります。ファイルパスの存在はバイナリです——ファイルがあるかないかです。スコアは再現可能です。

コスト。 AIトークンの消費なし。APIレート制限に抵触しません。必要なら1日100回実行してください。

シンプルさ。 アルゴリズムは監査可能です。ファイルパスの確認、ディレクトリ名のマッチング、リレーションシップの検証。ブラックボックスはありません。

スコアに見えないもの

これらの特性はいずれも、同じ取引によって購われています。このチェックが読むのは構造であって、コードではありません。結果として4つのことが起きますが、そのどれも私たちが隠すつもりのバグではありません。

振る舞いのドリフトは見えません。 2つのサービスが名前とディレクトリを保ったまま、両者間の同期HTTP呼び出しがキューのメッセージに変わっても、スコアは動きません。構造的には何も変わっていないからです。これは最大の盲点であり、安価な解決策はありません。これを捉えるには、コードを読むか、人間とともにモデルをレビューするしかありません。

移動は削除とまったく同じに見えます。 コード要素は、大文字小文字を区別する完全一致のファイルパスで検証されます。internal/auth/token.goを1行も変更せずにinternal/identity/token.goへ移動すると、その要素は欠落として報告されます。ドキュメント化されたパスが間違っている以上、技術的には正しい報告です。そしてこれは、ディレクトリ名を変更するリファクタリングが、警戒を誘うような形でスコアを下げる一方で、実際には要素ごとに1行の修正で解消することを意味します。

コンポーネントの正確さは継承されるものであって、検証されるものではありません。 Containerのディレクトリが存在すれば、その配下のすべてのコンポーネントは有効とみなされます。チェックが中を覗くことは決してありません。したがって、まだ存在しているものの中身を抜き取られて書き直されたContainerは、コンポーネントレベルではクリーンと評価され、その数値はあなたのレベル3の図について、根拠が支持する以上に自信を持っていることになります。

名前のマッチングは寛容です。 SystemsとContainersは3つのパスで名前によってマッチングされます。大文字小文字を無視した完全一致、次にどちらの方向でも部分文字列を含むかどうか、次にPascalCaseとkebab-caseを分割した後のトークンの重なりです。EkoAuthzauthzという名前のリポジトリに一致し、BackendApiServerbackendというディレクトリに一致します。これは些細な命名の違いがドリフトとして報告されるのを防ぐもので、あなたのモデルに有利な方向へ誤差を取ります。厳密な読み取りが欲しい場合は、見出しの数値ではなく要素ごとの内訳を使ってください。

総合すると、このスコアは、あなたのモデルが依然として同じシステムを記述しているかどうかの良い尺度であり、それを正しく記述しているかどうかの弱い尺度です。高いスコアは「構造上の驚きはない」と受け取るべきであって、「ドキュメントは正しい」と受け取るべきではありません。

スナップショットではなくトレンドを追跡する

単一のスコアは有用です。トレンドは強力です。

すべてのドリフト計算は完全な内訳とともに保存されます。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%を下回った場合にアクションが失敗します。ジョブサマリーには完全な内訳を含むフォーマット済みテーブルが表示されます——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、またはArchylのMCPサーバーを使用するMCP互換のAIエージェントを利用している場合、ドリフトスコアリングはツールとして利用可能です:

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アラート: ドリフト発生時に通知を受ける

2つの新しい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と共に即座に返り、statuscompletedになるまでポーリングします。GitHub Actionはこれを自動的に処理します。

これはループのどこに位置するのか

スコアはサイクルの中の一つのステップです。エージェントと人間がモデルを読み、コードが変わり、スコアがギャップを測り、CIが閾値を守り、チームが差分を解消する。測定のステップがなければ、このサイクルにフィードバックはなく、ドキュメントは誰にも問われないままドリフトします。その論拠と、そもそもドリフトを検出すべき理由の残りはガイドにあります。

この記事が責任を負うのは、測定のステップが信頼に足るものであることです。だからこそ、計算式であり、除外であり、見ることのできない4つのことなのです。

はじめに

  1. Archylで任意のプロジェクトを開く
  2. ヘッダーツールバーのハートビートアイコンをクリック
  3. 「Compute Drift Score」をクリック
  4. 継続的モニタリングのためにGitHub Actionをセットアップ
  5. drift.score_degradedアラート用にSlack Webhookを設定

あなたのアーキテクチャドキュメントは現実を反映しているか、していないかのどちらかです。今、どちらなのかを教えてくれる数値があり、そしてその数値と議論できるだけの算術も手元にあります。


このクラスタの残り: 問題そのものと他の検出方法についてはアーキテクチャドリフト検出、スコアが再び下がるのを防ぐ実践については生きたアーキテクチャドキュメント。定義: アーキテクチャドリフト。製品ページ: ドリフト検出