Skip to content

[Feature] マルチリポジトリ横断検索 #78

@Kewton

Description

@Kewton

概要

複数のリポジトリにまたがる横断検索機能を実装する。チームが複数リポジトリを運用している場合に、全リポジトリの知識を一括検索できるようにする。

背景・動機

少人数チームでは複数のリポジトリ(フロントエンド、バックエンド、ドキュメント等)を運用することが多い。「認証」に関する情報を探すとき、全リポジトリを横断して検索できると、知識の発見効率が大幅に向上する。

提案する解決策

実装前提条件(リファクタリング)

本機能の実装にあたり、以下の既存コードのリファクタリングが必要となる。

M1: 検索関数の base_path パラメータ追加

現在、全検索関数が Path::new(".") をハードコードしており、任意のリポジトリパスを受け取れない。全てのPath::new(".")ハードコード箇所に base_path: &Path パラメータを追加し、カレントディレクトリ依存を排除する。

対象箇所:

  • src/cli/search.rs 内の各検索関数(index_dir, symbol_db_path, load_config の呼び出し箇所)
  • src/cli/context.rs 内の index_dir, symbol_db_path 呼び出し
  • src/cli/config.rs 内の load_config 呼び出し
  • src/main.rs 内の load_config 呼び出し

注意: 対象箇所数は固定値で管理せず、Path::new(".")の全ハードコード箇所を網羅的に置換する。新たなハードコード箇所が追加された場合も同様に対応すること。

注意(Stage 7 M3): try_hybrid_search 内の Path::new(".")SearchContext 導入時に修正漏れリスクが高い。明示的にリファクタリング対象箇所として管理し、SearchContext 移行時に確実に置換すること。

既存の単一リポジトリ利用時は base_path にカレントディレクトリ(.)をデフォルト値として渡すことで後方互換性を維持する。

M2: SearchResult にリポジトリ識別子を付与

