mantis-meta-agent について
mantis-meta-agentは、Mantisのセキュリティレビューを継続的に管理するスキルです。監査とパッチ作成を専門のサブエージェントに委任し、必要に応じて上流との同期やスナップショット固定を行います。
主な機能
- 01レビューキャンペーンの継続管理
- 02専門サブエージェントへの委任
- 03上流との任意同期
- 04パス単位のスナップショット固定
- 05検出結果と状態のアーカイブ
活用シーン
- 01複数回のセキュリティレビュー実施
- 02長期セキュリティパイプラインの調整
- 03レビュー対象をスナップショットに固定
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ google/ mantis --skill mantis-meta-agentインストール後、Claude Code で/mantis-meta-agentを入力して読み込まれたか確認します。
詳細
メタエージェントオーケストレーター(/mantis-meta-agent)
システムの目標
自律型キャンペーンマネージャーです。継続的なレビューのループを監督し、レジリエンスを確保して、長時間実行されるセキュリティパイプラインを監視します。
コマンドの定義
- コマンド:
/mantis-meta-agent - 説明: 永続的なスーパーバイザーとして機能し、自動レビューキャンペーンを開始して監視します。
- パラメーター:
--sync:オプトイン方式の境界同期とスナップショットの固定です。このオプションが指定された場合(または今回のパスで同期するようユーザーが明示的に指示した場合)、パスの開始時(ブロック C)にターゲットをアップストリームと同期し、パスごとの不変スナップショットを固定します(ブロック D)。指定されていない場合(デフォルト)は、同期も固定も行いません。active_snapshot/snapshot_historyは書き込まず、snapshot_pinnedは未設定のままにして、現在とまったく同じようにライブツリーに対してパスを実行します(単一の静的スナップショット。--target_rootのセマンティクスは変更されません)。--snapshot_keep=<N>:固定済みスナップショットを<state_root>/.mantis_snapshots/に保持する数です(ブロック D のステップ 6 の GC)。デフォルトは 2 件(今回のパスと前回のパス)です。正確性のために古いスナップショットを再読み込みすることはないため安全です。検出時のスナップショットを基にパッチや PoC をリベースする場合は、数を増やしてください。--state_root=<absolute path>:workspace/と.mantis_snapshots/を含むディレクトリです。デフォルトは、メタエージェントの起動時における現在の作業ディレクトリの絶対パスです(つまり、workspace/の親ディレクトリです)。state_rootがCODE_ROOT内に解決される場合(同じ場所に配置されるケース。ターゲットリポジトリ内から起動するとデフォルトで該当します)、ステップ 3(PIN)では(a)処理を停止し、--state_rootにCODE_ROOT外のパスを指定するようユーザーに伝えなければなりません。これはデフォルトの動作であり、明示的なオプトインがない場合に安全な唯一の動作です。自動移動(選択肢 b)は、--auto_relocate_stateフラグを明示的に指定した場合(または今回のパスで自動移動するようユーザーが同等の指示をした場合)に限り、オプトインとなります。これがない場合、ユーザーの状態を移動してはなりません。ユーザーが明示的にオプトインした場合、workspace/と.mantis_snapshots/をCODE_ROOT外の兄弟ディレクトリに移動し、パスの残りの処理ではstate_rootを更新します。これはmantis-pipeline-adapterのシナリオ 1 で必要とされる「同じ場所に配置された状態」の移行です。移動はコピー後の削除ではなく MOVE です。また、workspace/.workspace_edit.lockが保持されている場合はスキップします(INV-5:ユーザーデータの損失防止)。MOVE は同じファイルシステム上でアトミックに行わなければなりません。兄弟ディレクトリの親の下に新しい一時ディレクトリを作成してそこへ移動し、その後rename(2)で最終的な兄弟パスに変更します。兄弟ディレクトリがすでに存在する場合、または一時ディレクトリを作成できない場合は、既存のディレクトリを上書きせずに処理を停止します。rename(2)が失敗した場合は、移動元に変更を加えずに処理を停止します。コピー後の削除にフォールバックしてはなりません。--auto_relocate_state:オプトイン用フラグです。state_rootがCODE_ROOT内に解決される場合(同じ場所に配置された状態。ターゲットリポジトリ内から起動するとデフォルトで該当します)、デフォルトでは処理を停止し、ユーザーに判断を委ねます。このフラグを指定する(または同等の指示をユーザーが行う)と、上記の--state_rootで説明した、アトミックな MOVE による自動移動を許可します。このオプションがない場合、ユーザーの状態を移動してはなりません。
入出力契約
- 読み取り:
- 現在のループパスを追跡し、スナップショットの由来情報と Block E の PREV 参照を確認するため、
workspace/.mantis_state.jsonのactive_snapshot/snapshot_historyを読み取ります。 - サブエージェント間の引き継ぎ時に状態を確認するため、
workspace/findings/内の個別の JSON 検出結果を読み取ります。各検出結果のpatch_statusも、事前同期のバックアップ衛生ゲートのために確認します。 - 事前同期のバックアップ衛生ステップの GATE A として、
workspace/.workspace_edit.lockを読み取ります。古い*.bak-*ファイルを削除する前に、ロックが FREE でなければなりません。 - Block D のステップ 0 におけるスナップショット再利用/STOP チェックのため、
CODE_ROOT/.mantis_snapshot_idセンチネルを読み取ります。
- 現在のループパスを追跡し、スナップショットの由来情報と Block E の PREV 参照を確認するため、
- 書き込み:
- アーカイブディレクトリ
workspace/archive/findings_pass_N/を作成し、検出結果の JSON ファイルと.trash/をそこへ移動します。また、(Stage 15)パス境界の参照用としてworkspace/.mantis_state.jsonとworkspace/kb/(THREAT_MODEL.mdを含む)をそこへコピーします。 workspace/.mantis_state.jsonを更新します。pass_numberをインクリメントし、last_updatedを更新し、vcs_infoは常にリフレッシュします。このパスで--syncが指定されていた場合は、さらにactive_snapshot({root, snapshot_id, snapshot_pinned, pass, vcs_type})を書き込みます。snapshot_pinnedは実際の状態を反映します(ピン留めされている場合はtrue、HALT 中はfalse)。snapshot_historyは Block D のステップ 5 で追記されます(パスごとに 1 件:{pass, snapshot_id, snapshot_pinned, timestamp})。以下の Step 4 RECORD では再追記しません。これらの新しいキーはschema.jsonの#/$defs/stateで定義されています。MODE-OFF(--syncなし)では任意項目であり、存在しません。--syncがスナップショットをピン留めする場合(Block D)、<state_root>/.mantis_snapshots/pass_<N>/の下に不変のスナップショットコピーを作成します(意図的に/workspace/のパスセグメントの外に配置することで、mantis-patch に既存の state-vs-code パスガードが引き続きこれを state ではなく CODE として扱うようにします)。CODE_ROOT/.mantis_snapshot_idセンチネルを書き込み、コピーに対してchmod -R a-wを実行します。
- アーカイブディレクトリ
- 前提条件:
- 対象プロジェクトが特定されている必要があります。キャンペーンのオーケストレーションツール/サブエージェントが利用可能な状態でなければなりません。
- 冪等性の保証:
workspace/findings/が空または存在しない場合は、検出結果の移動をスキップします(state/KB の境界コピーは引き続き実行します)。新しい実行時に既存のアーカイブを上書きしないよう、state ファイルがない場合はディスクからパス番号を一度だけ動的に特定します。- スナップショットのピン留めはクラッシュセーフです。センチネルが再計算した
SNAPSHOT_IDと一致する、すでに作成済みのスナップショットがあれば Block D で再利用し、一致しなければ STOP します(再利用または STOP)。keep-N GC(--snapshot_keepで設定可能、デフォルトは 2)では、対応するティアダウン処理とともに古いスナップショットを削除します。
手順
Mantis の防御的セキュリティレビューのパイプラインを継続的に実行する、永続的かつ長期稼働のスーパーバイザーとして動作してください。
対象形式に関する指示: 評価対象は、生のソースコード、コンパイル済みバイナリ、ファームウェアの blob、または稼働中のステージング/開発エンドポイントである可能性があります。対象が現在どのような形式であるかに応じて分析してください。利用可能な適切なツール(標準的な Unix ツール、
unblob、radare2、angr、objdump、Ghidra、qemu、unicorn、エミュレーターハーネスなど)を使って、検出結果を抽出、分析、再現、テストすることが許可されており、また推奨されています。ソースコードが利用できない場合は、ソースコードを前提とするワークフローを無理に進めず、対象の成果物に適した方法で対応してください。サブエージェントが利用可能なツールを把握していることを確認してください。
監査やパッチ適用のタスクを自分で実行しないでください。代わりに、コンテキストを効率的に維持し、タスクを分離するため、専門のサブエージェントに委任してください。
以下の継続的なループでオーケストレーション業務を実行してください。
-
サブエージェントのオーケストレーションループ: レビューループの各反復で、ループパスカウンター
Nを維持してください。-
初期化 / 起動:
workspace/.mantis_state.jsonの"pass_number"からNを読み取ります。存在しないか無効な場合は、workspace/archive/をスキャンしてfindings_pass_NまたはloopN_findingsに一致するフォルダーを探し、Nをmax_found + 1に解決します(アーカイブが存在しない場合はデフォルトで 1 になります)。境界同期とスナップショットのピン留め — パスライフサイクル CONTRACT(厳密な順序)。 毎回のパスの開始時に、以下の 4 つのステップを厳密にこの順序で実行します。パスライフサイクル Contract(
schema.json→ "Non-JSON Contracts")は、最初に SYNC すること、および同期前にスナップショット id を記録したりコピーをピン留めしたりしないことを要求します。これらのステップの順序を入れ替えたり、スナップショットの書き込みより前にステップ 1 を飛ばしたりしないでください。同期はオプトインです。 ステップ 1(SYNC)とステップ 3(PIN)は、
--syncが渡された場合、またはユーザーがこのパスでの同期を明示的に指示した場合にのみ実行します。それ以外の場合(デフォルト): ステップ 1 と 3 を完全にスキップし、active_snapshotやsnapshot_historyを書き込まず、snapshot_pinnedを未設定のままにし、これまでとまったく同様にライブツリーに対してパスを実行します。デフォルトモードでもステップ 2(新しい VCS 検出)は実行し、vcs_infoを記録します。ガード: 同期(ステップ 1)は、そのパスの最初の変更操作でなければなりません。このパスでステップ 1 が完了する前に、
snapshot_idを計算または記録したり、active_snapshotを書き込んだり、コピーをchmod/ピン留めしたりしないでください。-
SYNC(そのパスの最初の操作でなければなりません。
--syncのみ)。 まず、同期前のバックアップ衛生処理 — 中断された@mantis-patchの実行によって残された古い*.bak-*ファイルを削除しますが、安全な場合に限ります:- GATE A: ワークスペース編集ロック
workspace/.workspace_edit.lockが FREE でなければなりません(進行中のパッチがない)。ロックが保持されているか、ノンブロッキングで取得できない場合は、削除をスキップして同期に進みます(とにかく Block C STEP 0 がダーティチェックから*.bak-*を隠します)。 - GATE B:
workspace/findings/内のすべての finding でpatch_statusが設定されている(パッチ適用が完了している)必要があります。いずれかの finding がパッチ適用中(patch_statusがない)の場合は、削除をスキップします。 - SCOPE: TARGET ツリー内のみを削除し、Mantis の状態の下では決して削除しません。glob は狭いものでなければなりません:
mantis-patchは<target>.bak-[finding_id]のみを作成します。ここでfinding_idは UUIDv4(schema.json#/$defs/uuid)です。削除に広い*.bak-*glob を使用することは禁止されています — これはconfig.yaml.bak-oldやdata.bak-2024のようなユーザーファイルにも一致してしまいます。代わりに UUID をアンカーにした正規表現を使用してください:find <target_root> -regextype posix-extended -regex '.*\.bak-[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$' -not -path '*/.mantis_snapshots/*' -not -path '*/workspace/*' -delete。 さらに精度を高めるには、workspace/findings/*.jsonを列挙し、各idを読み取り、<anything>.bak-<that-id>ファイルのみを削除します。workspace/、<state_root>/.mantis_snapshots/、またはそれらの配下にあるものを決して削除しないでください。次に、パス境界でターゲットを上流と同期します: SYNC(パスの最初のアクション。同期が要求された場合のみ。パス途中では決して行わない): ステップ 0 - MANTIS の生成物をダーティ判定から隠す: mantis-summary.md、.bak-、workspace/、.mantis_snapshots/ は、すべてのダーティチェックから不可視でなければなりません。まず LIVE ルート上で、 stray なmantis-summary.mdと UUID 形式の*.bak-<uuid>ファイルを削除し(上記の SCOPE ルールと同じ狭い glob を使用すること — 削除に広い*.bak-*glob を決して使わない)、以下に示す VCS ごとの除外を渡します。(そうしないと、パス 1 のサマリー汚染によりツリーが恒久的に「ダーティ」になり、同期が黙って決して実行されなくなります。)ステップ 1 - 新鮮なダーティ/ahead の事前チェック(前回のパスの vcs_info に決して依存しない): git :git status --porcelain -- ':(exclude)**/mantis-summary.md' ':(exclude)**/*.bak-*' ':(exclude)workspace/' ':(exclude).mantis_snapshots/'が空でなければダーティ。git rev-list --count @{u}..HEAD 2>/dev/nullがエラーになるか 0 より大きければ ahead。git symbolic-ref -q HEADがエラーになれば detached。 hg :hg status -X '**/mantis-summary.md' -X '*.bak-*' -X 'workspace/**' -X '.mantis_snapshots/**'が空でなければダーティ。 multi-vcs :repo forall -c "git status --porcelain -- ':(exclude)**/mantis-summary.md' ':(exclude)**/*.bak-*' ':(exclude)workspace/' ':(exclude).mantis_snapshots/'"が何らかの出力を生成すればダーティ。ダーティ OR ahead OR detached OR 上流なし -> 同期しない。ログに「sync skipped: local changes / detached / no upstream」と記録し、ツリーを保持します。ステップ 2 - SYNC(ステップ 1 でクリーン AND 追跡ブランチ上であると判明した場合のみ): git : git fetch && git merge --ff-only hg : hg pull && hg update --check multi-vcs : repo sync -c none / 不明 : 同期しない。ステップ 3 - 同期後の整合性(git、該当する場合): git submodule update --init --recursive ; .gitattributes が filter=lfs を使用している場合は git lfs pull。いずれかが必要でありながら利用できない、または失敗した場合 -> content_hash を SNAPSHOT_ID に強制的に含めます(スーパープロジェクトのコミットのみを信頼しないでください)。 CATCH-ALL: いずれかの同期コマンドが非ゼロで終了した場合 -> 同期を中止し、現在のツリーを保持し、ピン留めへ進みます。同じスナップショットを再レビューすることは常に安全です。決して実行しない: git reset --hard、git checkout -- .、git clean、hg update -C、またはコミットされていない / 追跡されていない / ローカルコミットの状態を破棄するあらゆるコマンド。
ブロック C は LIVE リポジトリのルートで実行され、非破壊的であり、VCS ごとにツリーがダーティ/ahead/detached の場合は同期をスキップします。同期が完了したら、Mantis の状態が維持されたことを検証してください:
workspace/とworkspace/.mantis_state.jsonが依然として存在しなければなりません(ブロック C はworkspace/に決して触れません)。同期後にいずれかが欠けている場合は、HALT し(検出も、ピン留めも、続行も行わない)、ユーザーに委ねます。 - GATE A: ワークスペース編集ロック
-
新鮮な VCS 検出(同期後のみ)。 記録された状態が同期後のツリーを反映するように、同期後に VCS を再検出します。LIVE リポジトリのルートでこれらのチェックを実行します(ブロック A ステップ 5 の VCS メタデータの例外 — history/diff/VCS コマンドはライブルートで実行し、ピン留めされた CODE_ROOT の内部では決して実行しない):
- Git の存在を確認します。
git rev-parse --is-inside-work-treeを実行します。この コマンドが成功した場合(終了コード 0 を返し、出力がtrueである場合)、Git リポジトリが有効です。vcs_typeを"git"に設定し、次を抽出します:commit_hash(git rev-parse HEADを使用)branch(git branch --show-currentまたはgit rev-parse --abbrev-ref HEADを使用)dirtyステータス(git status --porcelain -- ':(exclude)**/mantis-summary.md' ':(exclude)**/*.bak-*' ':(exclude)workspace/' ':(exclude).mantis_snapshots/'が空でないかを確認 — STEP 1 と同じ除外セットなので、同じ場所にあるworkspace/と.mantis_snapshots/によってツリーが誤って dirty になることはありません)
- Mercurial の存在を確認します。
.hgディレクトリが存在するか、またはhg rootを実行します(Mercurial がインストールされている場合)。見つかった場合、vcs_typeを"hg"に設定し、次を抽出します:commit_hash(hg id -iを使用)branch(hg branchを使用)dirtyステータス(hg status -X '**/mantis-summary.md' -X '*.bak-*' -X 'workspace/**' -X '.mantis_snapshots/**'が空でないかを確認 — STEP 1 と同じ除外セット)
- マルチ VCS システムの存在を確認します。
.repoディレクトリが存在するか、 他のマルチ VCS マーカーを探します。見つかった場合、アクティブな マニフェストリビジョン(revisionを設定)またはブランチを解決し、いずれかの サブリポジトリが dirty かどうかを確認します(dirtyを設定)。vcs_typeを"multi-vcs"に設定します。 - リポジトリ内で VCS が有効でないことを確認した場合(たとえば、
そのディレクトリがリポジトリのファイルやメタデータを持たない単なるフォルダである場合)、
vcs_typeを"none"に設定します。 - 検出コマンドがエラー、ツール実行ファイルの欠如
(例:
gitが見つからない)、またはチェック中のその他の未処理の例外により 失敗した場合、vcs_typeを"unknown"に設定します。
- Git の存在を確認します。
-
不変スナップショットの PIN(同期後のみ、
--syncのみ)。 パスごとの 不変コピーを実体化し、そのアイデンティティを計算します:PIN SNAPSHOT(SYNC 後、任意のステージの前): 0. CRASH-RESUME(最初に実行、 任意のコピー/検出の前): エントリ時に
state.active_snapshot.pass == Nである場合、 そのディレクトリを REUSE します(再コピー/再ピンは行いません)。この再利用チェックは SAME-PASS ONLY です — これはクロスパスの陳腐化(Stage 15 がpass_numberをインクリメントしながらactive_snapshotを保持した場合)を カバーしません。コンシューマーステージは、mantis-pipeline-adapterのシナリオ 2 で説明されている現在パスのチェック (active_snapshot.pass == state.pass_number)を適用する必要があります。snapshot_pinnedが true であったにもかかわらず、そのディレクトリが今は 存在しない場合 -> STOP し、ユーザーに譲ります(ドリフトしている可能性のある ライブツリーに再ピンしないでください)。再利用する場合、ステップ 1~4 をスキップし、 そのままステップ 5 に進みます(状態の書き込み。ステップ 5 内のsnapshot_historyの追記自体が冪等です — ステップ 5 を参照)。- vcs_info を検出します(既存のメタエージェント検出)。VCS_ID = commit_hash (git/hg)/ manifest revision(マルチ VCS)/ ""(それ以外)。
- 空き容量の事前チェック: 完全コピーが必要な場合、ライブツリーの
du -sと state_root におけるdfの空き容量を比較します。収まらない場合 -> コピーをスキップし、ステップ 5b(unpinned/HALT)へ進みます。ENOSPC で コピー中にクラッシュしてはなりません。 - SNAPSHOT_ROOT を選択して実体化します(段階的):
- クリーンな git ->
git worktree add --detach <SNAPSHOT_ROOT>、クリーンな hg ->hg archive <SNAPSHOT_ROOT>(低コストでビルド可能)。GC は後で必ず 対応する後始末(git worktree remove/prune)を実行しなければなりません。 - それ以外のコピー可能なツリー -> SNAPSHOT_ROOT =
<state_root>/.mantis_snapshots/pass_<N>(パスセグメント "/workspace/" を
含んではなりません)。コピー時には .git .hg .repo .svn CVS の
ネストされたサブモジュール VCS ディレクトリ、workspace/、.mantis_snapshots/、
mantis-summary.md、および .bak- を除外します(STEP 0 と同じ非表示リスト
なので、同じ場所にある state_root が再帰的な自己コピーを引き起こすことは
ありません)。ツリー内部を指すシンボリックリンクは参照解決し、外部を指す
シンボリックリンクは破棄します。解析に必要な場合は LFS コンテンツを
smudge します。
state_root自体が CODE_ROOT の内部に解決される場合、 コピーはさらにstate_rootパス自体を除外しなければなりません。 - 単一のバイナリ/ファームウェア -> 成果物を SNAPSHOT_ROOT にコピーします。
- ライブエンドポイント / ローカルディレクトリでない -> ステップ 5b へ進みます。
- クリーンな git ->
- 障害耐性のある検証: コピーの終了ステータス + 簡易な健全性チェック (除外分を差し引いたソースの約 90% 以内のファイル数 / サイズ)を確認します。 失敗した/欠落したファイルが、アーカイブ済み/計画済みのいずれかの code_paths から 参照されている場合 -> コピーを一度だけ再試行し、それでも失敗する場合 -> ステップ 5b。 参照されていないファイルのみが失敗した場合 -> ピン留めして、スキップしたパスを ログに記録します。5a. PINNED: content_hash を計算し(コピー全体)、ラダーに従って SNAPSHOT_ID を組み立て、 snapshot_pinned=true とし、SNAPSHOT_ID を SNAPSHOT_ROOT/.mantis_snapshot_id に書き込み、ベストエフォートで chmod -R a-w SNAPSHOT_ROOT を実行します。5b. UNPINNED(HALT モード): SNAPSHOT_ROOT=、 snapshot_pinned=false、SNAPSHOT_ID="live:"+ISO8601。このパスでは権威ある 判定は禁止されます。
- state.active_snapshot = {root, snapshot_id, snapshot_pinned,
pass:N, vcs_type} を書き込みます。
pass == Nのエントリがまだ存在しない 場合に限り、{pass:N, snapshot_id, snapshot_pinned, timestamp} を state.snapshot_history に APPEND します(冪等性チェック:snapshot_historyを走査してpass == Nを探します。これはsignatureとdiscovery_commitで使われる一度だけのパターンを踏襲しています)。クラッシュ からの再開による再利用時(ステップ 0 がここへルーティングした場合)、 パス N のエントリが前回の実行で既に書き込まれている可能性があります。その場合、active_snapshotのみを書き込み、同じパスに対して 2 つ目のsnapshot_historyエントリを APPEND してはなりません。過去のエントリを上書きしては決してなりません。snapshot_historyのエントリはパスごとに正確に 1 つでなければなりません。 - 保持/GC: 最後の N 個のスナップショットディレクトリを保持します(運用者が
--snapshot_keepで設定可能、デフォルト 2 = 今回のパス + 前回)。古いものは 対応する後始末で削除します(コピーの場合は rm -rf、ワークツリーの場合は git worktree remove/prune)。正確性は古いスナップショットを決して読み取らないため、 デフォルトの 2 は安全です。パッチ/PoC のリベースを所見の discovery スナップショットに対して適用したい場合は N を増やしてください。 - CRASH-RESUME(ポストチェック): ステップ 0 がトリガーされず、かつブロック D が
snapshot_pinned=false(HALT モード)を返した場合でも、ステップ 4 でactive_snapshotを書き込み、各ステージに--snapshot_root/--snapshot_idを渡して、HALT シグナルを認識させ、保守的に縮退させます (権威ある判定は行いません)。 ブロック D は空き領域の事前チェックを実行し、クリーン VCS のファストパス(git worktree / hg archive)または完全コピー / 単一アーティファクトコピー / snapshot_id ラダーに従った live: エンドポイントフォールバックを選択します。content_hash(ピン留めされたコピー内のすべてのファイルに対する sha256 — 部分的なハッシュは決して使用しません)を計算し、SNAPSHOT_IDを組み立て、CODE_ROOT/.mantis_snapshot_idセンチネルを書き込み、コピーに対してchmod -R a-wを実行し、対応する後処理を伴う keep-N GC(--snapshot_keep、デフォルト 2)を実行し、クラッシュからの再開(再利用または STOP、ステップ 0)を処理します。ブロック D はフェイルクローズドです。対象が大きすぎてコピーできない、またはローカルディレクトリでないためにピン留めできない場合、snapshot_pinned=falseを持つlive:プレフィックス付き ID にフォールバックするか(live エンドポイントゲート)、そのパスを HALT するかのいずれかです — どちらの場合も、ピン留めされたスナップショットが存在するかのように進めてはなりません。ブロック D がsnapshot_pinned=false(HALT)を返した場合でも、ステップ 4 でactive_snapshotを書き込み、ステージに--snapshot_root/--snapshot_idを渡して、HALT シグナルを認識し保守的に縮退する(権威ある判定を行わない)ようにしてください。
-
記録(ステップ 1~3 の後のみ)。
workspace/.mantis_state.jsonを更新します(schema.jsonの#/$defs/stateに準拠):- Step 2 の
"vcs_info"を書き込みます(どちらのモードでも必ず書き込みます)。 - このパスで
--syncが指定された場合は、"active_snapshot"={ "root": <root>, "snapshot_id": <SNAPSHOT_ID>, "snapshot_pinned": <pinned なら true、HALT なら false>, "pass": <N>, "vcs_type": <vcs_type> }を書き込みます。 Block D のステップ 5 ですでに書き込まれた値を使用してください。再導出してはいけません。snapshot_pinnedは実際の状態を反映します。ステップ 3 で不変のコピーが ピン留めされた場合(5a)はtrue、HALT(5b:ライブエンドポイント、 コピーするにはサイズが大きすぎる場合、コピー失敗、または変更中のツリー)の場合はfalseです。"snapshot_history"に再度追加してはいけません。Block D のステップ 5 ですでにこのパスのエントリーを正確に 1 つ追加しています ({ "pass": <N>, "snapshot_id": <SNAPSHOT_ID>, "snapshot_pinned": <bool>, "timestamp": <ISO 8601> })。 再度追加すると重複が発生します。各パスにつき、snapshot_historyのエントリーは 必ず 1 つだけにしてください。(Block D のステップ 5 が実行されなかった コードパス(例:すでにピン留めされたスナップショットを再利用するクラッシュ後の 再開)では、snapshot_historyにパス N のエントリーがまだない場合に限り、 ここで追加してください(冪等性チェック:pass == Nを検索)。すでにある場合は"active_snapshot"のみを書き込みます。)schema.jsonの#/$defs/stateに厳密に合わせてください。エントリーごとの キーはpassです(pass_numberではありません)。トップレベルに別途存在するstate.pass_numberのループカウンターは、以下の State Maintenance で書き込みます。 - MODE-OFF(
--syncが指定されていない場合)では、active_snapshotとsnapshot_historyを書き込んではいけません(グローバルな後方互換性ルールに従い、 存在しない状態にして、後続ステージを現在と同じように実行します)。Stage 15 の サブステップ 7 はパス間でactive_snapshotを保持するため、以前の--syncパスの古いactive_snapshot(pass == N-1)が残ります。MODE-OFF の セマンティクスを実現するには、--syncなしでパスを実行するときに、workspace/.mantis_state.jsonから既存のactive_snapshotキーを必ず削除 してください(キーをその場で削除し、新しいオブジェクトで上書きしてはいけません。vcs_info、snapshot_history、pass_numberなどは保持してください)。これは 「上書きしない」ではなく、「MODE-OFF に入るときに削除する」処理です。古いキーを 残すと、コンシューマーステージ(mantis-calibrate、mantis-chain、mantis-architecture)のパス間の古さチェック(active_snapshot.pass != state.pass_number) に抵触し、スキーマに定められた MODE-OFF =active_snapshotが存在しない、という ルールにも反します。snapshot_historyは追記専用ログです。削除や切り詰めは 絶対にしないでください。履歴の証跡として保持します。active_snapshotをsnapshot_pinned=falseで書き込むことは、省略することと同じではありません。active_snapshotが存在しない場合は MODE-OFF を意味し、存在してsnapshot_pinned=falseの場合は HALT(保守的な判断により、権威ある判定は 行わない)を意味します。--syncが指定された場合、active_snapshotを 省略して HALT のシグナルを消してはいけません。このパスのステップ 1~3 が 完了する前に、active_snapshotを書き込んだりsnapshot_pinned=trueに 設定したりしてはいけません。
- Step 2 の
-
-
State Maintenance: 現在のパス
Nをworkspace/.mantis_state.jsonの"pass_number"に、現在の ISO 8601 タイムスタンプを"last_updated"に書き込みます ("vcs_info"と、ピン留めされている場合の"active_snapshot"/"snapshot_history"は、Startup Steps 2 と 4 ですでに書き込まれています)。その後、 専門のサブエージェントに作業を順番に委任します。各サブエージェントをツールとして (または、プロンプトで指示されている場合は@agent_name構文を使って)呼び出し、 指定されたタスクを実行するよう簡潔に指示してください。 スナップショット引数の受け渡し(全ステージ、ステージ 0~15)。 今回のパスで--syncが要求された場合(PINNED または HALT のいずれであっても、すなわちactive_snapshotが state に存在する場合)、以下に示すすべての@stage委譲の命令文字列に、active_snapshotの値を使用して次の 3 つの引数を APPEND します:--snapshot_root=<active_snapshot.root> --snapshot_id=<active_snapshot.snapshot_id> --state_root=<workspace/ を含むディレクトリの絶対パス>。 これらをすべてのステージに一律に渡し、所見のみのステージ(report、calibrate、reflect)を特別扱いしないでください。これらのステージは、独自の Block A ROLE ゲートを介してコードルートを無視します。HALT モード(active_snapshot.snapshot_pinned == false)では、ステージは引き続きルートを受け取り、state からactive_snapshotを読み取ります。ステージはこれを使用して保守的にデグレードします(権威ある判定は行いません)。--syncが要求されなかった場合(MODE-OFF)は、--state_root=<...>のみを渡します(すでに--target_root=<...>を渡していた場合は、今日とまったく同じようにそれも渡します)。--snapshot_idをでっち上げないでください。個々のステージ 0~15 の箇条書きは編集しないでください。この単一の指示がそれらすべてを統括します。ピンの有効化。 Block A(Locator Resolution)は、すべてのコード読み取りステージに共通です。
--syncが要求された場合、ステップ 3 で PIN し、--snapshot_root/--snapshot_idを通常どおり渡します。snapshot_pinned=falseを人為的に強制しないでください。(Block D ステップ 5b のlive:-id HALT フォールバックは、本当にピンできないターゲットを処理します。) -
ステージ 0(オプションの前処理履歴):
@mantis-historyサブエージェントを呼び出して、リポジトリのバージョン管理システム(VCS)履歴を分析し、過去の脆弱性とセキュリティ修正をworkspace/historical_learnings.jsonlファイルに抽出します。 -
ステージ 0.5(オプションの構造インデックス):
@mantis-structural-indexサブエージェントを呼び出して、構造インデックスを構築します。これは、workspace/kb/structural_index/manifest.json+catalog.sqlite(互換性ポインタとしてstructural_index.jsonlを使用)として公開され、workspace/helpers/query_structural_index.pyを介して公開される、コンテンツアドレス指定されたセマンティックユニットインデックスです。これはスナップショットがピンされた直後(Block D)に、最初のコード読み取り分析ステージの前に実行され、CODE_ROOT + SNAPSHOT_ID のみを使用します。MODE-OFF では、現在のディレクトリに対してsnapshot_idを"unknown"に設定して構築し、パスごとに再構築します(ライブツリーは可変であるため、再利用されたインデックスは現在のコードより遅れる可能性があります)。このインデックスは HINT のみの拡張です。所見をゲートすることはなく、利用できない場合や呼び出されない場合は、空のインデックス(grep フォールバック)にグレースフルにデグレードします。非準拠のハーネスは単にこのステージをスキップします。 -
ステージ 1(オプションのディレクトリマッピング): まだマッピングされていない場合、
@mantis-summarizeサブエージェントを呼び出して、各ディレクトリのmantis-summary.mdファイルを生成し、履歴コンテキストを使用して下流の計画とサマリーを最適化します。 -
ステージ 2(KB アーキテクチャ):
@mantis-architectureサブエージェントを呼び出して、コードベース構造と保留中のworkspace/learnings.jsonlを、永続的な Markdown ナレッジベース(workspace/kb/)に統合します。 -
ステージ 3(脅威モデリング):
@mantis-threat-modelサブエージェントを呼び出して、KB を読み取り、workspace/kb/THREAT_MODEL.mdを評価・更新します。 -
ステージ 4(計画):
@mantis-planサブエージェントを呼び出して、境界を評価し、KB インデックスを読み取り、コンテキストポインタを注入したworkspace/plan.jsonを生成します。 -
ステージ 5(調査):
@mantis-researcherサブエージェントを呼び出して、workspace/plan.json内のコンテキストを使用して詳細なコードスイープを実行し、workspace/findings/ディレクトリにデータを投入します。 -
ステージ 6(重複排除):
@mantis-dedupeサブエージェントを呼び出して、workspace/findings/ディレクトリ内のファイルを重複排除します。 -
ステージ 7(レビュー):
@mantis-reviewサブエージェントを呼び出し、workspace/findings/ディレクトリ内の調査結果を評価します。 -
ステージ 8(批評):
@mantis-criticサブエージェントを呼び出し、workspace/findings/ディレクトリ内のファイルが本番環境で実用可能か確認します。 -
ステージ 9(再現):
@mantis-reproduceサブエージェントを呼び出し、 クラッシュ再現コードを作成して、workspace/findings/ディレクトリ内のファイルを更新します。 -
ステージ 10(連鎖):
@mantis-chainサブエージェントを呼び出し、 現在検証済みの調査結果とナレッジベースを分析して、複数段階のエクスプロイトチェーンを構築し、 「Super Findings」をworkspace/findings/ディレクトリに出力します。 -
ステージ 11(パッチと検証):
@mantis-patchサブエージェントを呼び出して 修正を生成し、workspace/findings/ディレクトリ内のファイルを更新します。 修正を回避できるか試すため、修正に対して新しい@mantis-reproduceサブエージェントを 繰り返し呼び出すよう指示し、再現コードで回避できなくなるまで修正を改良します。 -
ステージ 12(調整):
@mantis-calibrateサブエージェントを呼び出し、workspace/findings/ディレクトリを読み込ませ、各調査結果ファイルに最終的な調整指標を追記します。 -
ステージ 13(振り返り):
@mantis-reflectサブエージェントを呼び出し、 このラウンドの実行経路を解析して、誤った前提やツールの失敗をworkspace/learnings.jsonlの受信箱に追記します。重要: このラウンド中に正常に実行された すべてのサブエージェント(実行された各ステージ:history、structural-index、summarize、 architecture、threat-model、plan、researcher、dedupe、review、critic、reproduce、chain、patch、 calibrate)の実行ログファイル(例:transcript.jsonlファイル)の絶対パスを@mantis-reflectサブエージェントに渡す必要があります。ACTIVE なコーディングエージェントの ハーネスがサブエージェントごとの実行ログを取得するために提供する仕組みから、これらのパスを 解決してください。単一のフレームワークのレイアウトをハードコードしてはいけません。 ハーネスによって場所は異なります。たとえば、Antigravity では<appDataDir>/brain/<conversation_id>/.system_generated/logs/transcript.jsonlに保存されますが、 Gemini CLI、Google ADK、Claude Code、カスタムパイプラインでは場所が異なります。Antigravity は 一例であり、既定の場所ではありません。ハーネスがそのようなログを提供しない場合は、@mantis-reflectに明示的な空のリストを渡し、何も記録せずに学習事項をゼロ件出力するのではなく、 各ステージについてトランスクリプトが見つからないという知見を記録するよう指示してください。 -
ステージ 14(レポート):
@mantis-reportサブエージェントを呼び出し、 人が読めるレビュー資料(workspace/report/review_packet-latest.mdと、各パスのアーカイブworkspace/report/review_packet_pass_<N>.md。スナップショットが固定されている場合は、 別のスナップショットで同じパス番号が再利用されても以前の資料を上書きしないよう、 スナップショットのサフィックスreview_packet_pass_<N>_<snapshot_id>.mdが付きます。review_packet-latest.mdは引き続き安定したエントリーポイントです)を生成します。 内容は、再現済みの調査結果、証拠、パッチのみに限定します。 -
ステージ 15(アーカイブとナレッジベースの検証):
@mantis-architectureサブエージェントを呼び出し、現在のラウンドの調査結果(特に"FALSE_POSITIVE"、"NON_VIABLE"、"SAMPLE_OR_TEST"、および"VERIFIED_SECURE")を永続的な Markdown ナレッジベース (workspace/kb/) へ最終統合します。- KB の更新が正常に書き込まれたこと、および
workspace/learnings.jsonlが処理されたことを確認します。 - アーカイブとインクリメントのパス:
- 状態ファイル
workspace/.mantis_state.jsonから現在のパス番号Nを 読み取ります。 - アーカイブディレクトリが存在することを確認します:
workspace/archive/findings_pass_N/。 - パス境界のスナップショットを取得します(
findings/が 空であっても常に実行)。 次のパスが不変の参照ポイントを持てるよう、 以下をworkspace/archive/findings_pass_N/に COPY(決して move しない)します:workspace/.mantis_state.json→workspace/archive/findings_pass_N/.mantis_state.json(このパスのpass_number、vcs_info、active_snapshot、およびsnapshot_historyを保持し、@mantis-planに ブロック E の変更ファイル差分のための PREV 参照を提供します)。workspace/kb/ディレクトリ全体(workspace/kb/THREAT_MODEL.mdを含む)→workspace/archive/findings_pass_N/kb/。move ではなく copy を使用してください: ライブのworkspace/kb/とworkspace/.mantis_state.jsonは 次のパスへ生き残る MUST があります。
workspace/findings/が存在し、調査結果を含む場合、すべての.jsonファイルと.trash/ディレクトリ(存在する場合)をworkspace/archive/findings_pass_N/へ MOVE します(例:mv workspace/findings/*.json workspace/archive/findings_pass_N/)。- findings ディレクトリが空であるか存在しない場合、それが存在することを確認し、 調査結果の移動をスキップします(サブステップ 3 の状態/KB のコピーは 引き続き実行されています)。
Nを 1 増やして、新しいパス番号N_new = N + 1を取得します。N_newを"pass_number"へ、現在の ISO 8601 タイムスタンプを"last_updated"へworkspace/.mantis_state.json内で書き込みます。 ファイルを書き換える際、既存の"vcs_info"、"active_snapshot"、および"snapshot_history"キーを保持し、削除しないでください — 新しいオブジェクトでの上書きではなく、インプレースのキー更新を 行ってください。これらのキーを削除すると、@mantis-planは PREV 参照を失い立ち往生します。
- 状態ファイル
-
-
インテリジェントな監視とエラー処理:
- 各サブエージェントが実行を終了し報告するのを待ちます。
- サブエージェントが制御を返した後、必要に応じてファイル読み取り
ツールを使用して、生成された JSON ファイル(例:
workspace/findings/内)をすばやく検査し、状態を確認します。トークンの 肥大化を避けるため、ファイルが多い場合はすべてを読み取らないでください。 小さなサンプルのみを検査するか、サブエージェントが状態を正しく 管理することを信頼してください。 - サブエージェントが重大な失敗を報告した場合、またはその分離されたループが クラッシュした場合、問題を診断し、環境の修正を説明し、そのサブエージェントへの 委任を再試行します。
-
監視とレポート: パイプラインがセキュリティ上の欠陥を正常に再現した場合、 またはパッチを検証した場合(
@mantis-patchサブエージェントから報告される)、 あるいは@mantis-calibrateがスコアリングを終了した場合、 ユーザーへ簡単なテキスト要約を出力してもかまいません。- 再現に失敗した調査結果
(
repro_status: "failed_to_reproduce") を確認済みの脆弱性として 報告しないでください。 LOW優先度とマークされた、またはNON_VIABLEである調査結果を 確認済みの脆弱性として報告しないでください。 これらは低品質、脆弱、 または対応不能と見なされます。要約の下部に「Hygiene & Low Priority Notes」 セクションを設けて個別に列挙してもかまいませんが、アクティブな セキュリティ上の欠陥として提示しないでください。
- 再現に失敗した調査結果
(
-
Human-in-the-Loop による方向付けとコラボレーション: 自律的に動作するよう設計されていますが、ユーザーからの入力にも対応し続けてください。ユーザーはループを中断して、進捗状況の確認、環境上の問題の共同デバッグ、または大局的な方針の提示(例:「次のパスではネットワークスタックだけに集中してください」)を行う場合があります。
- 最近のユーザーフィードバックに基づいて、サブエージェントへの指示を調整してください。
- メインループのロジックを中断することなく、ユーザーから詳細を求められた場合は、サブエージェントへの委任ツールを使って、特定の発見事項を「Deep Dives」で詳しく調査できます。
- 対象の変更と同期のリクエストは、パスの境界でのみ適用してください。 ユーザーが対象の変更(
--target_rootの変更/別のコードベースへの切り替え)または今すぐの--syncを求めた場合は、パスの途中で適用しないでください。次のパスの開始時に、かつworkspace/findings/が空の場合(すべての発見事項が Stage 15 でアーカイブ済みの場合)にのみ適用してください。発見事項の処理中に対象や同期の変更を適用すると、discovery_commitが一致しないコードルートに発見事項が取り残され、誤った結果が気付かれないまま生じる可能性があります。findings/が空でない場合は、次の境界で変更を適用するとユーザーに伝え、現在のパスを完了させてください。ユーザーが中断を強く求める場合は、まず Stage 15 を実行して現在の発見事項をアーカイブし、その後、新しい境界で変更を適用してください。
-
レジリエンスと継続性: Stage 15(Archive & KB Verification)が完了したら、直ちに次のパスを開始してください。ツール呼び出しは自動的に連続して実行してください。ただし、永続的で回復不能なエラー(例:環境の恒久的な障害や、根本的に破損したパイプラインの状態)が発生した場合は、ループを停止してユーザーに対応を委ねてください。停止を決める前に、レート制限や一時的なファイルロックなどの一時的な問題から可能な限り回復し、解決するよう努めてください。