asrch 0.1.1

Agent-safe bounded code search CLI
# CLI の挙動

[English](cli_behavior.en.md)

この文書は、`asrch` の外部挙動を簡潔に固定する。プロジェクト全体の目標と非目標は `goals_and_condition.md` を正とする。

件数は一致文字列の個数ではなく、`ripgrep` が返す一致行数として数える。同じ行に検索語が複数回現れても 1 件である。

## 検索プロトコル

エージェントは、複数語を OR 正規表現へ結合して本文を読むのではなく、次の順序で探索する。

1. `survey` で複数の候補語を比較する。
2. 有効な単一語を選び、`scout` で分布を確認する。
3. ファイルを特定し、`sample` で近接一致クラスタの範囲を見る。
4. 必要に応じて `show --line` で特定行周辺だけを詳しく見る。

## コマンド

| コマンド | 入力 | 目的 | 既定の出力上限 |
| --- | --- | --- | --- |
| `survey` | 複数の固定検索語と候補パス | 語ごとの一致行数、ファイル数、有望なパスを比較する | 構造的制約 |
| `scout` | 単一クエリ | 一致行数、ファイル数、上位ディレクトリ、上位ファイルを要約する | 構造的制約 |
| `sample` | 単一クエリと明示ファイル | 近接一致をクラスタ化し、範囲と短い文脈をページ表示する | 構造的制約 |
| `show` | 単一クエリと明示ファイル | 少数の一致、または指定行周辺を短い文脈付きで表示する | 構造的制約 |

`count` と `terms` は提供しない。`count` は `scout` と役割が重複し、単純頻度集計の `terms` は広い検索でノイズを次の検索語として推奨しやすいためである。

行数・バイト数に依存する出力 hard cap は掛けない。`survey` は最大 12 語 / 8 パス、`scout` は上位ディレクトリ・上位ファイル、`sample` は明示ファイル内の 1 ページ最大 5 クラスタ、`show` は最大 20 一致行と最大 5 context 行によって構造的に出力量を抑える。すべての出力行は最大 800 バイトに切り詰める。

`scout`、`sample`、`show` のうち、パスの既定値がカレントディレクトリ `.` なのは `scout` だけである。`sample` と `show` は明示ファイルを必須とする。検索モード指定は相互排他である。

## 複数語と OR

`survey` は `--term` を最大 12 回、候補パスを最大 8 個受け取り、各語と各パスの組み合わせを独立に検索する。一致本文は表示しない。

パス数はコマンドラインに渡された引数数で数える。同じパスを複数回指定した場合も別の指定として数え、検索結果もその回数分集計する。既定パスは `.` である。語数とパス数が両方上限を超えた場合は、両方の違反を同時に報告する。

出力は TOON に寄せた形式で、`overall[term,matches,files,dominant_path]` と `by_path` の両方を含める。`overall` は語ごとの合計一致行数、合計ファイル数、最も一致が多いパスを示す。`by_path` はパスごとの語の分布を示すが、一致ゼロの語行は省略する。これにより、エージェントが reasoning で再集計しなくても、次に使う検索語とパスを同時に選べる。

`scout` も TOON に寄せ、メタ情報を `scout:` 以下に、分布を `top_directories[path,matches]` と `top_files[path,matches]` に出す。`survey` の by-path 細目と `scout` の分布行では、検索対象パスからの相対パスを表示し、絶対パスの繰り返しを抑える。`sample` と `show` は本文 snippet の読みやすさを優先し、従来の形式を維持する。

`scout` は一致行数の多い順に上位 5 ディレクトリと上位 5 ファイルを表示する。同数の場合はパスの辞書順で並べる。ディレクトリの件数は、各一致ファイルの一致行数を親ディレクトリ単位で合算した値である。詳細行のパスは検索対象からの相対パスを優先し、相対化できない場合だけ元の表記を使う。