現在の SearchResult.path はリポジトリ相対パスのため、複数リポジトリの結果をマージする際にパス衝突が発生する。以下の変更を行う。

  • SearchResult 構造体に repository: Option<String> フィールドを追加(単一リポジトリ利用時は None
  • ワークスペース検索時は各結果に repository としてエイリアスを設定
  • Human出力では [alias] path 形式でプレフィックス表示
  • JSON出力では "repository": "alias" フィールドを追加

注意(Stage 7 M4): SearchResult 構築箇所として enrich_semantic_to_search_results および doc_to_search_result もプロダクションコード側の修正対象に含める。テスト側の make_result だけでなく、これらの関数内での SearchResult 初期化箇所にも repository フィールドを追加すること。

ワークスペース設定

M3: TOMLスキーマ定義

# ~/commandindex-workspace.toml(ユーザーホーム or 任意の場所)
[workspace]
name = "my-team"

[[workspace.repositories]]
path = "~/projects/frontend"    # 絶対パスまたはワークスペースファイルからの相対パス
alias = "frontend"              # 省略時はディレクトリ名を使用

[[workspace.repositories]]
path = "~/projects/backend"
alias = "backend"

[[workspace.repositories]]
path = "~/projects/docs"
alias = "docs"

パス解決ルール:

  • 絶対パス(/home/user/projects/frontend~/projects/frontend): そのまま使用。~ はホームディレクトリに展開する。
  • 相対パス(../frontend): ワークスペース設定ファイルの親ディレクトリを基準に解決する。
  • パス正規化: パス解決後に canonicalize() で正規化し、シンボリックリンクや .. を含むパスを実体パスに変換する。これにより、異なる表記で同一ディレクトリを指すパスの重複登録を検出できる。
  • チルダ展開(Stage 7 S6): ~ の展開には dirs::home_dir() を使用する。HOME 環境変数が未設定の環境(一部のCI環境やコンテナ等)では dirs::home_dir()None を返すため、その場合はエラーメッセージ(例: Cannot expand '~': home directory not found)を表示して該当リポジトリをスキップする。
  • パス重複チェック: canonicalize() 後のパスが重複している場合、設定ファイルロード時にエラーとして報告する(エイリアス重複チェックと同様)。

エイリアスのデフォルト値:

  • alias を省略した場合、path の末尾ディレクトリ名を自動的にエイリアスとして使用する。
  • 例: path = "~/projects/frontend"alias = "frontend"

エラーハンドリング:

  • 指定パスが存在しない場合: エラーメッセージを表示し、該当リポジトリをスキップして他のリポジトリの検索は続行する。
  • 指定パスに .commandindex/ インデックスが存在しない場合: 警告を表示し、該当リポジトリをスキップする。
  • エイリアスが重複する場合: 設定ファイルロード時にエラーとして報告する。
  • 正規化後のパスが重複する場合: 設定ファイルロード時にエラーとして報告する。
  • ワークスペースファイル自体が不正なTOMLの場合: エラーメッセージを表示して終了する。

セキュリティ対策

M2-security: シンボリックリンク経由のディレクトリトラバーサル防止(Stage 7 M2)

canonicalize() によるシンボリックリンク解決時に、意図しない機密ディレクトリ(例: /etc, /root 等)への参照が可能になるリスクがある。以下の対策を実施する。

  • canonicalize() 後のパスに対して、.commandindex/ ディレクトリの存在チェックを行い、CommandIndexプロジェクトとして有効なリポジトリのみを検索対象とする
  • .commandindex/ ディレクトリが存在しないパスは「未インデックス」として警告・スキップする(既存のエラーハンドリングと統合)
  • これにより、シンボリックリンクが機密ディレクトリを指していても、.commandindex/ が存在しない限りインデックス読み込みは発生しない

S6-security: チルダ展開時のHOME未設定環境への対応(Stage 7 S6)

~ を含むパスの展開において、HOME 環境変数が未設定の環境では予期しない動作やパニックが発生する可能性がある。

  • チルダ展開には dirs::home_dir() を使用し、None が返された場合はパニックせずエラーメッセージを返す
  • エラーメッセージ例: Cannot expand '~': home directory not found
  • 該当リポジトリはスキップし、他のリポジトリの処理は続行する

S1: 設定の責務分離

ワークスペース設定ファイル(commandindex-workspace.toml)は 「どのリポジトリを横断検索対象とするか」のみを管理 する。各リポジトリ固有の設定(除外パターン、インデックス設定等)は、各リポジトリ内の commandindex.toml#76 で導入)に委譲する。ワークスペース設定ファイルにリポジトリ固有の設定項目を持たせない。

CLIインターフェース

# ワークスペース内の全リポジトリを横断検索
commandindex search "認証" --workspace ~/commandindex-workspace.toml

# 特定リポジトリに絞り込み(検索前フィルタ:対象リポのみ検索実行)
commandindex search "認証" --workspace ~/commandindex-workspace.toml --repo backend

# ワークスペースのインデックス状況を確認
commandindex status --workspace ~/commandindex-workspace.toml

# ワークスペース内の全リポジトリをインデックス更新
commandindex update --workspace ~/commandindex-workspace.toml

Phase 1 非対応サブコマンド

以下のサブコマンドはPhase 1では --workspace オプションに非対応とする。--workspace を付けて実行した場合は明示的なエラーメッセージを返す。

サブコマンド エラーメッセージ 理由
embed embed does not support --workspace yet Embeddingストアのリポジトリ横断スコア正規化が未対応
context context does not support --workspace yet コンテキスト生成のマルチリポ対応は設計検討が必要
config show config show does not support --workspace yet ワークスペース設定と個別リポジトリ設定の統合表示は未対応(Stage 7 S4)
config path config path does not support --workspace yet ワークスペース設定と個別リポジトリ設定パスの出力は未対応(Stage 7 S4)
clean clean does not support --workspace yet マルチリポジトリ一括クリーンの安全性確認が未対応(Stage 7 S4)

S5: --repo フィルタの動作仕様

--repo オプションは 検索前フィルタ として実装する。指定されたエイリアスに一致するリポジトリのみを検索対象とし、他のリポジトリのインデックスは開かない(検索後フィルタではない)。これにより、不要なリポジトリのインデックス読み込みを回避し、パフォーマンスを最適化する。

検索結果の出力

  • 各結果にリポジトリ名(alias)をプレフィックスとして表示(例: [backend] src/auth.rs
  • JSON出力には repository フィールドを追加
  • スコアはリポジトリ間で正規化(Phase 1ではRRFスタイルのランク順位ベースマージ。下記「スコアマージ方式」を参照)

スコアマージ方式

Phase 1では、リポジトリごとに独立してBM25検索を実行し、結果をRRF(Reciprocal Rank Fusion)スタイルでマージする。

方式:

  1. 各リポジトリで独立にBM25検索を実行し、リポジトリ内でのランク順位を取得する
  2. 各結果に対してRRFスコアを算出: score = 1 / (k + rank)(kは定数、既存のRRF実装に合わせる)
  3. 全リポジトリの結果をRRFスコアで降順ソートしてインターリーブする
  4. リポ間マージ用のRRF関数(Stage 7 M1): 既存の rrf_merge はキーが (path, heading) のため、異なるリポジトリで同一パスのドキュメントが存在する場合にキー衝突が発生する。リポジトリ間マージ専用の rrf_merge_cross_repo 関数を新設し、キーを (repository, path, heading) とすることで衝突を防止する。単一リポジトリ内のマージには既存の rrf_merge をそのまま使用する。

理由:

  • BM25スコアはインデックスごとのIDF値に依存するため、異なるリポジトリ間でスコアを直接比較することは統計的に不正確
  • ランク順位ベースのマージにより、リポジトリ間の公平な結果統合を実現する

S3: status --workspace 出力仕様

status --workspace は以下の情報をリポジトリごとに出力する。--format オプションは既存の StatusFormat 型を再利用する。

Human出力(デフォルト):

Workspace: my-team (3 repositories)

  frontend  ~/projects/frontend     1,234 files  2026-03-20 15:30
  backend   ~/projects/backend        567 files  2026-03-21 10:00
  docs      ~/projects/docs           89 files   2026-03-19 08:45

JSON出力(--format json):

{
  "workspace": "my-team",
  "repositories": [
    {
      "alias": "frontend",
      "path": "/home/user/projects/frontend",
      "indexed_files": 1234,
      "last_updated": "2026-03-20T15:30:00Z",
      "status": "ok"
    },
    {
      "alias": "backend",
      "path": "/home/user/projects/backend",
      "indexed_files": 567,
      "last_updated": "2026-03-21T10:00:00Z",
      "status": "ok"
    },
    {
      "alias": "docs",
      "path": "/home/user/projects/docs",
      "indexed_files": 0,
      "last_updated": null,
      "status": "not_indexed"
    }
  ]
}

status フィールドの値: ok(正常)、not_indexed(インデックス未作成)、not_found(パスが存在しない)

実装方針

  • 各リポジトリのインデックスは独立(既存の .commandindex/ を利用)
  • ワークスペース検索は各リポジトリの検索結果をマージ
  • 並列検索(rayon等)でパフォーマンスを確保

リポジトリ数上限とリソース制御(Stage 7 S1)

10以上のリポジトリをワークスペースに登録した場合、tantivy の IndexReader が使用する mmap ファイルハンドルがOSのプロセスごとの上限に達するリスクがある。以下の対策を実施する。

  • ワークスペースに登録可能なリポジトリ数の上限を 50 とする。超過した場合は設定ファイルロード時にエラーとして報告する
  • Phase 1 では逐次検索(1リポジトリずつ open → search → close)で実装し、同時に開くインデックスを1つに制限する
  • 将来的に並列検索を導入する場合は、セマフォ(tokio::sync::Semaphore 等)で同時オープン数を制御する

SearchContext 構造体のフィールド定義

SearchContext 構造体には以下のフィールドを含める。

必須フィールド:

  • base_path: PathBuf — リポジトリのルートパス

候補フィールド(リファクタリング時に検討):

  • config: Configcommandindex.toml から読み込んだ設定
  • index_dir: PathBuf — tantivy インデックスディレクトリパス
  • symbol_db_path: PathBuf — tree-sitter シンボルDBパス

含めないもの:

  • OutputFormat / StatusFormat — 出力形式は検索コンテキストではなくCLI層の責務
  • limit — 表示件数制限もCLI層の責務
  • workspace 関連 — ワークスペースは SearchContext の外側で管理し、リポジトリごとに SearchContext を生成する

S2: 横断検索のスコープ

Phase 1 では BM25(tantivy全文検索)のみ を横断検索の対象とする。ハイブリッド検索(Embedding + BM25)の横断対応は将来のPhaseで対応する。理由: Embeddingストアはリポジトリごとに独立しており、横断時のスコア正規化が複雑になるため。

S4: rayon依存に関する注意事項

並列検索のために rayon クレートを追加する際、既存の tantivy が内部で rayon を使用しているため、バージョン競合が発生しないことを確認する。cargo tree -d でバージョン重複をチェックし、必要に応じて tantivy が使用する rayon バージョンに合わせる。

update --workspace の動作仕様

エラーハンドリング:

update --workspace 実行時、各リポジトリのインデックス更新でエラーが発生した場合のハンドリング方針:

  • エラーが発生したリポジトリについては、エラーメッセージを表示してスキップする
  • 他のリポジトリのインデックス更新は続行する(status --workspace と同様のスキップ・続行方式)
  • 全リポジトリの処理完了後、エラーが発生したリポジトリの一覧をサマリとして出力する
  • 1つ以上のリポジトリでエラーが発生した場合、コマンド全体の終了コードは非ゼロとする

進捗表示(Stage 7 S5):

update --workspace の逐次実行時に、ユーザーが進捗を把握できるよう以下の形式で進捗メッセージを出力する:

[1/3] Updating frontend...
[2/3] Updating backend...
[3/3] Updating docs...

影響範囲分析

Stage 3 影響範囲レビュー指摘事項

Must Fix

ID 指摘内容 影響ファイル 対応方針
M1 SearchResultrepositoryフィールド追加時、Option<String>型でデフォルトNoneにして後方互換維持 src/search/hybrid.rs, src/output/ 配下 repository: Option<String>をフィールドに追加。既存コードではNoneをセットし、ワークスペース検索時のみSome(alias)を設定。シリアライズ時は#[serde(skip_serializing_if = "Option::is_none")]で後方互換を維持
M2 全てのPath::new(".")ハードコード箇所を除去、SearchContext構造体導入で引数爆発を防ぐ src/cli/search.rs, src/cli/context.rs, src/cli/config.rs, src/main.rs SearchContext構造体を新設しbase_path(必須), config, index_dir, symbol_db_path(候補)をまとめる。各関数は&SearchContextを受け取る形にリファクタリング。デフォルトコンストラクタでbase_path = Path::new(".")を設定し後方互換維持。OutputFormatlimit等のCLI層の責務は含めない
M3 既存テスト(output_format.rs, hybrid.rsmake_result)がコンパイルエラーになるため機械的修正が必要 tests/output_format.rs, tests/ 配下のテストファイル SearchResultへのフィールド追加に伴い、テスト内のmake_resultヘルパーにrepository: Noneを追加。構造体初期化箇所を網羅的に修正
M4 --workspace/--repoオプションの既存conflicts_with_allとの整合性確認 src/main.rs(clap定義部分) 既存のconflicts_with_all設定を確認し、--workspaceが他オプション(--format等)と競合しないことを検証。--repo--workspace必須の依存関係をrequiresで定義
M5 WorkspaceConfig構造体とload_workspace_config関数の新規実装 src/cli/workspace.rs(新規), src/cli/mod.rs WorkspaceConfig, RepositoryEntry構造体をserde対応で定義。load_workspace_configでTOMLパース・パス解決・canonicalize()によるパス正規化・エイリアス重複チェック・パス重複チェック・存在確認を実装

Should Fix

ID 指摘内容 影響ファイル 対応方針
S1 JSON出力のrepositoryフィールド追加でe2eテスト影響確認 tests/ 配下のe2eテスト repositoryフィールドがNoneの場合はJSON出力に含まれないことを確認するテストを追加。ワークスペース検索時の出力検証テストも新規作成
S2 マルチリポ時のIndexReader openのI/Oコスト・メモリ懸念 src/cli/search.rs, src/search/hybrid.rs Phase 1では逐次open/closeで実装。リポジトリ数が多い場合の性能劣化はログ警告で通知。将来的にはIndexReaderプール化を検討
S3 rayon依存追加時のtantivyバージョン確認 Cargo.toml cargo tree -dでバージョン重複を確認し、tantivy内部のrayonバージョンに合わせる。CI上でも重複チェックを実施
S4 SearchContext構造体導入推奨 src/cli/search.rs, src/cli/context.rs M2と統合して対応。SearchContextbase_path(必須), config, index_dir, symbol_db_pathを集約し、関数シグネチャを簡素化。OutputFormatlimit等のCLI層の責務は含めない
S5 status/updateのワークスペース対応ラッパー関数 src/cli/status.rs, src/cli/update.rs(新規または既存) 各リポジトリに対して既存のstatus/updateを呼び出すラッパー関数を実装。エラーは個別リポジトリ単位でハンドリングし、全体の処理は続行。status --workspace--formatは既存のStatusFormat型を再利用
S6 新CLIオプションのテスト追加 tests/cli_args.rs --workspace, --repoオプションのパーステスト、--repo単独指定時のエラーテスト、--workspaceと他オプション組み合わせテストを追加
S7 Phase 1ではembed/context--workspace非対応を明示 src/main.rs(clap定義部分), ドキュメント embed/contextサブコマンドには--workspaceオプションを追加しない。--workspaceを付けた場合は明示的なエラーメッセージ(例: embed does not support --workspace yetcontext does not support --workspace yet)を返す

Stage 5 通常レビュー指摘事項(反映済み)

Must Fix

ID 指摘内容 対応箇所
M1 Path::new(".")のハードコード箇所数を固定値で管理しない M1セクション: 「13箇所」→「全てのハードコード箇所」に修正。注意書き追加
M2 ワークスペース検索時のスコアマージ方式を定義 「スコアマージ方式」セクションを新設。RRFスタイルのランク順位ベースマージを明記
M3 影響ファイル一覧にsrc/cli/context.rsを追加。Phase 1ではcontext --workspaceを非対応とする 影響ファイル一覧に追加済み。Phase 1非対応サブコマンド一覧にcontextを追加

Should Fix

ID 指摘内容 対応箇所
S1 パス解決後にcanonicalize()で正規化、パス重複チェック追加 M3 TOMLスキーマ定義のパス解決ルール・エラーハンドリングに追記。M5対応方針にも反映
S2 SearchContextに含めるフィールドを明確にリストアップ SearchContext構造体のフィールド定義」セクションを新設。必須/候補/含めないものを分類
S3 Phase 1ではリポごとにBM25スコアをランク順位ベースでマージ(RRFスタイル) 「スコアマージ方式」セクションに詳細手順を記載。スコア直接比較を行わない理由も明記
S4 update --workspaceのエラーハンドリングを明記 update --workspaceのエラーハンドリング」セクションを新設。statusと同様のスキップ・続行方式
S5 status --workspace--formatStatusFormat型を再利用 S3 status --workspace出力仕様に明記。S5対応方針にも反映

Stage 7 影響範囲レビュー指摘事項

Must Fix

ID 指摘内容 影響ファイル 対応方針
M1 rrf_mergeのキーが(path, heading)のためリポ間マージ時にパス衝突を引き起こす src/search/hybrid.rs リポ間マージ専用のrrf_merge_cross_repo関数を新設。キーを(repository, path, heading)とする。単一リポ内マージには既存rrf_mergeを使用
M2 canonicalize()でシンボリックリンク解決時に機密ディレクトリへの参照が可能 src/cli/workspace.rs(新規) canonicalize()後のパスに対して.commandindex/ディレクトリの存在チェックを実施。存在しないパスは未インデックスとして警告・スキップ
M3 try_hybrid_search内のPath::new(".")SearchContext導入時に修正漏れリスク src/cli/search.rs, src/search/hybrid.rs 明示的にリファクタリング対象箇所として管理。SearchContext移行時に確実に置換
M4 enrich_semantic_to_search_resultsdoc_to_search_result内のSearchResult構築箇所がテスト修正対象に含まれていない src/search/hybrid.rs, src/cli/search.rs プロダクションコード側のSearchResult構築箇所(enrich_semantic_to_search_results, doc_to_search_result)も修正対象に明記

Should Fix

ID 指摘内容 影響ファイル 対応方針
S1 10+リポでmmapファイルハンドル上限リスク src/cli/workspace.rs(新規), src/cli/search.rs リポ数上限を50に設定。Phase 1では逐次検索で同時オープンを1つに制限。将来的にセマフォ制御
S2 既存e2eテストに--workspace未指定時のリグレッション検証追加 tests/ 配下のe2eテスト --workspace未指定時の既存動作が変化しないことを確認するリグレッションテストを追加
S3 WorkspaceConfig用エラー型をConfigErrorと分離して新設 src/cli/workspace.rs(新規) WorkspaceConfigError列挙型を新設し、ワークスペース設定固有のエラー(パス重複、エイリアス重複、リポ数上限超過等)を構造化
S4 config show/config pathをPhase 1非対応サブコマンドリストに追加 src/main.rs(clap定義部分), ドキュメント config show, config path, cleanをPhase 1非対応サブコマンドテーブルに追加
S5 update --workspaceの逐次実行で進捗メッセージ出力 src/cli/update.rs [1/3] Updating frontend...形式の進捗メッセージを出力
S6 チルダ展開時のHOME未設定環境への対応 src/cli/workspace.rs(新規) dirs::home_dir()を使用。Noneの場合はエラーメッセージを返して該当リポジトリをスキップ

影響を受けるファイル一覧

ファイル 変更種別 影響する指摘
src/search/hybrid.rs 変更(SearchResult構造体修正、rrf_merge_cross_repo新設) M1, M3, Stage7-M1, Stage7-M4
src/cli/search.rs 変更(base_pathパラメータ追加、SearchContext導入、doc_to_search_result修正) M2, S2, S4, Stage7-M3, Stage7-M4
src/cli/context.rs 変更(base_pathパラメータ追加、Phase 1では--workspace非対応) M2
src/cli/config.rs 変更(base_pathパラメータ追加) M2
src/main.rs 変更(clap定義、load_config呼び出し修正、Phase 1非対応サブコマンド追加) M2, M4, S7, Stage7-S4
src/output/ 配下 変更(repositoryフィールド出力対応) M1
src/cli/workspace.rs 新規WorkspaceConfig, WorkspaceConfigError, load_workspace_config、セキュリティチェック) M5, Stage7-M2, Stage7-S1, Stage7-S3, Stage7-S6
src/cli/mod.rs 変更(workspaceモジュール追加) M5
src/cli/status.rs 変更(ワークスペース対応ラッパー、StatusFormat再利用) S5
src/cli/update.rs 変更(ワークスペース対応ラッパー、エラーハンドリング、進捗表示) S5, Stage7-S5
tests/output_format.rs 変更(make_result修正) M3, S1
tests/cli_args.rs 変更(新CLIオプションテスト追加) S6
tests/ 配下のe2eテスト 変更(repositoryフィールド検証追加、リグレッションテスト追加) M3, S1, Stage7-S2
Cargo.toml 変更(rayon依存追加、dirs依存追加) S3, Stage7-S6

受け入れ基準

基本機能

  • ワークスペース設定ファイル(TOML)で複数リポジトリを登録できる
  • --workspace で全リポジトリを横断検索できる
  • --repo で特定リポジトリに絞り込める(検索前フィルタとして動作)
  • 検索結果にリポジトリ名が表示される
  • status --workspace でワークスペース全体の状態を確認できる
  • update --workspace でワークスペース全体を更新できる

リファクタリング(M1)

  • 検索関数が base_path パラメータを受け取り、任意のリポジトリパスで動作する
  • 全てのPath::new(".")ハードコード箇所がSearchContext経由に置換されている
  • try_hybrid_search内のPath::new(".")も確実にSearchContext経由に置換されている(Stage 7 M3)
  • 既存の単一リポジトリ利用時の後方互換性が維持されている

検索結果の識別(M2)

  • SearchResult にリポジトリ識別子(repository フィールド)が含まれる
  • 複数リポジトリの結果マージ時にパス衝突が発生しない
  • Human/JSON両出力形式でリポジトリ名が適切に表示される
  • enrich_semantic_to_search_resultsおよびdoc_to_search_result内のSearchResult構築箇所にもrepositoryフィールドが追加されている(Stage 7 M4)

スコアマージ(Stage 5 M2追加)

  • ワークスペース検索時にリポジトリごとに独立してBM25検索を実行する
  • RRFスタイルのランク順位ベースでスコアマージが行われる
  • BM25スコアの直接比較は行わない
  • リポ間マージ専用のrrf_merge_cross_repo関数がキー(repository, path, heading)で実装されている(Stage 7 M1)

設定ファイルの堅牢性(M3)

  • 絶対パス・相対パス・~ 展開が正しく動作する
  • パス解決後にcanonicalize()で正規化される
  • 正規化後のパス重複が検出・エラー報告される
  • エイリアス省略時にディレクトリ名がデフォルト値として使用される
  • 存在しないパス・未インデックスリポジトリ・エイリアス重複時に適切なエラー/警告が出る
  • ワークスペースに登録可能なリポジトリ数の上限(50)が設定されている(Stage 7 S1)

セキュリティ(Stage 7 新設)

  • canonicalize()後のパスに対して.commandindex/ディレクトリの存在チェックが実施されている(Stage 7 M2)
  • シンボリックリンクが機密ディレクトリを指していても、.commandindex/が存在しない限りインデックス読み込みは発生しない(Stage 7 M2)
  • チルダ展開にdirs::home_dir()を使用し、Noneの場合はパニックせずエラーメッセージを返す(Stage 7 S6)

設計原則(S1)

  • ワークスペース設定にリポジトリ固有の設定項目が含まれていない

検索スコープ(S2)

  • Phase 1 ではBM25検索のみが横断検索に対応している

ステータス出力(S3)

  • status --workspace がリポ名・パス・ファイル数・最終更新日・ステータスを出力する
  • --format json で構造化JSON出力が可能
  • --format オプションは既存の StatusFormat 型を再利用する

依存管理(S4)

  • rayon 追加時に tantivy とのバージョン競合がないことを確認済み

Phase 1 非対応(Stage 5 M3追加, Stage 7 S4追加)

  • embed --workspace が明示的エラーを返す
  • context --workspace が明示的エラーを返す
  • config show --workspace が明示的エラーを返す(Stage 7 S4)
  • config path --workspace が明示的エラーを返す(Stage 7 S4)
  • clean --workspace が明示的エラーを返す(Stage 7 S4)

SearchContext 構造体(Stage 5 S2追加)

  • base_pathが必須フィールドとして含まれている
  • OutputFormatlimit等のCLI層の責務が含まれていない

update --workspace エラーハンドリング(Stage 5 S4追加)

  • エラー発生リポジトリをスキップし、他のリポジトリの更新を続行する
  • 処理完了後にエラーサマリを出力する
  • 進捗メッセージ([1/3] Updating frontend...形式)が出力される(Stage 7 S5)

影響範囲対応(Stage 3 レビュー反映)

  • SearchResult.repositoryOption<String>型で後方互換を維持している(M1)
  • 全てのPath::new(".")ハードコード箇所がSearchContext経由に置換されている(M2)
  • 既存テスト(output_format.rs, hybrid.rs)がrepositoryフィールド追加後もコンパイル・パスする(M3)
  • --workspace/--repoオプションが既存のconflicts_with_allと競合しない(M4)
  • WorkspaceConfig構造体とload_workspace_config関数が実装されている(M5)
  • JSON出力の後方互換性がe2eテストで検証されている(S1)
  • マルチリポ時のIndexReader I/Oコストが許容範囲内である(S2)
  • rayon依存がtantivyとバージョン競合しない(S3)
  • SearchContext構造体で引数爆発が防止されている(S4)
  • status/updateのワークスペース対応ラッパーが実装されている(S5)
  • --workspace, --repoのCLIパーステストが追加されている(S6)
  • embed --workspaceが明示的エラーを返す(S7)
  • context --workspaceが明示的エラーを返す(S7)

影響範囲対応(Stage 7 レビュー反映)

  • rrf_merge_cross_repo関数がキー(repository, path, heading)で新設されている(M1)
  • canonicalize()後のセキュリティチェック(.commandindex/存在確認)が実装されている(M2)
  • try_hybrid_search内のPath::new(".")が明示的にリファクタリング対象として管理されている(M3)
  • enrich_semantic_to_search_resultsdoc_to_search_resultSearchResult構築箇所が修正対象に含まれている(M4)
  • 10+リポ時のmmapファイルハンドル上限対策(リポ数上限50、逐次検索)が実装されている(S1)
  • --workspace未指定時のリグレッションテストが追加されている(S2)
  • WorkspaceConfigError列挙型がConfigErrorと分離して新設されている(S3)
  • config show/config path/cleanがPhase 1非対応サブコマンドに含まれている(S4)
  • update --workspaceで進捗メッセージが出力される(S5)
  • チルダ展開時にdirs::home_dir()を使用し、HOME未設定時にエラーメッセージを返す(S6)

品質

  • cargo test / clippy / fmt 全パス

依存 Issue

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions