mantis-architecture について
mantis-architectureは、リポジトリ分析向けのセキュリティナレッジベース構築スキルです。コード構造と最新・過去の学習内容を統合し、相互リンクされたMarkdownの構成、コンポーネント、脆弱性の記録を維持します。
主な機能
- 01コンポーネントと信頼境界の分析
- 02リンク付きMarkdownナレッジベースの作成
- 03アーキテクチャと脆弱性パターンの記録
- 04依存関係の抽出
- 05学習内容と各パスのナレッジベースを保存
活用シーン
- 01コードベースのセキュリティ文書の作成
- 02ソース変更に合わせたコンポーネントと脆弱性記録の更新
- 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をそのまま残します。
- トランザクション処理:すべての KB Markdown の更新が正常に書き込まれたことをプログラムで検証した後にのみ、
手順
コードベースと保留中の学習内容を分析し、将来のエージェント向けの永続的な Markdown ベースのメモリを構築します。
アーキテクチャの段階を次のように実行します。
- ロケーターの解決(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.
```
-
受信箱を読み取ります(
workspace/learnings.jsonlおよびworkspace/historical_learnings.jsonl):workspace/learnings.jsonlの内容(および存在する場合はworkspace/historical_learnings.jsonl)を解析します。すべての トラジェクトリの知見、発見された脆弱性、実行可能なクラッシュパス、および 検証済みのパッチを抽出します。
-
ソースコードの境界を分析:
CODE_ROOT配下のディレクトリ構造と主要なソースファイルを調査します (ブロック A で解決された固定スナップショット。ブロック A の ステップ 6 に従って絶対パスを使用し、VCS コマンドを実行しないでください)。リポジトリの内容に基づいて、システムのコア コンポーネント、インターフェース、信頼境界を動的に特定します。これはドメインを問わず広く当てはまります。 ソフトウェアシステム(例:パーサー、コントローラー、ネットワーク デーモンの特定)、ハードウェア/RTL 設計(例:IP ブロック、JTAG インターフェース、メモリコントローラーの特定)、Infrastructure-as-Code(例: クラウド権限、VPC 境界、デプロイ記述子の特定)、 またはデータ/ML パイプライン(例:データ ingress ポイント、モデル シリアライゼーション機構、トレーニング境界の特定)のいずれであっても同様です。
-
ナレッジベース (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 で強制) によって提供されています。後から差し戻された修正は、アサーションごとのタグではなく、これらのメカニズムによって捕捉されます。
-
-
ナレッジの検証と減衰 (ドリフト防止):
- コードがパッチまたはリファクタリングされると、ナレッジは陳腐化します。KB の更新を確定する前に、既存の
workspace/kb/entities/内のアサーションを、CODE_ROOT配下のソース (固定されたスナップショット — ライブの VCS クエリではなく、ライブの作業ツリーでもありません) と突き合わせてスポットチェックしてください。BUILD FRESH の結果 (ステップ 0b) では、スポットチェックをまったく行わないでください。以前のアサーションを破棄し、今回のパスでCODE_ROOTからすべてのエンティティを再導出します。STALE / HALT の結果では、ベストエフォートでのみスポットチェックを行い、結果にかかわらず STALE バナーを維持してください。 - エンティティファイルが、ある変数がサニタイズされていないと主張している (古い学習に基づく) のに、ライブコードが現在サニタイズ関数を含んでいる (パッチが適用されたため) 場合は、その古い学習を KB から削除または修正してください。
- ある学習が現在のトラジェクトリインサイトによって繰り返し誤りと証明される場合は、その「誤った学習」が持続して将来のエージェントを盲目にしないよう、積極的に修正してください。
- 所見に由来するアサーションを修正または再確認する際は、その KB ファイルの
KB_SNAPSHOTマーカーを再スタンプしてください。
- コードがパッチまたはリファクタリングされると、ナレッジは陳腐化します。KB の更新を確定する前に、既存の
-
トランザクションによる受信箱のクリアとアーカイブ:
- 無限ループやトークンの肥大化を防ぐため、キューをクリアして学びをアーカイブする必要があります。
- 検証して確定する: 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 の来歴は、すべての呼び出しで記録する必要があります。
完了したら、ユーザーに通知します。