mcpField
H
HEIDES

HEIDES

ローカル
github.com/AbduljabbarBXR開発ツール13 週間前に更新

HEIDES について

HEIDESは、コーディングエージェント向けのローカル実行型コード分析ツールです。コードグラフを構築して問題を報告し、パッチ適用前に影響を判定します。クラウドサービスやモデルには依存しません。

主な機能

  1. 01永続的なコードグラフの構築
  2. 02汚染フローとコードリスクの検査
  3. 03呼び出し関係とインポートの分析
  4. 04パッチと影響を受ける呼び出し元の評価
  5. 05終了コードによるゲート判定
  6. 06CLIとMCPツールの提供

活用シーン

  1. 01適用前のパッチ影響評価
  2. 02CIで重大な問題をブロック
  3. 03呼び出し元とコード文書の検索
  4. 04入力がSQLやシェルのシンクに届くか確認

MCP 対応

`heides mcp`はstdio経由で11個のツールを提供します。`harmony.check`や`harmony.report`は、重大度、ファイル位置、セキュリティゲート情報を含む結果を返します。

設定

ローカルサーバーの設定はどのクライアントでも共通です。コピーしてクライアントの MCP 設定ファイルに貼り付けてください。

インストール方法は未掲載です

このサーバーのパッケージやリモートエンドポイントはまだ取得できていません。プロジェクトの README の手順に従ってください。

リポジトリ
パッケージ
mcpbheides-0.13.1-linux-x86_64.mcpb0.13.1
mcpbheides-0.13.1-darwin-arm64.mcpb0.13.1
mcpbheides-0.13.1-darwin-x86_64.mcpb0.13.1
mcpbheides-0.13.1-windows-x86_64.mcpb0.13.1

ツール

ツール一覧はまだ取得されていません

ローカルサーバーのツールはマシン上で起動して初めて取得できます。メンテナーはまだツール一覧を提供していません。

詳細

HEIDES

HEIDES、コードの神経系

コードの神経系

HEIDES は、AI コーディングエージェントが単独では持っていないもの、つまりコードの永続的なマップ、そのマップから導き出された警告、パッチを適用する前の判定を提供する、決定論的なハーネスです。エージェントが提案し、HEIDES が安全性を判断します。

バイナリは 1 つ。クラウドも、モデルも、アカウントも不要です。ノートパソコンでも、サーバーでも、CI でも、Termux を実行するスマートフォンでも動作します。

heides scan                 # map the codebase once
heides check                # run every guard, exit non-zero on a blocker or critical
heides staged patch.diff    # judge a patch before it lands
heides mcp                  # expose it to any MCP client

check はレポートではなく、ゲートです。ブロッカーまたはクリティカルな問題が見つかると、ゼロ以外の終了コードを返すため、出力を解析しなくても、実際の SQL インジェクションがあれば CI は失敗します。問題のないワークスペースは終了コード 0 を返します。--exit-zero を指定すると、従来どおり常にゼロを返す動作に戻り、--exit-threshold=warning を指定すると、判定がより厳しくなります。

すべてのガードはローカルで動作します。それが設計のすべてです

heides は、読み込んだファイルから証明できる内容だけを報告します。各検出結果にはファイル名と行番号が示され、同じツリーであれば、ノートパソコンでも、コンテナーでも、ネットワークを切ったスマートフォンでも、同じ判定になります。古くなるキャッシュも、障害が発生する可能性のあるレジストリもありません。

以前はそうではありませんでした。heides には、固定されたバージョンが既知の CVE に該当するかを確認する依存関係ガードがありましたが、ツール内で確認する方法はどれも誤った結果を出す可能性がありました。

  • ネットワーク経由では、ゲートの判定がツリーではなくネットワークの状態に左右されていました。同じ 5 ファイルのフィクスチャで、ガードを有効にした check は 3242 ms、無効にした場合は 117 ms かかりました。
  • キャッシュを使う場合は、さらに問題がありました。オフラインキャッシュは、問題がないという回答を 24 時間後に期限切れにしていたため、その日の朝に公開された CVE があっても、エントリーが再取得されるまで「既知の脆弱性なし」と表示されていました。出力からは、この 2 つの状態を区別できませんでした。

脆弱性がないことと、まだ情報を得ていないことを区別できないガードは、誤った安心感を与えます。そして、誤った安心感は合格と見分けがつきません。そのため、このガードはオプトインにするのではなく削除しました。安全なデフォルトとしてオプトインにしても、デフォルトの処理が遅いことに変わりはなく、正確なキャッシュも、やはりキャッシュです。

