Skip to content

[Feature] --related 検索オプション実装(関連ドキュメント・コード検索) #50

@Kewton

Description

@Kewton

概要

commandindex search --related <file> オプションを実装し、指定ファイルに関連するドキュメント・コードを検索できるようにする。

背景・動機

開発者が「このファイルに関連するドキュメントやコードはどれか」を素早く把握するために必要。Phase 4 (Context Retrieval) の中核機能。

提案する解決策

CLI オプション

commandindex search --related src/auth/handler.ts
commandindex search --related docs/design/auth.md --format json
commandindex search --related src/auth/handler.ts --limit 10

排他制御

--related は通常の全文検索 query や --symbol とは排他。clap の conflicts_with を使用して3者排他を実現する。

  • --related 指定時、既存フィルタ(--tag, --path, --type, --heading)は適用しない(関連検索は独自のスコアリングロジックで結果を返すため)
  • --limit は共通で使用可能(デフォルト値20を流用)

関連判定ロジック(スコアリング)

以下の判定基準を組み合わせて関連度スコアを算出し、上位N件を返す。
スコアは単純加算方式で合算する(複数の関連性がある場合はスコアが積み上がる)。

構造ベース(Phase 1-2由来):

判定基準 スコア 説明
Markdownリンク([[]] / []())による明示的な参照関係 1.0 直接リンクは最も強い関連性
import / require による依存関係(symbols.db) 0.9 コード間の直接的な依存
frontmatter のタグ一致 0.5 × 一致タグ数 タグが多く一致するほど高スコア
ファイルパスの部分一致(例: docs/auth/src/auth/ 0.4 パスセグメント一致による推定
同一ディレクトリ内のファイル近接性 0.2 物理的な近接性

注: スコアの重み付けは初期値であり、チューニングは後続Issueで対応する。

コード連携(Phase 3由来):

判定基準 スコア 説明
import / require による依存関係(symbols.db) 0.9 双方向: 指定ファイルがimportしているもの + 指定ファイルをimportしているもの
シンボル名とMarkdown内のキーワード一致 0.5 シンボル名でtantivy全文検索

パス近接性アルゴリズム

  1. 共通パスプレフィックス方式: 2つのファイルパスの共通ディレクトリプレフィックスの深さに応じてスコアリング
    • 同一ディレクトリ: 0.2
    • 1階層上で共通: 0.1
    • それ以上離れている場合: 0.0
  2. パスセグメント部分一致: 異なるルート(docs/ vs src/)でも同名のサブディレクトリを持つ場合にスコア付与
    • 例: docs/auth/design.mdsrc/auth/handler.tsauth セグメント一致 → 0.4

タグ一致のデータ取得方法

tantivy インデックスから path 完全一致でドキュメントを取得し、tags フィールドを読み出す方式を採用する。

  • 指定ファイルに対応する tantivy ドキュメントの tags を取得
  • 全ドキュメントの tags と照合し、一致数に応じたスコアを付与
  • tantivy の TermQuery を使用して path 完全一致で高速検索

import依存関係のパス解決

dependencies テーブルの target_module はモジュールパス文字列(例: ./utils, std::io)であるため、ファイルパスとの突合にはパス解決が必要。

  • source→target 検索: find_imports_by_source(file_path) で指定ファイルのimport先を取得(新規実装が必要
  • target→source 検索: find_imports_by_target(module_path) で指定ファイルをimportしているファイルを取得(既存)
  • パス解決ルール: target_module の部分文字列がファイルパスに含まれるかで判定(厳密なモジュール解決は後続Issueに委譲)

関連検索結果の出力型

pub struct RelatedSearchResult {
    pub file_path: String,
    pub score: f32,
    pub relation_types: Vec<RelationType>,  // どの判定基準でヒットしたか
}

pub enum RelationType {
    MarkdownLink,
    ImportDependency,
    TagMatch { matched_tags: Vec<String> },
    PathSimilarity,
    DirectoryProximity,
    SymbolKeywordMatch,
}

出力フォーマット

human / json / path の各形式に対応。関連度スコア付き。

モジュール設計

関連検索のスコアリングロジックは src/search/related.rs に分離し、src/cli/search.rs はオーケストレーションのみとする。

src/
├── cli/search.rs          # run_related_search() オーケストレーション
├── search/
│   └── related.rs         # スコアリングロジック(新規)
├── indexer/
│   ├── reader.rs          # search_by_exact_path() 追加
│   └── symbol_store.rs    # find_imports_by_source(), find_file_links_by_target() 追加
└── output/                # format_related_results() 追加

パス正規化

関連検索の入力パスは以下の正規化を行ってからマッチングに使用する:

  • 先頭の ./ を除去
  • パス区切りを / に統一
  • 末尾の / を除去

受け入れ基準

  • --related で指定ファイルの関連ドキュメントが検索できる
  • Markdownリンクによる関連が検出される
  • タグ一致による関連が検出される
  • パス近接性による関連が検出される
  • import依存関係による関連が検出される(双方向: source→target, target→source)
  • 関連度スコアでソートされる
  • human / json / path 出力形式に対応
  • --related と query / --symbol を同時指定した場合にエラー
  • 関連ファイルが見つからない場合に適切なメッセージ
  • --related に存在しないファイルを指定した場合に適切なエラーメッセージ
  • --related に指定したファイルがインデックス未登録の場合に警告メッセージ表示
  • cargo test / clippy / fmt 全パス

新規実装が必要なAPI

  • find_imports_by_source(file_path): 指定ファイルのimport先一覧を取得(symbol_store.rs)
  • find_file_links_by_target(target_file): 指定ファイルを参照しているリンク元一覧を取得(symbol_store.rs)
  • search_by_exact_path(path): tantivy の TermQuery で path 完全一致検索(reader.rs)

依存 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