mcpField
M
mantis-architecture

mantis-architecture

github.com/googleセキュリティ2.7k1.6k 回インストール3 日前に更新
リポジトリ

mantis-architecture について

mantis-architectureは、リポジトリ分析向けのセキュリティナレッジベース構築スキルです。コード構造と最新・過去の学習内容を統合し、相互リンクされたMarkdownの構成、コンポーネント、脆弱性の記録を維持します。

主な機能

  1. 01コンポーネントと信頼境界の分析
  2. 02リンク付きMarkdownナレッジベースの作成
  3. 03アーキテクチャと脆弱性パターンの記録
  4. 04依存関係の抽出
  5. 05学習内容と各パスのナレッジベースを保存

活用シーン

  1. 01コードベースのセキュリティ文書の作成
  2. 02ソース変更に合わせたコンポーネントと脆弱性記録の更新
  3. 03分析パス間でのセキュリティ学習の保存

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/google/mantis --skill mantis-architecture

インストール後、Claude Code で/mantis-architectureを入力して読み込まれたか確認します。

詳細

アーキテクト(/mantis-architecture)

システムの目標

ナレッジベースの統合ツールです。学習キュー(workspace/learnings.jsonl)の一時的な知見とコードベースの構造分析を、正規の相互リンク付き Markdown ナレッジベース(workspace/kb/)に変換します。

コマンドの定義

  • コマンド: /mantis-architecture
  • 説明: システムアーキテクチャを定義し、特定のエンティティ(コンポーネント)をマッピングし、過去の脆弱性パターンを分類して、KB の基盤を構築します。
  • 引数(すべて省略可能。LOCATOR RESOLUTION / Block A によって解決されます): --snapshot_root=<dir>(または SNAPSHOT_ROOT 環境変数)— 対象ソースの読み取り元となる固定コードスナップショットです。--snapshot_id=<id> — そのスナップショットの SNAPSHOT_ID です。--state_root=<dir> — すべての状態および KB のパスにおける workspace/ の親ディレクトリです。--target_root=<dir> — スナップショットより優先される、準備済みのツリーです(このステージに渡されることはまれです)。いずれも指定されない場合、現在の動作とバイト単位で同一の動作(劣化状態/固定なし)となり、現在のディレクトリからソースを読み取り、snapshot_pinned を false として扱います。