依存関係、シークレット、露出は GRIM にあります。GRIM は公開され、リリースされており、このリポジトリのキャッシュではなく、継続的に更新されるフィードに基づいています。heides deps と deps.* ツールは引き続き存在し、そのことを正確に伝えます。これらの名前を持つエージェントは、ツールが壊れていると判断するのではなく、回答の移転先を把握できます。

heides が引き続きローカルで証明するのは、これから加えようとしている変更に関わる重要な部分です。

汚染SQL 文字列、シェル、プロンプトに到達するユーザー入力
シークレットソースと設定内にある、値の形式から識別されるコミット済みの認証情報
エッジケース不適切な入力でパニックを起こすアンラップとインデックスのパターン
スキーマ外部キーの循環、主キーの欠落、読み取りパス上の PII
設定.env、Dockerfile、Terraform、マニフェスト内の認証情報

これらはすべて、世の中の状況ではなく、リポジトリに関する事実です。そのため同じツールに含まれ、CVE の確認は含まれません。

MCP 経由

harmony.check と harmony.report は、ガード、重大度、メッセージ、ファイル、行番号を含む検出結果を返します。harmony.report は security_gate と security_posture を含むため、エージェントは文章を解析せずに判定を基準として使えます。また、網羅性のレシートは JSON 内に含まれます。問題なしという結果を受け取ったエージェントが、実際にどの程度検査されたのかを確認するために、2 回目の呼び出しをする必要はありません。

そのガードがなくなった後も、ガードのために書かれた教訓は残りました。MCP サーバーは 1 つのプロセスですべてのクライアントを処理するため、動作を変える設定は、それを要求した呼び出しのスコープ内に限定し、プロセス全体には設定しないでください。以前の harmony.check はプロセス全体のグローバル設定を変更し、元に戻しませんでした。そのため、あるクライアントが引数を渡すと、すべてのクライアントからの後続リクエストのセキュリティポスチャーが、気付かれないまま変わってしまいました。

存在する理由

AI エージェントは強力ですが、盲目です。コードの永続的なマップを持たないため、完璧な関数を書けても、読んだことのない呼び出し元を3つ壊してしまうことがあります。リンターやテストがそれを検出するのは変更が取り込まれた後で、しかも実行される経路に限られます。典型的な失敗例は、エージェントがシグネチャを変更し、テストされていない呼び出し箇所が壊れる一方、テストスイートは成功のままで、午前2時に本番環境が壊れるというものです。

HEIDES は、重要な瞬間、つまり書き込みの前にそのギャップを埋めます。その時点でほかのツールには答えられない質問に答えます。この関数を呼び出しているのは誰ですか?このファイルが実際に使っているインポートはどれですか?このパッチはグラフと競合しますか?ユーザー入力は SQL 文字列、シェル、プロンプトに流れ込んでいますか?

基盤

基盤はコードベースを1つの組み込み SQLite ファイルにマッピングします

HEIDES はツリーを一度走査し、1つの組み込み SQLite ファイルに永続グラフを構築します。そこにはファイル、取得したドキュメントコメント付きのシンボル、呼び出しエッジ、インポートエッジ、そして2つの FTS5 テーブル(1つは名前とドキュメント、もう1つはリテラルとコメントを対象とする)が含まれます。その後の質問はすべてインデックス検索で処理されるため、エージェントはファイルを読む代わりにグラフに問い合わせます。

基盤はモデルでも推測でもありません。heides describe は、エントリーポイント、ハブ、言語ごとのドキュメント網羅率を含むワークスペース全体のマニフェストを一度に読み取ります。ワークスペース内で誰にも呼び出されていない関数が、自動的にデッドコードになるわけではありません。Express、Flask、Django、Go のルート登録が認識されるため、ハンドラーが呼び出されていないルートとして報告されなくなります。

コストに関する契約は、このファイルに固定された数値ではなく、CI のスケールフェーズによってプッシュのたびに検証されます。インデックス作成時間はファイル数に対して線形であること、クエリはインデックス上で実行されること、メモリ使用量に上限があること、そして分析にネットワークを必要としないことが保証されます。

汚染追跡

汚染追跡は関数の境界を越えて、ユーザー入力からシンクまでを追跡します

汚染追跡は、実際のバグを見つける機能です。ソースは言語ごとのリクエストデータと環境変数の読み取りです。フローはブロックのスコープ内で追跡され、関数の境界やモジュールレベルのコードを越えて伝播します。ホップ数には上限があり、それを超えると報告されません。シンクには、SQL、SSRF、NoSQL、シェル、ファイルシステム、プロンプト、eval、Django の mark_safe が含まれます。

SSRF と NoSQL には、意図的に SQL より厳しい判定条件を設けています。ハードコードされたヘルスチェック URL も、リクエストハンドラー内のリテラルなクエリオブジェクトも安全です。そのため、これらのルールでは、ハンドラー内のどこかにソースが存在するだけでなく、汚染された値が実際にシンクの行まで到達することを条件としています。

app.get('/health', async (req, res) => {
  const id = req.query.id;                              // a source is in scope here
  const r = await fetch('https://api.internal/health'); // ...and this must stay silent
});

クラウドメタデータアドレスを対象とする汚染された fetch は、一般的な SSRF ではなく認証情報の窃取として報告されます。それが実態だからです。

user controlled input reaches a cloud metadata fetch sink on this line. source at line 4

レポートが主張するのは、確認できる内容だけです。変数を通じて渡された汚染されたホストは SSRF として報告されます。アドレスはその行に現れず、ツールがその向き先を推測することもないためです。

最も重要なルールは、慎重に判断することです。run、raw、literal、prepare は曖昧な名前なので、データベースらしいレシーバー上で使われた場合にのみ SQL と判定されます。

db.run("DELETE FROM users WHERE id = " + id)   // critical SQL finding
run(taskName)                                  // silence, a task runner is not a database

同じことがドキュメントクエリにも当てはまります。メソッド名だけでは曖昧ですが、レシーバーは曖昧ではありません。

UserModel.find(JSON.parse(req.query.filter))  // critical NoSQL finding
items.find(i => i.id === id)                  // silence, that is an array method

両方のケースには回帰テストがあるため、この近道が復活することはありません。

言語

汚染解析とインデックス作成は別々に行われます。この表では、それぞれの対応状況を正確に示しています。 以下の各行は、文法リストから推測したものではなく、リリース済みバイナリを使って測定した結果です。

言語シンボル付きでインデックス作成汚染解析
JavaScript, TypeScript, TSX, Python, PHP, Go, Java, C#はいはい
C, C++はいいいえ
Rubyはいはい
HTML, CSSはいいいえ
Rustはいいいえ

0.16.0 までは、TypeScript の汚染解析が気づかれないまま実行されていませんでした。パーサーは .ts を typescript に対応付けていた一方、ルールテーブルに typescript の行がなかったため、すべての TypeScript ファイルが何も告げられずにスキップされていました。今回のシリーズ以前は、Ruby の汚染解析もまったくできませんでした。理由は3つあり、rb 拡張子がなく、ソースの行もなく、ブロック検出器が波括弧には対応していても def と end には対応していなかったためです。Rust はインデックス作成されますが、汚染解析は行われないため、Rust コード内のシェルまたは SQL のシンクは報告されません。

.tsx は通常の TypeScript 文法ではなく、TSX 文法で解析されます。この2つは互換ではありません。JSX 要素は通常の文法では名前を付けられないノード種別を開くため、走査はそこで停止し、コンポーネントファイルから得られるシンボルは、同じコードを .ts 拡張子にした場合より少なくなっていました。C と C++ はシンボルと呼び出しエッジ付きでインデックス作成されますが、汚染解析は行われません。固定バッファーに対する sprintf の出力が system に渡されても、何も報告されません。

ゲート

適用前のゲートが、差分を取り込む前に判定します

heides staged は、エージェントのループで実際に使う部分です。ファイルではなく差分を判定します。シグネチャーの削除だけでなく範囲の拡大、パッチで壊れる呼び出し元やインポート、パッチが導入する汚染、そしてプロジェクトにテストがあればそのテストも判定します。判定結果は構造化されているため、エージェントは文章を解析せずにゲートとして使用でき、検出事項ごとにファイルと行番号を示して、終了コードが0以外になります。

インストール

1行のインストーラーで、linux、macos、windows、Termux Android 向けのビルド済みバイナリをダウンロードします。

curl -fsSL https://raw.githubusercontent.com/AbduljabbarBXR/heides/main/scripts/install.sh | bash