TOON ライクな値は、ASCII 英数字と `_`、`-`、`.`、`/`、`=` だけで構成される場合は引用符なしで出す。それ以外はダブルクォートで囲み、`"` と `\` をエスケープする。

一語が全候補語の一致行数合計の 80% 以上を占める場合、その語が比較を支配していることを警告する。固定文字列モードで 3 文字以下の語を受け取った場合は、意図外の部分一致を避けるため境界付き検索を提案する。

`scout`、`sample`、`show` は、`--regex` 指定時にエスケープされていない `|` を含むクエリを拒否する。任意の正規表現を完全に解析して OR を分解することは目的としない。

## 検索モード

検索語は既定で固定文字列として扱う。

- オプションなし: 固定文字列の部分一致
- `--identifier`: ASCII 識別子境界付き固定文字列
- `--word`: 単語境界付き固定文字列
- `--regex`: 明示的な正規表現。`survey` では使用不可

短い語や一般語を探す場合は、意図外の部分一致を避けるため `--identifier` または `--word` を優先する。
空の検索語は拒否する。

## `sample` の選択方法

`sample` は確率的なサンプリングを行わない。同じコマンドが同じ結果を返す決定性を優先する。

`sample` は明示した 1 ファイルだけを受け付ける。ディレクトリは拒否する。

1. 2 行以内に近接する一致を同じクラスタとして扱う。
2. 各クラスタについて、行範囲、ヒット数、先頭一致、末尾一致を表示する。
3. `--clusters N` で 1 ページあたりのクラスタ数を 1 から 5 の範囲で選ぶ。既定は 3。
4. `--page N` で N ページ目を表示する。クラスタはファイル内の出現順にページングする。
5. 各クラスタの先頭一致と末尾一致の前後 1 行を表示する。先頭と末尾が同じ行の場合、本文は 1 回だけ表示する。

`sample` は `--context` を受け付けない。出力量は `--clusters` と `--page` で制御する。

一致は `ripgrep --sort path` の順で処理するため、同じ入力に対するクラスタ順とページ内容は決定的である。`--page` が最終ページを超えた場合は失敗せず、空ページと有効なページ範囲を表示する。

## `show` の制約

`show` は明示したファイルだけを受け付ける。ディレクトリは拒否する。一致行が 20 件を超える場合、または内部走査上限へ到達した場合は、本文を表示せず検索語を絞るよう要求する。

`show --line N` は、検索結果一覧ではなく指定行周辺だけを表示する。この場合、一致件数が 20 件を超えていても拒否しない。`sample` が出したクラスタ範囲の途中を確認するときに使う。

指定行は検索語に一致している必要がない。`N` は 1 以上かつファイルの最終行以下でなければならない。`--context N` は前後それぞれの行数で、0 から 5、既定値は 2 である。

`show` は snippet 単位で出力する。行数・バイト数による途中停止はせず、表示件数と context 数で構造的に制御する。

## 広すぎる検索

一致行が 1,000 件を超える、または一致ファイルが 100 件を超える場合、検索が広いことを表示する。内部走査上限へ到達した場合は検索を停止し、件数を `at least` として表示する。

内部走査上限は各検索につき 50,000 一致行である。snippet 用に保持する一致は先頭 5,000 件までである。`survey` と `scout` の件数集計は走査済みの全件を使う。`sample` のクラスタとページは保持された先頭 5,000 件だけから作るため、それを超える場合は検索語またはパスを狭めるよう表示する。`show` は `--line` なしでは 20 件を超えた時点で snippet を出さないため、保持上限による欠落は発生しない。

走査上限へ達した `survey` の件数は `>=N`、`scout`、`sample`、`show` の件数は `at least N` と表示する。

エージェントは、この表示を受けたら出力上限を増やすのではなく、検索語またはパスを絞る。

## エラーと終了状態

存在しないサブコマンドとオプションは、それぞれ `unknown command`、`unknown option` と help を標準エラーへ表示する。必須引数不足、数値範囲違反、ディレクトリを要求しないコマンドへのディレクトリ指定など、入力の誤りは非ゼロで終了する。

`show` が広すぎる検索を拒否した場合も非ゼロで終了し、snippet は表示しない。検索結果が 0 件であること自体はエラーではない。

## 既定の除外

次のようなノイズの多い対象は、`rg` の glob と ignore 規則によって既定で除外する。

- `.git`、`target`、`node_modules`、`vendor`
- `dist`、`build`、`coverage`、`generated`
- `scratch`、`tmp`
- `*.log`、`*.jsonl`、`*.xml`、`*.min.js`、`*.map`

既定除外を解除する CLI オプションは提供しない。明示的なノイズ探索を簡単にすることより、通常のエージェント探索を安全にすることを優先する。