入出力の契約

  • 読み込み:
    • workspace/learnings.jsonl(現在のラウンドから得られた未加工の知見)。
    • workspace/historical_learnings.jsonl(任意、過去の脆弱性メタデータ)。
    • コードベースのディレクトリ構成と主要なソースファイル。
    • workspace/kb/ 内の既存の Markdown ファイル(検証/陳腐化チェック用)。
    • workspace/.mantis_state.json(パス数の取得用)。
    • workspace/.mantis_state.json → active_snapshot(root、snapshot_id、snapshot_pinned)および snapshot_history — KB の鮮度ゲート(ステップ 0b)用の出所情報。スナップショットは STATE からのみ読み取ってください。KB の鮮度を判定するために、実行中の VCS コマンド(git/hg/repo)は絶対に実行しないでください。
    • workspace/.mantis_state.json → kb_snapshot_id(現在の KB が最後にビルドされた対象の SNAPSHOT_ID。初回またはレガシー KB では存在しません)。
    • workspace/.mantis_state.json → changed_files および changed_files_status(mantis-plan の Block E が書き込み、ステップ 0b の結果 3 における対象を絞った KB 無効化で使用します。パス 2 以降に存在しますが、古い場合があります(前のパスで書き込まれている場合)。対象を絞った処理では changed_files_pass と state.pass_number を照合し、一致しない場合は全体を再構築します)。
  • 書き込み:
    • workspace/kb/ 以下の Markdown ファイル(architecture.md、entities/[component_name].md、vulnerabilities/[CWE-ID].md、index.md)。
    • workspace/kb/dependencies.json — アーキテクチャ分析中に抽出したインポート/依存関係エッジの JSON マップ(キー = CODE_ROOT からの相対パスであるソースファイルパス、値 = キーのファイルをインポート/依存するファイルの配列)。これは、mantis-plan の依存関係を考慮したファンアウト(フェーズ 2)で使用されます。コードベースに解析可能なインポート構造がない場合は、{} を書き込みます。対象を絞った無効化では、変更されたエントリーのみを再導出します(下記の結果 3 を参照)。
    • workspace/learnings.jsonl を workspace/archive/learnings/learnings_pass_${N}_${X}.jsonl にアーカイブします。
    • すべての KB ファイル(index.md、各 entities/*.md、各 vulnerabilities/*.md)の(再)書き込み時に、その最初の行として `` マーカーを付けます。また、workspace/.mantis_state.json の kb_snapshot_id = SNAPSHOT_ID とします。
    • KB 全体のツリーをパスごとの不変なコピーとして workspace/archive/kb/kb_pass_${N}_${X}/ に保存します(後で修正が取り消されても、パス N 時点で KB が何を記録していたかがひそかに消されないようにします)。
  • 前提条件:
    • workspace/learnings.jsonl が存在している必要があります。
  • 冪等性の保証:
    • トランザクション処理:すべての KB Markdown の更新が正常に書き込まれたことをプログラムで検証した後にのみ、workspace/learnings.jsonl をアーカイブに移動します。KB ファイルはその場で上書きされます。
    • スナップショットのスタンプ処理も同じトランザクションの一部です。KB_SNAPSHOT マーカー、パスごとの workspace/archive/kb/kb_pass_${N}_${X_kb}/ コピー、および kb_snapshot_id の状態書き込みは、learnigns の移動前、または同時に完了します。失敗した場合は、workspace/learnings.jsonl をそのまま残します。

手順

コードベースと保留中の学習内容を分析し、将来のエージェント向けの永続的な Markdown ベースのメモリを構築します。

アーキテクチャの段階を次のように実行します。

  1. ロケーターの解決(Block A、以下にインラインで記載):
LOCATOR RESOLUTION (before reading ANY target code or artifact):
0. ROLE: If this skill NEVER reads target source (report, calibrate, reflect),
   you are a FINDINGS-ONLY stage: skip steps 2-6; still read active_snapshot from
   state for provenance/annotation; NEVER stop merely because a code root is unset.
1. Determine CODE_ROOT, in this priority order:
   a. If --target_root is passed on THIS invocation, CODE_ROOT = --target_root.
      It is AUTHORITATIVE and OVERRIDES SNAPSHOT_ROOT and the state fallback
      (used when a caller hands you a prepared tree, e.g. a patched shadow).
   b. Else if --snapshot_root (or SNAPSHOT_ROOT) is passed, use it.
   c. Else read state_root/workspace/.mantis_state.json (state_root from
      --state_root if passed, else ./workspace/... relative to the current dir)
      -> active_snapshot.root / .snapshot_id / .snapshot_pinned.
   d. Else (no arg AND no readable active_snapshot): CODE_ROOT = current directory,
      treat snapshot_pinned = false (MODE-OFF). Do NOT stop.
2. SENTINEL CHECK (only if snapshot_pinned is true AND you did NOT take path 1a):
   verify CODE_ROOT/.mantis_snapshot_id exists and equals SNAPSHOT_ID. If missing
   or different -> STOP "snapshot sentinel mismatch". (A --target_root tree (1a) is
   deliberately mutated and is sentinel-EXEMPT.)
3. PATH FIELDS:
   - SNAPSHOT-RELATIVE (read under CODE_ROOT): code_paths entries; plan target_files
     that are file paths. Strip ONLY a trailing ":<digits>". A code_paths entry
     containing "://" is a URL/endpoint, NOT a file read. A code_paths entry that is
     NOT of the form <existing-path>:<integer> is a non-source LOCATOR
     (symbol/offset/endpoint): only check that the artifact/symbol exists; skip ALL
     line-range and line-existence logic.
   - STATE-RELATIVE (read/write under state_root/workspace, NEVER prefix CODE_ROOT):
     kb_references, repro_file_path, reattack_file_path, helper scripts, report
     files, and all state/findings JSON.
4. Never WRITE under CODE_ROOT when snapshot_pinned is true. Any command that
   compiles, generates, or writes artifacts MUST run in a PRIVATE SHADOW copy
   (mktemp -d from CODE_ROOT), never with cwd=CODE_ROOT. Read-only inspection may
   cd into CODE_ROOT.
5. VCS-METADATA CARVE-OUT: history-log extraction and any VCS diff/blame command
   run in the LIVE repository root (which still has .git/.hg/.repo), NOT CODE_ROOT
   (the snapshot copy strips VCS metadata). Do NOT stop merely because CODE_ROOT
   lacks .git/.hg/.repo.
6. Every shell command uses ABSOLUTE paths and sets its own working directory on
   that call. Do NOT assume the working directory persists between calls.

これはコードを読み取る段階です(ステップ 2 と 4 で対象ソースを読み取ります)。そのため、Block A のステップ 1〜6 がすべて適用され、調査結果のみを扱う段階ではありません。以下の作業を行う前に、状態から CODE_ROOT、SNAPSHOT_ID、snapshot_pinned を解決してください。Block A のステップ 3 に従い、すべての workspace/kb/... パスは STATE 相対です。state_root/workspace の下で読み書きし、CODE_ROOT の下は絶対に使用しないでください。対象ソースはすべて CODE_ROOT の下から読み取ってください。KB の鮮度を判定するために VCS コマンドを実行しないでください(Block A のステップ 5 にある例外は、この段階では使用しない履歴/差分/blame のためのものです)。

0b. KB スナップショット鮮度ゲート(機械的処理。STATE と KB マーカーのみを使用し、実行中の VCS は使用しない):

- `CUR` = `SNAPSHOT_ID` (resolved by Block A; the empty string if
  `active_snapshot` was absent). `PINNED` = `snapshot_pinned` (false if absent).
- **MODE-OFF short-circuit (3-state rule):** if `active_snapshot` is ABSENT
  in state (no `--sync` was requested — MODE-OFF = today's default), SKIP the
  freshness gate entirely: do a best-effort build/update against `CODE_ROOT`,
  do NOT prepend any STALE banner, and do
  NOT stamp `kb_snapshot_id`. This is byte-for-byte today's behavior. (Only
  HALT and PINNED run the gate below.)
- `KB_ID` = the `kb_snapshot_id` value in `.mantis_state.json` (primary); else the
  text after `KB_SNAPSHOT:` on the FIRST line of
  `state_root/workspace/kb/index.md` if that file exists (secondary fallback,
  for legacy runs without state); else `""` (no prior KB). State is primary so
  the file-marker parsing pitfall (comment-wrapped first line, no `-->`
  stripping) can never strand `KB_ID` with the comment closer and force BUILD
  FRESH every pass.
- Choose EXACTLY ONE outcome by string checks, top to bottom, first match wins:
  1. `PINNED` is false (HALT mode — `active_snapshot` present but unpinned)
     ->  **STALE / HALT.** Do a best-effort build/update against `CODE_ROOT`,
     but PREPEND the STALE banner (below) as the first lines of `index.md`.
     Do NOT claim currency: leave the
     banner in place. Set `kb_snapshot_id` = `CUR` (a `live:` id).
  2. Else `KB_ID` == `CUR` (both non-empty)  ->  **CURRENT.** Do the incremental
     update + decay-check (step 4) as today. Re-stamp `KB_SNAPSHOT: CUR` on
     every (re)written file. REMOVE any STALE banner previously prepended to
     `index.md`.
  3. Else (`PINNED` true AND (`KB_ID` is empty OR `KB_ID` != `CUR`)) ->
     **BUILD FRESH (full or scoped re-architecture).** The pinned code advanced
     since the KB was built (a sync / pass-boundary change), OR the KB is
     unstamped / legacy. Choose full or scoped:
     - **Scoped invalidation (Phase 2 incremental efficiency):** If
       `changed_files_status` is known (not UNKNOWN) AND the KB already has a
       `KB_SNAPSHOT` stamp (KB_ID was non-empty, just different) AND
       `changed_files_pass` equals the current `state.pass_number` (the diff
       is from THIS pass, not a stale prior pass — absent or different →
       treat as UNKNOWN → full rebuild below), attempt a SCOPED rebuild: only
       invalidate KB entries whose source files are in `changed_files`, plus
       their parent-rollup dependents (KB entities that import/reference the
       changed files). Re-derive ONLY those entries from `CODE_ROOT`; carry
       forward all other KB entries unchanged (they were built against the
       same code, just a different snapshot ID). Re-stamp `KB_SNAPSHOT: CUR`
       on every (re)written file.
        - **Parent-rollup (2-hop, matching plan's fan-out):** When
          invalidating a KB entry for changed file F, also invalidate any KB
          entry that REFERENCES F directly (1-hop) AND any entry that
          references a 1-hop dependent of F (2-hop). This matches
          `mantis-plan`'s dependency-aware fan-out (which expands up to 2
          hops), ensuring that a grandchild entity (H imports G, G imports
          changed F) is not carried forward stale and later fed as a
          `kb_reference` while its dependency has changed.
       - **Guardrail:** If ANY uncertainty arises (can't determine which KB
         entries map to which source files, the KB structure is ambiguous, or
         changed_files is empty but KB_ID != CUR), fall back to full rebuild
         below. Never carry forward a stale entry for a changed file.
     - **Full rebuild (Phase-1 fallback):** If KB_ID is empty (no prior KB),
       OR `changed_files_status` is UNKNOWN, OR the scoped invalidation guardrail
       fired, REBUILD every KB file from scratch against `CODE_ROOT`. Do NOT
       carry forward any prior assertion you have not re-derived from
       `CODE_ROOT` this pass. Stamp `KB_SNAPSHOT: CUR`. REMOVE any STALE banner.
- STALE banner (paste verbatim, substituting `<KB_ID>` and `<CUR>`; keep the
  leading `>` on every line so it renders as a visible blockquote):

  ```
  > **STALE KB WARNING — do not trust without re-verifying.**
  > snapshot_pinned=false, or the KB was built against a different snapshot.
  > KB_SNAPSHOT=<KB_ID> does not match active_snapshot.snapshot_id=<CUR>.
  > Every SECURE/FIXED/NON_VIABLE/SAMPLE_OR_TEST claim below is UNVERIFIED
  > against the current code. Re-verify before trusting; do NOT filter, skip,
  > or down-prioritize work based on this KB.
  ```
  1. 受信箱を読み取ります(workspace/learnings.jsonl および workspace/historical_learnings.jsonl):

    • workspace/learnings.jsonl の内容(および存在する場合は workspace/historical_learnings.jsonl)を解析します。すべての トラジェクトリの知見、発見された脆弱性、実行可能なクラッシュパス、および 検証済みのパッチを抽出します。
  2. ソースコードの境界を分析:

    • CODE_ROOT 配下のディレクトリ構造と主要なソースファイルを調査します (ブロック A で解決された固定スナップショット。ブロック A の ステップ 6 に従って絶対パスを使用し、VCS コマンドを実行しないでください)。リポジトリの内容に基づいて、システムのコア コンポーネント、インターフェース、信頼境界を動的に特定します。これはドメインを問わず広く当てはまります。 ソフトウェアシステム(例:パーサー、コントローラー、ネットワーク デーモンの特定)、ハードウェア/RTL 設計(例:IP ブロック、JTAG インターフェース、メモリコントローラーの特定)、Infrastructure-as-Code(例: クラウド権限、VPC 境界、デプロイ記述子の特定)、 またはデータ/ML パイプライン(例:データ ingress ポイント、モデル シリアライゼーション機構、トレーニング境界の特定)のいずれであっても同様です。
  3. ナレッジベース (KB) の構築または更新:

    • 標準の Markdown を使用して workspace/kb/ ディレクトリ内のファイルを 作成または更新します。以下の厳密なパスに従ってください:

      • workspace/kb/architecture.md: 高レベルのデータフロー、ゾーン定義、 システム設計、および全体的な可用性/稼働時間要件(文書化されている場合、または systemd、kubernetes、 ロードバランサーなどの構成から推測できる場合)。
      • workspace/kb/entities/[component_name].md: コンポーネントの具体的な定義 (例:auth_module.md)。関連する脆弱性クラスへのリンクを含め、 既知の制約(例:「このモジュールは入力 X をサニタイズする」)を文書化する必要があります。コンポーネントの重要度と 可用性要件(該当する場合は CRITICAL、STANDARD、または LOW_CRITICALITY として分類)を文書化します。ここにトラジェクトリの知見を組み込みます。
      • workspace/kb/vulnerabilities/[CWE-ID_or_BugClass].md: このコードベースに 歴史的に関連してきたバグクラス(例:CWE-79.md または Memory-Corruption.md)の説明。やってはいけないことの 例を含みます。
      • workspace/kb/index.md: 上記で作成されたすべてのファイルへのリンクと 1 行の 要約を含むルートカタログ。これは Planner が 読み取るマップです。
    • 重要なフォーマットルール: エンティティと脆弱性を相互参照するには 相対リンクを使用します(例: [Auth Module](entities/auth_module.md))。すべての markdown ファイルは簡潔にし、 実行可能なセキュリティコンテキストに焦点を当ててください。

    • スナップショットスタンプ(フレッシュネスゲートの実行時、すなわち HALT または PINNED の場合、 (再)書き込みされるすべての KB ファイルで必須。MODE-OFF では決して行わない): index.md、 各 entities/*.md、および各 vulnerabilities/*.md の最初の 行を正確に にします(ステップ 0b の `CUR` を代入。これは HTML コメントなのでレンダリングされません)。これが次の パスのフレッシュネスゲート(ステップ 0b)でドリフトを検出する方法です。**MODE-OFF ゲート(3 状態ルール):** `active_snapshot` が ABSENT の場合(MODE-OFF — `--sync` が要求されていない)、ファイルごとの `KB_SNAPSHOT` マーカーを スタンプしないでください: `CUR` は 空文字列(`arch:145`: 「`active_snapshot` が 存在しない場合は空文字列」)なので、必須のマーカーは(空の 値)になります — これは Phase 1 には存在しなかったスナップショット時代の成果物です。ファイルごとの マーカーはステップ 0b のフレッシュネスゲートによってのみ消費され、 MODE-OFF はそれを完全にスキップします(arch:147-152: 「フレッシュネスゲートを 完全にスキップする... これは今日の動作とバイト単位で同一です。HALT と PINNED のみが 以下のゲートを実行します。」)。この MODE-OFF ゲートは、以下のフレッシュネスゲートのロジック およびステップ 0b の結果条項を反映しており、それらはファイルごとの KB_SNAPSHOT: CUR スタンプについて HALT/PINNED の結果(CURRENT :164、 スコープ付き BUILD FRESH :178、完全な BUILD FRESH :195)でのみ言及しています。

    • ファイルごとの KB_SNAPSHOT スタンプ付与が、KB のアサーションに対する唯一の来歴メカニズムです。 アサーションごとに (AS_OF:<snapshot>) タグを書かないでください。AS_OF 再検証リーダーは決して実装されておらず、陳腐化保護はすでにフレッシュネスゲート (ステップ 0b) が kb_snapshot_id を SNAPSHOT_ID と比較すること、および所見ごとの discovery_commit (mantis-critic のブロック B で強制) によって提供されています。後から差し戻された修正は、アサーションごとのタグではなく、これらのメカニズムによって捕捉されます。

  4. ナレッジの検証と減衰 (ドリフト防止):

    • コードがパッチまたはリファクタリングされると、ナレッジは陳腐化します。KB の更新を確定する前に、既存の workspace/kb/entities/ 内のアサーションを、CODE_ROOT 配下のソース (固定されたスナップショット — ライブの VCS クエリではなく、ライブの作業ツリーでもありません) と突き合わせてスポットチェックしてください。BUILD FRESH の結果 (ステップ 0b) では、スポットチェックをまったく行わないでください。以前のアサーションを破棄し、今回のパスで CODE_ROOT からすべてのエンティティを再導出します。STALE / HALT の結果では、ベストエフォートでのみスポットチェックを行い、結果にかかわらず STALE バナーを維持してください。
    • エンティティファイルが、ある変数がサニタイズされていないと主張している (古い学習に基づく) のに、ライブコードが現在サニタイズ関数を含んでいる (パッチが適用されたため) 場合は、その古い学習を KB から削除または修正してください。
    • ある学習が現在のトラジェクトリインサイトによって繰り返し誤りと証明される場合は、その「誤った学習」が持続して将来のエージェントを盲目にしないよう、積極的に修正してください。
    • 所見に由来するアサーションを修正または再確認する際は、その KB ファイルの KB_SNAPSHOT マーカーを再スタンプしてください。
  5. トランザクションによる受信箱のクリアとアーカイブ:

    • 無限ループやトークンの肥大化を防ぐため、キューをクリアして学びをアーカイブする必要があります。
    • 検証して確定する: Markdown の KB 更新がすべてディスクに正常に書き込まれ、相互参照が有効であることをプログラムで検証します。また、コミットする前に、(再)書き込みされたすべての KB ファイルが `` マーカーで始まっていること、および調査結果に基づくすべての判定が現在の SNAPSHOT_ID に根拠を置いていることを確認します。
    • 移動してコミットする: 統合の成功を検証した後に限り、workspace/learnings.jsonl をアーカイブディレクトリに移動します。
      • ターゲットディレクトリが存在することを確認します(例: mkdir -p workspace/archive/learnings/)。
      • workspace/.mantis_state.json から "pass_number" を読み取り、ループのパス番号 N を特定します。値がないか無効な場合は、workspace/archive/ を検索して findings_pass_N または loopN_findings に一致するフォルダーを探し、アーカイブがない場合は 1、ある場合は max_found + 1 を N とします。
      • workspace/archive/learnings/ 内で learnings_pass_${N}_*.jsonl に一致する既存ファイルを数え、1 を加えてサブインデックス X を特定します。
      • ファイルを移動します。 mv workspace/learnings.jsonl workspace/archive/learnings/learnings_pass_${N}_${X}.jsonl
    • KB のスナップショットを作成する(パスごとのアーカイブ): 統合が正常に完了した後、KB ツリー全体をパスごとのアーカイブにコピーします。
      • ディレクトリが存在することを確認します(mkdir -p workspace/archive/kb/)。
      • サブインデックス X_kb = workspace/archive/kb/ 内にある既存の kb_pass_${N}_* ディレクトリ数 + 1 を計算します。
      • コピーします(移動はしないでください。次のパスでもライブの workspace/kb/ を保持する必要があります)。cp -a workspace/kb/. workspace/archive/kb/kb_pass_${N}_${X_kb}/
    • 状態を記録する: kb_snapshot_id = SNAPSHOT_ID(手順 0b の CUR)を workspace/.mantis_state.json に書き込みます。active_snapshot が存在しない場合(MODE-OFF)は、kb_snapshot_id を書き込まず、STALE バナーも追加しないでください(鮮度ゲートはスキップされています)。HALT モードでは、kb_snapshot_id = CUR を書き込み、index.md の STALE バナーはそのまま残します。
    • 統合に失敗した場合、または中断された場合は、データが失われないよう workspace/learnings.jsonl を元の場所にそのまま残します。
    • 実行開始時に workspace/learnings.jsonl が存在しない場合(例:このパスですでに Stage-2 の呼び出しでアーカイブされているため、Stage-15 の呼び出しで存在しない場合)は、学びの移動だけをスキップします。鮮度ゲート(手順 0b)の実行、KB_SNAPSHOT マーカーの記録、kb_snapshot_id の書き込み、パスごとの KB アーカイブのコピーは、引き続き行います。KB の来歴は、すべての呼び出しで記録する必要があります。

完了したら、ユーザーに通知します。

コメント