HEIDES_VERSION でバージョンを固定できます。プレフィックスのないバージョンを指定し、先頭の v は削除されるため、0.16.0 と v0.16.0 のどちらも使用できます。npm インストーラーも同じ変数を読み取るため、どちらの方法でも同じバージョンに固定できます。

# any published tag, bare or with a leading v
HEIDES_VERSION=v0.16.0 curl -fsSL https://raw.githubusercontent.com/AbduljabbarBXR/heides/main/scripts/install.sh | bash

または、Rust ツールチェーンを使わずに npm からインストールします。

npm install -g heides

heides の実行時にバイナリが見つからない場合、ランチャーがその場でダウンロードし、その旨を表示します。これは本来必要になるはずのないフォールバックです。npm 11.16 以降では依存関係のライフサイクルスクリプトがデフォルトでブロックされ、npm 11.17 では --allow-scripts フラグを指定するとインストール自体が中断されるため、バイナリを取得する postinstall フックが実行されません。直前に失敗した操作である再インストールを案内するのではなく、ランチャーがフックと同じインストーラーを実行します。プラットフォームの一覧は install.js にあるため、重複して管理する必要はありません。

または cargo でインストールします。

cargo install heides

または、リリースページからお使いのプラットフォーム用のビルド済みバイナリを入手するか、cargo build --release でソースからビルドします。

どの配布経路も同じバージョンを使用しており、npm ラッパーとバイナリに食い違いが生じた場合はテストがビルドを失敗させます。

クイックスタート

heides scan                       # build the spine index
heides check                      # every guard, human readable
heides query callers send_order   # who calls it
heides query search refresh       # names, docs, literals and comments
heides describe                   # the workspace manifest in one shot
heides plan "add a health endpoint"   # is this plan grounded in what exists
heides staged patch.diff          # judge a patch before applying it
heides mcp                        # serve the eleven tools over stdio

2つのバグを仕込んだ小規模な Express サービスを使った実例です。

$ heides check
0 blocker(s), 3 critical, 0 warning(s), 1 info

[critical] user controlled input reaches a SQL sink ... at src/knexish.js:6
[critical] user controlled input reaches a SQL sink ... at src/knexish.js:7
[critical] user controlled input reaches a SQL sink ... at src/orders.js:9
[info] no dependency manifests found

$ heides query search users
2 hit(s)
SELECT * FROM users WHERE email = (literal) at src/knexish.js:5
DELETE FROM users WHERE id = (literal) at src/orders.js:9

$ heides plan "add a health endpoint"
feasible true
  no identifier in this plan exists in the spine. this plan introduces new definitions.
  existing functions to build on or replace: findUser, greet at src/clean.js:1
  spine holds 4 file(s) and 5 symbol(s). index version 8.

コマンドリファレンス

すべてのコマンドをまとめて紹介します。heides <command> --help を実行すると、各コマンドの使用方法が表示されます。

コマンド説明
scan現在のコードベースを永続インデックスにマッピングします。他のコマンドは、このコマンドで構築したインデックスを読み取ります。
statusインデックスに保持されているファイル、シンボル、呼び出しエッジ、インポートを1行で表示します。
describeワークスペースのマニフェストです。言語、件数、エントリーポイント、ハブ、ドキュメントのカバレッジ、実際のコーパスを基盤とするガードを表示します。
querycallers、imports、definition、calls、neighbors、search。あるシンボルを呼び出す箇所、定義の場所、呼び出し先を調べたり、名前、シグネチャ、ドキュメント、リテラル、コメントを対象にフリーテキスト検索したりできます。
checkすべてのガードを実行します。ゲートとして機能し、検出事項がブロッカーまたは重大な問題の場合は、ゼロ以外の終了コードを返します。
staged適用前に統一差分をチェックします。
verifyプロジェクトが自身について表明できるアサーションです。プロジェクト独自のテストと、すべてのローカルガードを実行し、分岐に使えるブール値を返します。
dbtables、columns、reads、writes、orphans、missingindex、policies、cycles、schema、routes、touch。コードから読み取ったデータベースグラフを表示します。
deps廃止されました。以前は、固定バージョンが既知の CVE に該当するかを確認していました。現在は実行を拒否し、GRIM を案内します。
configマニフェストや設定ファイルをスキャンし、認証情報や重要な設定を検出します。
exportコードマップを Markdown ファイルに書き出します。MCP に対応する同等の機能がない唯一のコマンドです。ファイルへのエクスポートであり、サーバーにはエクスポート先がないためです。
confirm依存関係に追加する前に、パッケージ名が実際に何を指すのかを crates.io と npm に問い合わせます。選択によりネットワークを使用する唯一のコマンドです。
planコードベースに照らしてプランを評価し、使用した根拠を表示します。フリーテキストを受け取ります。
scaffoldプランからプロジェクトを生成し、インデックスを作成します。フリーテキストを受け取ります。
changed-sinceUnix タイムスタンプより後に mtime が更新された、インデックス対象のファイルを表示します。spine.changed_since ツールと同じ結果を返します。
watch変更時に再インデックスと再チェックを行います。
versionバージョンを表示します。
mcpstdio 経由で MCP サーバーを実行します。

