geo-sleuth について
geo-sleuthは、根拠を追跡できる写真の位置特定を支援するスキルです。スクリプトの候補ボードで手掛かりや順位、除外、検証を記録し、コマンドと生成ファイルに基づいて結論を確認できます。
主な機能
- 01根拠に結び付いた候補管理
- 02手掛かりの記録と評価
- 03地理候補の順位付け
- 04スクリプトによる除外確認
- 05画像・地形分析のワークフロー
活用シーン
- 01根拠を記録しながら写真の位置を特定
- 02地理的根拠で候補地域を比較
- 03地点を検証できない場合に範囲を報告
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ oldcircle/ geo-sleuth --skill geo-sleuthインストール後、Claude Code で/geo-sleuthを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
data/calling_codes.jsoncountry_names.jsondriving_side.jsonREADME.mdterritories.jsonreferences/aerial.mdcorridors.mddata-sources.mdgeometry.mdobserve.mdsearch.mdsky.mdskyline-fallback.mdverify.mdreferences/clues/global.mdREADME.mdregions/_template/clues.mdREADME.mdregion.jsonregions/ca/clues.mdregion.jsonregions/cn/clues.mdregion.jsonsearch.mdtests.jsonregions/cn/data/admin.jsonarea_codes.jsonplates.jsonregions/il/clues.mdregions/il/data/admin.json詳細
geo-sleuth (v2)
目標:検証に耐える場所を見つけます。すべての結論で、使用した手掛かり、実行したコマンド、生成したファイルを示す必要があります。
コマンド内の
${CLAUDE_SKILL_DIR}は、この SKILL.md が置かれているディレクトリを意味します(references 内のコマンドも同様です)。Claude Code では自動的に置き換えられます。他のエージェントでは、実行前にexport CLAUDE_SKILL_DIR=<absolute path of this directory>を実行してください(コマンドごとにシェル変数が保持されない場合は、すべてのコマンドの先頭に付けてください)。または、この部分をディレクトリのパスに直接置き換えてください。
作業は3つのレイヤーに分かれています。まずこれを覚えてから、手順を読んでください。
| レイヤー | 担当 | ツール |
|---|---|---|
| 判断:候補がどれか、証拠をどう評価するか、候補を除外できるか、次に何をスキャンするか | スクリプト(候補ボード) | board.py |
| 認識:テキストの読み取り、表の検索、衛星画像内の対象の発見、ストリートビューとの照合 | まずスクリプトで計算して順位付けし、上位数件だけを確認します | intake.py ocr.py clues.py sat_scan.py match.py geo.py bearings |
| 判断:画像から手掛かりを読み取り、表に情報がない場合に仮説を提案し、機械が選んだ上位数件から決定すること | あなた | — |
この手法は、写真からの位置特定(网络迷踪)を扱う制作者の動画14本とパズル22問の分析、および複数回のブラインドテスト比較に基づいています。分析メモはリポジトリでは公開されていません。v1から得られた教訓は、文章で書いたルールは実行されず、同じスキルの同じバージョンでも実行結果が大きく異なったことです。そのためv2では、コード化できるルールをすべて board.py に組み込んでいます。
厳守ルール(常に適用。★=board.pyで強制されるため、そのまま従ってください)
- ユーザーがその写真は自分のものではないと言った場合、または画像に個人の住居や未成年者が写っている場合は、続行する前に一度その用途を尋ねてください。プロンプトにすでに出典や目的(評価用のパズル、パズル作成者のヒント、ユーザーが自分で撮影したと述べている)が示されている場合は尋ねず、通常どおり最も細かいレベルまで進めてください。
- 検証を捏造しないこと。「地図上で測定した」「ストリートビューと照合した」「±10 m」は、このセッションで実際に実行したコマンドと実際に生成したファイルに対応していなければなりません。実行していない場合は「未検証」と書いてください。
- 精度には根拠が必要です: 誤差半径 ≤100 m には、2 つの独立した制約の交点、または ≥3 つの不変な特徴における地上レベルの一致が必要です。カメラ位置を報告する前に、セルフチェックを実行してください:
pose.py project --horizon <sea-horizon row>は、現在のカメラ位置に対してピッチがどうあるべきか、および各特徴の「期待される行」を計算します。それを写真と突き合わせてください(対象物への伏角 ≠ カメラのピッチ。terrain.py elevでカメラ位置の標高を調べてください。高低差が画像内の伏角と一致しなければ、カメラ位置が誤っています)。 - 一意のアンカーが得られたら、ループを閉じること: 以降のすべての検索と幾何計算はそのアンカーから始めます。「青緑色の湖水」や「熱帯の公園」のような一般的な特徴に戻って、その種の中で最も有名な場所を選んではいけません。
- まず方位を計算し、次に構造物を特定すること: 衛星画像のどの街区が写真の塔や煙突なのかは、それ自体が一つの解釈です。まず
sun.py compassまたは確認済みのランドマークで画像内のその真方位を計算し、次にgeo.py bearingsを使って、候補のカメラ位置周辺のどの輪郭がその方位に当たるかを調べてください。何も合わない場合は、まず両方のテンプレート(「元画像/鏡像」、「日の出/日の入り」)を試してください。未検証の場合は、ティアを下げるだけで、除外はしないでください。 - ★ 推論する前にカテゴリ全体を列挙すること: 「丘陵都市」「熱帯」「自治体内の IP」から地域を推論する場合、
board.py childrenを使ってすべての下位行政区画を候補として追加し、それから証拠で順位付けしてください。主要な市街地をデフォルトにしたり、人口で選んだりしないでください。 - メタデータとヒントは仮説です: EXIF、IP 位置、位置タグ、またはパズル作成者の言葉が画像と矛盾する場合、画像が優先されます。それらを整合させるための物語をでっち上げないでください。IP は国 A を示しているが、ヒントや規制上のデザイン(ナンバープレート、標識)が別の大陸を指している場合は、
clues.py lookup territories <country A> --continent <continent>で交差させてください。 - 自己整合性: 各重要な判断を、別のクロップまたはキーワードセットで一度やり直してください。2 つの結果が数十キロメートル以上異なる場合は、ティアを下げてください。
- ★ 点を特定できない場合は、範囲 + 不足している情報を示すこと: 候補が少数の離散的なものである場合、中間点を取らないでください。
board.py reportの主回答は常に最上位の候補です。残りは識別テストとともに代替案に入れてください。 - ★ 除外と確認は同じ基準を使います:
board.py excludeは読み取り済み/計算済みの手がかり + 計算済みファイル(geo.py frame、terrain.pyなどの出力)のみを受け付けます。観察された手がかりと推論された手がかりはevidence --againstで重みを下げることしかできず、尤度比は 1/3~3(推論)または 1/5~5(観察)にクランプされます。「近くに X がある」から候補を生成することもフィルタリングであり、X は画像内で確認されたものでなければなりません。キャンパス、住宅街、街路区間などの細かいレベルの候補もボードに載せる必要があります:board.py add --from <poi.py --out / osm.py geom output> --level area/roadで一度にまとめて追加し、手で選別しないでください。候補を外すときは、比較画像とともにevidence --againstを書き、checkは証拠が一件もない候補を一覧表示します(つまり誰もそれらを見ていないということです)。より細かい候補はそれを含む候補の下に置き(点をその街路区間の下に:--parent、またはboard.py move)、そうすればその支持がそのレベルの順位付けに数えられ、checkはレベルを飛ばすと失敗します。第三者データからのラベル(自治体の台帳にある樹種、学校名の完全一致)は重みを下げることしかできず、除外を正当化することは決してできません(2 つのケースで、まさにこの方法で正解が手作業で飛ばされました)。除外範囲は証拠範囲以下でなければなりません: 地区、エリア、道路など範囲を持つ候補については、excludeに--covers lat,lon[:lat,lon]が必要で、証拠がどの区間に及ぶかを示します。スクリプトは半分未満のカバレッジを拒否します(道路のある 1 点を見ただけで道路全体を除外した事例が 2 回失敗しました)。 - ★ 人口と知名度は証拠ではありません。走査順は「シェア ÷ ページ数」(
board.py next)に従います: 小さな地区を先に終わらせ、大きな地区はページ上限を設けて最後に回してください。
フロー
すべての手順を順番に行う必要はありません。ステップ1で逆画像検索が直接ヒットした場合は、ステップ6と7に進んで確認してください。各ステップの出力は候補ボードに追加します。
ステップ1:ステップ0~3を1つのコマンドで実行
uv run ${CLAUDE_SKILL_DIR}/scripts/intake.py photo.jpg --out-dir intake/ [--box x0,y0,x1,y1 ...]
uv run ${CLAUDE_SKILL_DIR}/scripts/board.py init --photo photo.jpg
intake.py の実行には通常1~2分かかります。初回は依存関係のインストールがあるため、さらに時間がかかります。コマンドには十分に長いタイムアウト(10分以上)を設定するか、バックグラウンドで実行してください。コマンドがタイムアウトで中断された場合も、逆画像検索のサブプロセスが rev/ への書き込みを続けている可能性がありますが、intake.md は生成されません。完了したものとして扱わないでください。
intake.md には、メタデータ、OCR テキスト(拡大・タイル分割した処理で読み取られた行には pass=up/tile と記されており、仮説として扱います)、Baidu の類似画像(掲載元サイトの件数と番号付きコンタクトシート)、逆画像検索のラベルと段階別の投票数、住宅団地・開発地と思われる名称、エッジの切り抜き一覧、失敗した項目が含まれています。その後、次の4つの作業を行います。
- 画像を見る:
edges/内のすべての切り抜き(4辺と4隅)を確認し、references/observe.mdのチェックリストに沿って調べます。各手掛かりをboard.py clue "<text>" --kind <kind> --status observed|read|inferred|computed --file <zoomed crop>で記録します。ステータスは正確に付けてください。読み取ったテキストは read、「建物はおそらく8階建て」「道路は上り坂になっている」は inferred です。 - 計算結果が以前の手掛かりを実際に検証する場合は、
clue "<result>" --kind <kind> --status computed --file <output> --resolves K1で関連付けます。複数の手掛かりに関連付ける場合は--resolvesを繰り返してください。無関係な計算結果は、未解決のインフラに関する手掛かりを解決しません。この関連付けは検証を記録するものであり、場所を裏付けるものではありません。 - 参照表:国番号、車両の通行側、海外領土は全世界共通です。ナンバープレート、地域番号などの国別データは地域パックに含まれています。
clues.py lookup <kind> <value> [--country <cc>]を実行します。--countryを指定しない場合はすべてのパックを検索し、複数の国に一致する候補があればすべて返します。行政区画が特定される場合は、board.py apply --kind plate --value <plate prefix> --file <zoomed crop>を直接使ってください(候補と証拠が自動的に追加されます。同じ階層の他の候補は除外されず、重みだけが下がります)。 - 逆画像検索の結果:まず
rev/<name>_baidu_similar.jpgを開き(左上のタイルはクエリ画像です)、同じ物体または同じ場面の類似画像を探します。見つかった場合は、番号を使って JSON 内のsimilar[i].fromを確認し、掲載元ページを調べます。ラベルに住宅団地、開発地、ホテルの名称がある場合は、poi.py "<name>" --city <city> --out pois.jsonを使って座標を取得します。同名の検索結果(複数のキャンパスや支店など)がある場合は、すべてboard.py add --from pois.json --level areaでボードに追加してから確認します。スクリーンショットは必ず開き、投稿が見つかったら、その投稿に含まれる残りの写真も確認してください。検索先は物体の種類に応じて選びます(references/search.md)。 - ヒントとメタデータ:それぞれを推定された手掛かりとして記録し、どの程度信頼できるかを明記します。IP の位置情報で分かるのは投稿時に投稿者がいた場所だけであり、投稿時刻は撮影時刻ではありません。
- 国固有の情報:国がまだ特定されていない間に、
references/clues/global.md(国を区別する手掛かり)を確認します。国固有の手掛かり、参照表、推奨サービス、ヒントは地域パック(regions/<cc>/)にあります。候補となる国が決まったら、regions.py show <cc>を実行します。参照表、サービス、行番号付きの手掛かり項目の概要が1行で表示されるので、必要な項目だけを読みます。国が確定したらboard.py country <cc>を実行し、global.mdの参照を終えます。利用できるパックはregions.py listで確認できます。パックがない場合は、グローバルツールを使ってください。
ステップ 2:候補をすべて列挙し、根拠を評価して、次のステップを確認します
uv run ${CLAUDE_SKILL_DIR}/scripts/board.py children <parent admin area> # municipality → all districts; country → first-level admin divisions (gazetteer.py queries OSM, with bbox)
uv run ${CLAUDE_SKILL_DIR}/scripts/board.py evidence --clue K1 --for <candidate A>:5 --for <candidate B>:2 --against <candidate C>:0.3 --why "…" --file <comparison image>
uv run ${CLAUDE_SKILL_DIR}/scripts/board.py rank
uv run ${CLAUDE_SKILL_DIR}/scripts/board.py next
next が示す内容は、次のどちらかだけです。
- 区別できない:安価なものから高価なものへと、候補すべてに対して一度に識別テストを実施します。照合テーブル → 地形(平地か丘陵の市街地か、
tiles.py fetch --zoom 13またはterrain.py)→ 車両のカラーリング(現地語で " bus" を画像検索し、検索結果の画像から路線標識を読み取り、地区ごとにバス後部のストライプを比較します)→ 道路設備(候補ごとの市街地でストリートビューを確認します)→ 河川/道路網のテンプレート。それらをすべて試しても区別できない場合でも、やめずに、提示される「共有数 ÷ ページ数」の順に調べます。盤面の国が判明すると、nextはこれらの行を地域パックのヒントに置き換えます。 - 絞り込み可能:まず
board.py urban <candidate>を使って範囲を市街地に絞り込みます(またはscan-bboxで手動指定します)。次にboard.py falsify <candidate> --text "…"を使って反証条件を書き、ステップ 3 に進みます。
大まかな環境上の位置特定ルールも引き続き適用されます。河川幅や建物の色より先に地形を確認します。季節現象は月と組み合わせて確認します。珍しい施設の組み合わせは共通部分を取ります。見分けやすい種は除外のみに使います。土地の種類しか手がかりがない場合は、土地被覆図(references/clues/)を使って、まずその種類の土地に絞り込みます。
ステップ 3:候補を絞り込むための分岐を選ぶ
| 手元にある情報 | アプローチ | 参照先 |
|---|---|---|
| 固有の目印(建物、像、塔、景勝地の建物) | 目印の幾何学的解析:視線の交点、整列線、接線、カメラの高さによる建物の絞り込み | geometry.md |
| 遠くの山並み、スカイライン | terrain.py view でカメラ位置の候補をレンダリングして比較します。これで特定できるのは視線方向1つだけなので、次に2つ目の制約を探します。EXIF がない場合は、メインカメラだと決めつけないでください(遠くの山並みはズームで撮影されていることがよくあります)。検索範囲の端で最適な焦点距離が見つかった場合は、範囲を広げて再実行します。手前に近距離の対象があり、その先に遠距離の対象がある場合は、両方のレイヤーをスコアリングします | geometry.md |
| はっきりした影、光が当たった顔、フレーム内の太陽 | sun.py locate / when / facing / compass:緯度帯、時刻、方角、画像内の対象物の真方位 | sky.md |
| 路線番号、鉄道や送電線の仕様、大きな川 | 線状の回廊+線から点への絞り込み:osm.py route / crossings / along | corridors.md |
| 1つのフレーム内に2~3種類のインフラ | osm.py near --report、2種類の線状地物の交差には osm.py intersect(カーブは注記されるだけで、除外はされません) | corridors.md |
| 線状インフラ+特定できない山並み、文字情報なし | インフラに沿った標高から稜線を計算し、地域全体を絞り込みます → スカイラインとインフラまでの距離を数値でスコアリングします → 上位3~5件を重ね合わせます → 等間隔に並ぶ構造物からカメラ位置を特定します:terrain.py scan --lines … --out hits.json --clusters-out clusters.json → terrain.py ridge photo.jpg --x0 … --x1 … --out ridge.json → terrain.py fit --hits hits.json --ridge ridge.json [--line … --line-dist …] --sheet top.jpg --photo photo.jpg(細かく検索するには --at lat,lon --radius 800 --grid 100 --zoom 13 に切り替えます) → imgprep.py piers photo.jpg --rows … --out cols.json --sheet piers.jpg → geo.py spacing --cols … --line … --span … --center lat,lon --ridge ridge.json | corridors.md 4.3、geometry.md 7.4 / 7.7 |
| 明瞭な街路配置、目印なし | osm.py street-scan で交差点を絞り込みます → tiles.py sheet → ストリートビュー | corridors.md |
| 逆画像検索で類似画像が見つからない、文字情報なし、シーンの要素(道路の仕様+隣接する特徴物+地形)のみ | 最初に場所を手動で選ばないでください:シーンを英語のクエリ1つにまとめ、sat_scan.py grid --bbox <coastal strip/corridor> --zoom 17 --cell 360 --query … --neg … で CLIP に順位付けさせます。上位 20~30 件のサムネイルだけを確認します。amenity=parking のような OSM の地物は不完全な場合があるため、grid は points より適しています | search.md |
| フレーム内に位置がわかっている点が4つ以上ある(窓からの眺め、見下ろす構図。遠くの塔、橋、桟橋を水平に撮った写真も対象ですが、高さを特定してください) | pose.py solve でカメラ位置、方角、高さを求めます。複数の候補位置がすべて一致する場合は、pose.py check --cands で1つずつスコアリングします。ロバストな Δchi2 > 9 の場合のみ、board.py exclude --computed に渡せます | geometry.md セクション 10 |
| 「フレーム内に X がない」という理由で除外したい | まず geo.py frame で、X がフレーム内にあり、十分な大きさで、遮られていないかを計算します。除外可能と判定されたものだけを board.py exclude --computed に渡せます | geometry.md セクション 11 |
| 認識可能な種類に属する、名前のわからない建物。検索地域は絞り込み済み | osm.py find で列挙します → 各建物に向いた近隣のビューを gsv.py targets で取得します → match.py で順位付けします。上限を設けてバッチ処理します | search.md セクション 6 |
| 認識可能な施設の種類(穀物乾燥塔、飼料工場、製糖工場、コンクリートバッチングプラント) | 業界の分布を調べます → osm.py buildings で大きな建物を列挙します → sat_scan.py points で順位付けします | search.md |
| チェーンのサブブランドの店舗 | まず開店に関するプレスリリースから住所を探します。店舗検索は候補を集めるためだけに使います → osm.py along + ストリートビューのサンプリング | search.md |
| 飛行機の窓からの写真、見下ろすドローン撮影 | 航空写真の分岐 | aerial.md |
ステップ 4:衛星画像から場所を特定する — 機械が上位にランク付け
uv run ${CLAUDE_SKILL_DIR}/scripts/sat_scan.py grid --bbox <scan_bbox> --zoom 17 --preset track --multi-scale --top 30 --out sat.json --sheet sat_top.jpg --heat heat.jpg
uv run ${CLAUDE_SKILL_DIR}/scripts/poi.py "<district> <school, in the local language>" --city <city> --region <cc> --out schools.json # seeds: --seeds schools.json boosts nearby cells
uv run ${CLAUDE_SKILL_DIR}/scripts/sat_scan.py points --points big.json --preset factory --out r.json --sheet r.jpg # rank candidate points from osm.py buildings / poi.py
- プリセット:track(ランニングトラック)、stadium、factory、silo、dam、bridge、quarry、solar、greenhouse、port、カスタムの
--query。テストでは、都市部の300余りのセルで、OSMにマッピングされたランニングトラックの半数以上が上位30件に入りました。OSMの情報がない中国の旧市街では、学校の運動場が1位になりました。順位付けはしますが、判断はしません。上位20~30セルのサムネイルを確認し、写真の方位と形状に照らし合わせてください。 - 画像の説明を、見る前に俯瞰画像で確認できる特徴へ置き換えます。曲線状の建物、八角形のパビリオン屋根、スポーツコート、線路に垂直な駐車スペースなどです。高層ビルの場合は、建物の基部を確認してください。画像には撮影日があります。
- 候補が多い場合は、候補表を作成します。各地点を1行、写真で直接確認できる各条件を1列にします。
- 上位30件に一致するものがない場合は、まず
board.py checkに記載された「推論によって重みを下げた候補」と反証条件を再確認し、次にプリセットを切り替えるかz18に移動し、それから範囲を広げます。
ステップ 5:確認 — ストリートビューも上位にランク付け
uv run ${CLAUDE_SKILL_DIR}/scripts/baidu_pano.py scan <lat,lon> --radius 300 --out panos.json # the street-view script the region card names (CN: baidu_pano.py); otherwise gsv.py
uv run ${CLAUDE_SKILL_DIR}/scripts/match.py rank --query photo.jpg --panos panos.json --toward <landmark lat,lon> --spread 15 --refine sift --top 10 --out m.json --sheet m.jpg
uv run ${CLAUDE_SKILL_DIR}/scripts/match.py rank --query photo.jpg --items around.index.json --render gsv --spread-headings -30,0,30 --out m.json --sheet m.jpg
match.pyはDINOv2のグローバル類似度で粗く順位付けし、SIFTのインライア数で細かく順位付けします。テストでは、同じ場所を異なる年に撮影した正解のストリートビューがすべて上位4件に入りました。上位10件だけを開き、車両、標識、植生ではなく、変化しにくい特徴(建物の輪郭、窓の位置、バルコニー、柱の位置、縁石、稜線)を比較してください。道路レベルでは2つ以上、建物レベルでは3つ以上の特徴が必要です。インライア数が15以上の画像が1枚もなくても、誤りだとは限りません。季節の違い、古い撮影画像、写真は歩道から撮影されているのにストリートビューは道路の中央から撮影されている場合など、テストでは正解画像のインライア数が5件、または0~8件しかないケースがありました(2件)。まず上位10件を開いて変化しにくい特徴を比較し、一致するものがない場合にのみ--spread-headingsを変更するか、--withinの範囲を広げてください。グローバルスコアは季節の影響が大きく(花の季節に撮影された画像は、どこであっても高く順位付けされます)、可能であれば写真と同じ季節に撮影された過去の画像と比較してください(gsv.py sheet --date)。- パノラマの地点が多い場合は、撮影日と道路でグループ化します。
sheet --road <road name> --spread 60は1つの道路だけを表示します。古い画像のほうが見通しがよい場合があります。 - ストリートビューがなくても確認できます。
terrain.py view --photoで稜線を比較してください。候補施設の名称(OSMの名称、近くの地名+現地語での施設種別の語)を探し、ニュース、百科事典、公式サイトの写真を検索して、ファサードの細部を比較します。 - ストリートビューが写真より何年も古い場合は、古い建物や恒久的な構造物を基準にしてください。
ステップ 6:カメラ位置を特定して出力する
- 振り返る:対応するストリートビュー地点で 180°向きを変え、撮影者側に何があるか確認します。
- カメラ位置を特定するには、互いに独立した 2 つの制約が必要です(
geo.py intersectによる視線の交点、geo.py lineによる位置合わせ線、pose.pyによる複数地点の解決、カメラの高さ、逆方向のストリートビュー)。制約が 1 つしかない場合、建物レベルの確信度は最大でも「中」です。 - 測定可能な影がない場合は、光の当たっている面を使って方角を判断します:
sun.py facing --lit left --shaded camera。車、船、電車から撮影された写真の場合は、進行方向を明記します。
uv run ${CLAUDE_SKILL_DIR}/scripts/board.py check # before concluding: do exclusions have files, does the main answer have verified evidence, which clues went unused
uv run ${CLAUDE_SKILL_DIR}/scripts/board.py report --merge result.json # main answer = top-ranked; alternatives, exclusions and unused clues are written into result.json automatically
uv run ${CLAUDE_SKILL_DIR}/scripts/evidence.py spec.json --out evidence.jpg
依頼されるまで待たずに、回答とあわせてユーザーに evidence.jpg を提示します。衛星画像から道路レベルの判断をするには、z17 をざっと見るのではなく、≥z18 の範囲を切り出す必要があります。
出力:
- 1 文の結論:場所 + カメラ位置 + 方角(該当する場合は、進行方向と撮影時刻も)
- 座標:WGS84、および地域カードにローカル測地系が記載されている場合はその測地系(
geo.py convert)、誤差半径付き - 証拠画像(カメラ位置と方角を示す扇形を記した衛星画像 + 比較画像)
- 推論の連鎖:手がかり → 推論 → 実際に実行したコマンドと作成したファイル → 範囲
- 段階別の確信度(以下の表)。各レベルを個別に評価してください。報告する階層は、「中」以上と評価された最も細かい階層です。建物レベルの確信度が低くても、エリアレベルの確信度は下がりません
- 除外した候補とその理由、代替候補と判別テスト、使用しなかった手がかりまたは解決できなかった手がかり(
board.py reportで生成) - 地点を特定できない場合:確定しているレベルと、さらに必要な情報
ツールのメッセージ、レポートの見出し、生成されたラベルには英語を使用します。証拠として、元のテキスト(OCR、地名、サービスの応答)をそのまま保持し、読者にはその意味を説明するか翻訳します。エージェントの最終レポートはユーザーの言語で作成します。中国語では、「high/medium/low」に「高/中/低」を、「city/area/road/building/floor」に「城市/片区/路/楼/楼层」を使用します。
| レベル | 高 | 中 | 低 |
|---|---|---|---|
| 都市 | テキスト、ナンバープレート、エリアコード、または確認済みの基準地点 | 独立した複数の弱い手がかりが一致 | 弱い手がかりが 1 つだけ、またはヒントのみ |
| エリア | 衛星画像上で、固有の施設またはランドマークが上空から見た特徴 ≥3 件と一致する(一致候補のエリア全体を確認済みで、別の一致候補はない) | 候補エリア内で最も類似した地点だが、候補の確認は未完了 | 推定 |
| 道路 | 地上レベルで固有の特徴 ≥2 件が一致 | レイアウトが一致し、固有の特徴が 1 件ある。地上レベルの画像がまったくない場合:エリアレベルが高で、方位の自己確認に合格 | 衛星画像上のレイアウトのみ |
| 建物 | 独立した制約 2 つ + 地上レベルで特徴 ≥3 件が一致 | 2 つの制約のうち 1 つ | 推定 |
| 階 | 2 種類の参照情報が一致 | 参照情報が 1 つ | 示さない |
予算と停止条件
intake.pyは1回の呼び出しとして数えます。3種類のキーワードセットで画像の逆検索をしても何も見つからない場合は、そこで止めてチェックリストに戻り、ほかの手掛かりを探します。- 候補をまだ絞り込めない間は、地点を1つずつスキャンしないでください(
board.py nextが「絞り込めない」と示した場合は、先に識別テストを行います)。低コストのテストを行っても絞り込めない場合は、指示された順序でスキャンし、まず各候補の市街地の最初の3ページを確認します。 - スキャンと確認を常に優先します。
sat_scan.pyの上位30セルと、match.pyの上位10枚の画像を確認し、上位の候補がすべて間違っている場合に限って範囲を広げます。ページを順に見ていかないでください。 - OSMで候補を列挙する前に、
osm.py coverageを実行します。データがまばらな地区は通知なく除外されるため、その場合はsat_scan.py gridに切り替え、結論でその旨を伝えます。 - パノラマは、エリアごとに最大500地点のバッチでスキャンします。バッチまたは複数のエリアで一致するものが見つからない場合は、候補の生成方法、検索範囲、推論によって優先度を下げた候補を見直します。その後、方法を変更するか、根拠のある範囲まで検索範囲を広げます。一致しないエリアが一定数に達しただけでは、調査を終了する理由になりません。
- サービスが失敗した、または利用できない場合に妨げられるのは、その検索経路だけであり、調査全体ではありません。実行可能なほかの情報源や方法を検討し、失敗したリクエストを変更せずに繰り返さないでください。
- 停止する前に、
board.py checkを実行します。推論によって優先度が下げられたものの除外されていない上位20件の候補を、順位順に再確認します。 - 求められた地点の粒度を証拠で裏付けられた場合、ユーザーから停止を求められた場合、ユーザーが設定した予算に達した場合、または残る実行可能なアクションでは候補を絞り込めそうにない場合に結論を出します。解決できない場合は、
board.py reportを使って、裏付けられた粒度、実際の検索範囲、試した検索経路、阻害要因、不足している証拠を記載します。結論を出すために、座標や精度を捏造しないでください。
実行環境
- Python 3.10 以降、
uv、curl。必ずuv run ${CLAUDE_SKILL_DIR}/scripts/xxx.pyを使ってください。各スクリプトが依存関係を宣言しています。参照先にあるscripts/は、このスキルのディレクトリからの相対パスです。 - 初回セットアップ時、または実行時に問題が発生した後は、
uv run ${CLAUDE_SKILL_DIR}/scripts/doctor.pyを実行します。サービスへの接続性を確認するには--networkを追加してください。時間のかかるスキャンを始める前に、英語のチェック項目と対処法を読んでください。写真のアップロードや ML モデルの読み込みは行われません。 - 画像の逆検索ではローカルの Google Chrome を使用し、自動的に Playwright Chromium(
uvx playwright install chromium)へフォールバックします。どちらも起動しない場合はintake.py --no-revを使い、検索をスキップしたことを報告します。OCR は macOS では Apple Vision を優先し、それ以外の環境では RapidOCR を使用します。Apple Vision のフォールバックとしても RapidOCR を使用します。 match.pyとsat_scan.pyは、初回使用時に ML の依存関係をインストールし、モデルの重みをダウンロードします。時間とディスク容量に余裕を持たせてください。- キャッシュはカレントディレクトリ内の
.geo-cache/に、候補ボードはカレントディレクトリ内のboard.jsonに保存されます。スクリプト一覧とデータソースについてはreferences/data-sources.mdを参照してください。 - macOS には
timeoutコマンドがありません。また、zsh では$varが単語分割されないため、ループ内ではbash -cまたは${=var}を使用してください。州全域を対象とする Overpass クエリには数分かかる場合があるため、バックグラウンドで実行してください。