MCP ツールリファレンス

このサーバーは、あらゆる MCP クライアント向けに、stdio 経由で 21 個のツールを公開します。記載があるものを除き、すべてのツールにコマンドライン版があります。

  • spine.scan。現在のコードベースを永続インデックスにマッピングします。(scan)
  • spine.query。シンボルを呼び出している箇所、モジュールをインポートしている箇所、定義の場所、関数が呼び出しているものを調べるほか、名前、シグネチャ、ドキュメント、リテラル、コメントを対象に全文検索します。(query)
  • spine.describe。ワークスペースのマニフェストを一度の呼び出しで表示します。言語、件数、エントリーポイント、ハブ、ドキュメントの網羅率を確認できます。(describe)
  • spine.neighbors。シンボルのあらゆる関連情報を表示します。定義とその記録済みドキュメント、呼び出し元、呼び出し先を確認できます。(query neighbors)
  • spine.changed_since。Unix タイムスタンプ以降に変更されたインデックス済みファイルを表示します。(changed-since)
  • harmony.check。すべてのガードを実行し、根拠とともに検出結果を表示します。(check)
  • harmony.report。同じ判定を、重要度別の件数とクリーン状態フラグを含む構造化 JSON として返します。
  • harmony.staged。適用前に統合差分をチェックします。(staged)
  • harmony.verify。プロジェクト独自のテストとすべてのガードを実行し、結果を 1 つの真偽値で返します。(verify)
  • grounding.plan。コードベースに照らして計画を評価し、使用した根拠を示します。(plan)
  • grounding.scaffold。計画から新しいプロジェクトのスキャフォールドを作成し、ただちにインデックス化します。(scaffold) 3 つの deps.* ツールはガードとともに削除されました。呼び出すと、未知のツールというエラー(サーバーの故障と誤解される可能性があります)ではなく、その機能が GRIM に移されたことを説明するエラーが返されます。
  • db.tables、db.columns、db.reads、db.writes、db.routes、db.schema、db.touch。コードから読み取ったデータベースグラフを表示します。(db <subcommand>)
  • config.scan。マニフェストや設定ファイル内の認証情報と設定を確認します。(config)
  • web.confirm。パッケージレジストリで事実を確認します。(confirm)

check は同じ判定を出力し、export はマップを書き出すため、harmony.report に個別のコマンドはありません。これを分けても、同じ回答に別の表記を追加するだけです。

セキュリティモデル

  • 設計上、決定論的です。検出結果にはすべて、ファイル、行、理由、ルール ID が含まれます。ブラックボックスはありません。
  • デフォルトではローカルで動作します。依存関係チェックとグラウンディングのための明示的なウェブ呼び出しを除き、マシンの外部にデータが送信されることはありません。
  • テレメトリ、分析、アカウント、ポート、デーモンプロトコルはありません。stdio 上で 1 つのプロセスが動作します。
  • ランタイム依存関係のない単一の静的バイナリです。
  • MCP サーバーは生のバイト列を読み取るため、バイナリ入力で停止することはありません。また、メッセージサイズに上限を設けています。

ユースケース

  • ターミナルでのエージェント型コーディングセッションにおけるガードレール。
  • CI または MCP 経由での、AI が生成したプルリクエストのマージ前レビュー。
  • コードベース全体を読むことなく、エージェントが未知のコードベースに慣れるための支援。
  • エージェントアプリケーションのセキュリティレビュー、特にプロンプトインジェクションの確認。
  • 古いプロジェクトの依存関係の適正化。

まだ対応していないこと

明確に記載し、ROADMAP.md で引用と解決状況の列を使って追跡しています。このリストについて、明示しておくべき点が2つあります。ここに記載されたギャップは計画に織り込める制限ですが、何も通知せずに処理を行わない状態はそうではありません。0.15.2 で、インデックスが一度も作成されていないワークスペースのチェックが問題なしと報告する不具合がリリースされていました。この特定の不具合は現在、2つのテストで固定されています。1つは、新たに構築されたグラフから列挙されたすべてのファイルを読み戻せることを検証し、もう1つは、インデックス未作成の汚染されたファイルを初回実行で検出して報告することを検証します。

  • データベースレイヤーはまだありません。.sql の解析も、スキーマグラフも、どのコードがテーブルにアクセスするかを尋ねる方法もありません。これは既知のギャップの中で最大です。欠けているのは データベース レイヤーであり、ストアではない点に注意してください。基盤はすでに組み込み SQLite ファイル1つなので、新しいストアを導入するのではなく、既存のストアを拡張します。
  • API サーフェスグラフがないため、「POST /users は最終的に何に書き込むのか」に1回の呼び出しで答える機能はありません。これは最優先項目です。
  • ファイルシステムの書き込み先を超えるパストラバーサル、およびフレームワーク固有のシェル API に対するコマンドインジェクションルールはありません。
  • オープンリダイレクト、XXE、安全でないデシリアライズ、暗号の誤用に関するルールはありません。
  • 依存関係を読み取れないエコシステムがいくつかあります。Ruby、.NET、Swift、Gradle、Dart です。また、ロックファイルからの推移的な解決もありません。
  • インデックス作成の対象外の言語:SQL、shell、Kotlin、Swift、Scala、Dart、Dockerfile。C と C++ はシンボルと呼び出しエッジを使ってインデックス化されますが、汚染行はありません。Rust はインデックス化されますが、汚染スキャンの対象ではありません。
  • どのガードもネットワークを使いません。 すべての検出結果はファイルから証明できます。ネットワークに接続する唯一のコマンドは grounding.plan 内のウェブ確認です。これは呼び出し元が名前を指定して求める意図的な検索であり、check の一部として実行されるガードではありません。
  • staged は競合のみを検証します。パッチ適用後のツリーに対して汚染スキャンを実行しないため、フローを導入するパッチはまだゲートで検出されません。

出力の読み方

このリポジトリをチェックしたところ、185行が出力され、そのうち152行は同じ文でした。 これは件数が152の検出結果が1つあるということであり、それを152行で表示すると、重要な検出結果が大量の出力に埋もれてしまいます。

0 blocker(s), 1 critical, 157 warning(s), 41 info

[warning] unwrap can panic when the value is not present. handle the case
instead. x152 (edge.cases) at src/deps.rs:893

advice, unproven and unranked:
[info] diagnostic console call left in the code. x10 (best.practice) at npm/bin/heides.js:17

ルールは3つです。同一の検出結果はまとめられ、件数と最初のファイルおよび行が保持されるため、情報は失われません。--all を指定すると、すべての検出結果が表示されます。また、証拠とアドバイスが混在することはありません。汚染の検出結果は、実際に読みに行けるコード上の経路です。一方、「関数が N 行にわたる」はスタイル上の意見であり、エージェントは前者に対するのと同じ方法では後者に対応できません。最上部の件数は常にすべての検出結果を示すため、まとめても結果が実態より良く見えることはありません。

--no-advice を指定すると、アドバイザリーセクション全体が省略されます。証拠以外を求めないゲート向けです。

エージェントにかかるコスト

heides はモデルによる読み取りを想定して構築されているため、呼び出しの戻り値は単なる回答ではなく、予算に関わります。このリポジトリでの測定結果は次のとおりです。

呼び出しバイト数トークン数
すべての Rust ファイルを1回ずつ読む1,105,462276,365
describe6,4971,624
describe --brief5,1161,279
アドバイス付き harmony.check(MCP)4,8271,206
デフォルトの harmony.check(MCP)718179

概要の取得にかかる量は、ソースを読む場合の169分の1です。MCP 経由では、harmony.check は証拠のみを返し、advice: true を指定するとスタイル上の意見も返します。エージェントはその意見に対応できず、ゲートもそれを理由に失敗させられないためです。CLI は完全な記録を保持します。ターミナルを使う人は、意図的に全体を読んでいるからです。

結果が会話を終わらせてしまわないように、2つのフラグを用意しています。

  • describe の --brief は、ルールの測定結果、ドキュメントのカバレッジ、ドキュメント化されていないシンボルの一覧を省略します。エージェントが対応するデータではなく、ゲートを評価する人向けの記録です。
  • harmony.check の max_bytes は、設定した予算に合わせて結果を切り詰めます。切り詰めは行の境界で行われ、省略された内容も報告されるため、上限付きの結果を完全な結果と取り違えることはありません。
insight

heides の間で見解が食い違う箇所と、変更が及ぼす影響を示します。

heides insight contradictions   # signals that cannot both be true
heides insight impact <symbol>  # what editing this could reach
heides insight coverage         # where no rule can fire at all
heides insight baseline save    # record today's findings as known
heides insight baseline         # what is new since that baseline

contradictions は独立して計算したシグナルを比較するため、食い違いは推測ではなく証拠になります。たとえば、定義に一致するものがないハンドラーを持つルート、デッドコードのルートチェックでも到達不能と判定されるハンドラー、ドキュメントが充実したファイル内で最も多く呼び出されているにもかかわらずコメントがない関数、どこからも到達されず、どこも呼び出していないファイルなどです。

impact は、エージェントが編集の前に必ず尋ねる問いに答えます。変更の推移的な呼び出し元の数、変更に伴って影響を受けるファイル、その背後にあるルート、そしてテストから到達可能かどうかを報告します。「呼び出し元が4つ」と「呼び出し元が4つあり、テストから到達できない」は異なる答えだからです。

coverage は、問題なしという判定に意味がない箇所を示します。rust: 44 file(s) indexed, no taint rule can fire on any of them は「問題なし」とは異なる記述であり、対応する価値があるのはそのうち片方だけです。

baseline は、膨大な検出結果を差分に変換します。新しい検出結果は、以前から存在するものより重要です。また、検出結果のキーは行番号を無視するため、ファイルが下に移動しただけでベースラインがノイズだらけになることはありません。

実行記録

すべての check は、問題がない実行でも、実際に何を確認したかを最後に示します。

analysed 12 of 12 indexed file(s)
languages: javascript, typescript, python

これは単なる飾りではありません。検出結果のないワークスペースと、一度も解析されていないワークスペースが、まったく同じ表示になっていました。どちらなのかを示せないチェックは、いずれの結果も信頼できません。実行記録には、完全にはカバーできなかった言語も記載され、言語が不完全となる2つのケースが区別されます。

languages: rust
no taint rules for: rust (indexed, taint not scanned)

languages: ruby
taint scanned, no grammar: ruby (no symbols in the graph)

1つ目はインデックス化されているものの、フローのスキャン対象ではありません。2つ目はフローのスキャン対象ですが、グラフにシンボルを提供しません。この2つは異なる不足であり、違いを無視すればツールはユーザーの信頼を失います。

インデックス化されたファイルをすべて読み取れなかった場合や、依存関係レジストリにアクセスできなかった場合、部分的な結果を完全な結果として報告せず、その旨を伝えます。

コントリビューション

プルリクエストを作成する前に CONTRIBUTING.md を読んでください。RULES.md は仕様書です。ハーネスが実行するすべてのルールについて、正確な発火条件、重大度、保証が記載されており、動作を偶然ではなくレビュー可能なものにします。

開発

cargo build --release
cargo test

同じゲートが、すべてのプッシュとプルリクエストで CI 上でも実行されます。フォーマット、警告をエラーとして扱う clippy、ビルド、そして全テストスイートが対象です。全テストスイートには、イディオムに沿ったコードでルールが発火すると失敗するクリーンコーパスゲート、ランダムなバイト列や大量の波括弧をパーサーに与える耐障害性テストスイート、パフォーマンス予算を満たすことを検証するスケールフェーズ、バイト単位で同一の出力と同一のインデックスを要求する決定性テストが含まれます。

ライセンス

MIT。LICENSE を参照してください。

コメント

MCP は初めてですか?

プロトコルの概要から最初のサーバーの導入まで、よくある疑問にまとめて答えます。

AI アプリケーションが外部のツールやデータソースに統一的な方法で接続するためのオープンなプロトコルです。クライアントはモデルとの対話を担い、MCP サーバーはツール・リソース・プロンプトテンプレートを提供します。標準メッセージでやり取りするため、1 つのサーバーを複数のクライアントで再利用できます。