Skip to content

paths: walk every simple path between two concepts - #424

Merged
t0k0sh1 merged 2 commits into
mainfrom
418-paths-walk
Aug 5, 2026
Merged

paths: walk every simple path between two concepts#424
t0k0sh1 merged 2 commits into
mainfrom
418-paths-walk

Conversation

@t0k0sh1

@t0k0sh1 t0k0sh1 commented Aug 5, 2026

Copy link
Copy Markdown
Owner

Summary

POST /contexts/{name}/paths — 2つの概念の間を実際に手繰るエンドポイント(#418)。activate(起点から拡散)とexplore(近傍走査)では「AとBはどう関係しているか」に答えられなかったギャップを埋める。origins→targets間の全simple pathを最短順に返し、各trailは概念列(path)と歩いたassociation群(attributions込み、walk順)を運ぶ。

設計判断

  • 走査規律はexploreと同一: 双方向、labelはbridgeしない、retracted edgeはbridgeしない、ADR 0009 §6.3のschema:type除外(explore_excludingと同じmonomorphized-visible-closureパターンのpaths_excluding)
  • ランキングは決定的: distance昇順 → weakest-link strength降順(trail中の最小の生累積|sum|。corroborationが単発の強調に勝つactivateと同じ規律)→ 挿入順
  • 正直なcap: simple path列挙は最悪ケースで組合せ爆発するため、1呼び出しのエッジ展開数に固定budget(100k)を設け、達したらcapped: trueで報告(totalは下界)。網羅に見える切り捨てをしない
  • max_depthはexploreと同じ天井10、limitはデフォルト10・上限100(trailはassociationの連なりで単発マッチより重いためMAX_MATCH_LIMITより狭い)

各層の追従

  • MCP pathsツール(stdio bridge / /mcp 両対応、必須引数refusalテスト込み)
  • 両SDK: Python paths()(async source → unasync再生成)/ TypeScript paths()sdk/spec/surface.yaml登録、surface parity両言語通過
  • wire契約: tests/fixtures/wire/http/paths.json固定(additive、HTTP_CONTRACT不変)、shapes.json、Python/TSの契約テストにtyped decode追加
  • auth.rsRole::Read分類、/metricstaguru_searches_total{op="paths"}
  • /protocolマニュアル(使い分け+エンドポイント表)、README、docs(concepts/modeling)、CHANGELOG

Test plan

  • コア単体テスト11本(端点間・逆向き走査・weakest-linkランキング・corroboration・retracted/schema:type除外・simple path保証・prefix記録・capped)
  • HTTP統合(full loop、schema:type除外、wire契約)、MCP統合(呼び出し+refusal)
  • cargo fmt / cargo clippy --all-targets(警告なし)/ cargo test 全通過(2,150件)
  • Python: ruff / mypy / pytest(unit+integration、実サーバspawn)/ check_surface
  • TypeScript: build / eslint / tsc / vitest(unit+integration)/ check:surface

Closes #418

https://claude.ai/code/session_014RfogjbkTt5f14rz8fzYgP

Summary by CodeRabbit

  • 新機能
    • 2つの概念間にある単純経路を、最短順で検索できる paths 機能を追加しました。
    • 経路上の関連情報や引用、距離、強度を確認できます。
    • 深さ・結果件数を指定でき、探索上限に達した場合は状態を表示します。
    • HTTP API、MCP、Python SDK、TypeScript SDKから利用できます。
  • ドキュメント
    • 経路探索の使い方、制限事項、検索結果の見方を追加しました。
  • テスト
    • HTTP、MCP、SDKでの経路検索動作を検証しました。

POST /contexts/{name}/paths (#418) — the 手繰り itself: activate
spreads outward and explore sweeps a neighborhood, but neither answers
"how are these two related?" without the client re-walking the graph.
Each trail carries the whole concept path plus its associations in
walk order with full attributions.

Traversal follows explore's exact discipline (bidirectional, labels
never bridge, retracted edges never bridge, ADR 0009 §6.3's
schema:type exclusion via the same monomorphized-visible-closure
pattern). Ranking is deterministic: distance ascending, then
weakest-link strength descending on raw cumulative |sum| — the same
corroboration-outranks-emphasis discipline activate documents — then
insertion order. Simple-path enumeration is combinatorial in the worst
case, so one call examines at most a fixed edge budget and reports
capped: true honestly instead of a silently complete-looking total.

Exposed as the paths MCP tool, in both core SDKs per
sdk/spec/surface.yaml, pinned as a wire-contract fixture (additive,
HTTP_CONTRACT unchanged), classified Role::Read, counted as
taguru_searches_total{op="paths"}, and documented in the /protocol
manual, README, and docs site.

Closes #418

Claude-Session: https://claude.ai/code/session_014RfogjbkTt5f14rz8fzYgP
@coderabbitai

coderabbitai Bot commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 2d06227e-9e95-40ac-a2fa-b64d96dda7ae

📥 Commits

Reviewing files that changed from the base of the PR and between 42438f3 and f4f50ff.

📒 Files selected for processing (1)
  • src/mcp/schema.rs
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/mcp/schema.rs

📝 Walkthrough

Walkthrough

概念間の単純パス探索を追加しました。コア走査、HTTP API、MCP、Python SDK、TypeScript SDK、ワイヤー契約、メトリクス、文書、テストを更新しました。

Changes

paths 機能

Layer / File(s) Summary
単純パス列挙と結果モデル
src/context.rs, src/context/traverse.rs
単純パス、関連付け、距離、強度を返すモデルを追加しました。逆方向の枝刈り、除外規則、決定的ランキング、深さ・件数・エッジ予算を実装しました。
HTTP APIと契約検証
src/api.rs, src/api/explore.rs, src/main.rs, src/auth.rs, src/metrics/*, src/llm-protocol.md, tests/fixtures/wire/*, tests/http_api/*
POST /contexts/{name}/pathsを追加しました。リクエスト検証、関連付け解決、capped、認証、メトリクス、HTTP契約を追加しました。
MCPツール連携
src/mcp.rs, src/mcp/route.rs, src/mcp/schema.rs, tests/http_api/mcp_basics.rs
pathsツールを追加しました。originstargetsを必須入力として扱い、max_depthlimitを転送します。
SDKモデルとクライアント
sdk/python/*, sdk/typescript/*, sdk/spec/surface.yaml, README.md, docs/*, CHANGELOG.md
両SDKにTrailPathsPageContext.pathsを追加しました。公開エクスポート、ワイヤー契約、統合テスト、利用文書を更新しました。

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Client
  participant HTTP as POST /contexts/{name}/paths
  participant Context as Context::paths
  participant Resolver as association resolver
  Client->>HTTP: origins, targets, max_depth, limit
  HTTP->>Context: enumerate simple paths
  Context->>Resolver: resolve path associations
  Resolver-->>HTTP: TrailOut matches
  HTTP-->>Client: PathsPage with total and capped
Loading
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed タイトルは、2つの概念間の単純経路を探索する主要変更を明確かつ簡潔に示しています。
Linked Issues check ✅ Passed 実装はIssue #418の経路探索、決定的ランキング、除外規則、API連携、SDK、MCP、文書化の要件を満たしています。
Out of Scope Changes check ✅ Passed 変更はIssue #418の経路探索機能、関連する公開インターフェース、文書化、契約テストの範囲内です。
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch 418-paths-walk

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (3)
src/context/traverse.rs (1)

1137-1149: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

複数起点と重複起点のテストが不足しています。

paths_impl は起点を seen_origins で重複排除し、呼び出し側の順序を保つと 491-493 行のコメントで宣言しています。しかし追加したテストはすべて単一起点です。重複排除が壊れると、同じ trail が二重に列挙され total が水増しされます。この不変条件は現状テストで保証されていません。

同じ起点を二度渡した場合と、複数の異なる起点を渡した場合の total を検証するテストを追加してください。

💚 追加テストの例
#[test]
fn paths_deduplicates_repeated_origins_and_walks_every_distinct_one() {
    let mut context = Context::default();
    context.associate("a", "r", "t", 1.0).unwrap();
    context.associate("b", "r", "t", 1.0).unwrap();

    // The same origin twice must not enumerate the same trail twice.
    assert_eq!(context.paths(&["a", "a"], &["t"], 10, 10).total, 1);
    // Two distinct origins each contribute their own trail.
    let both = context.paths(&["a", "b"], &["t"], 10, 10);
    assert_eq!(both.total, 2);
}

以上は path instructions に従った指摘です。{src,tests}/**/*.rs: 「テストされていないエッジケース・失敗系(エラー・タイムアウト・不正な入力)の欠落」を指摘してください。

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/context/traverse.rs` around lines 1137 - 1149, Add a test near
paths_returns_nothing_for_unknowns_zero_depth_or_self that verifies paths
deduplicates repeated origins while traversing every distinct origin. Build
separate trails from two origins to one target, assert repeated input such as
["a", "a"] yields total 1, and assert ["a", "b"] yields total 2.

Source: Path instructions

src/llm-protocol.md (1)

65-70: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

引用解決の列挙に paths を追加してください。

pathstrails_outsection/locator を解決します。項目5と /contexts/{name}/citations の列挙に paths を追加してください。

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/llm-protocol.md` around lines 65 - 70,
項目5と「/contexts/{name}/citations」の引用解決対象に paths を追加し、trails_out と同様に paths 内の
section/locator を解決するよう llm-protocol.md の列挙を更新してください。
sdk/typescript/tests/integration/client.test.ts (1)

159-164: 🗄️ Data Integrity & Integration | 🔵 Trivial | ⚡ Quick win

両SDKの paths 統合テストを完全なレスポンス契約まで拡張してください。

現在のテストは単一路径の一部のフィールドだけを検証しています。次の変更を各テストに追加してください。

  • sdk/typescript/tests/integration/client.test.ts#L159-L164: Trail.distanceTrail.strength、関連付けの subjectobjectweightattributions、および max_depth 境界を検証してください。
  • sdk/python/tests/integration/test_full_loop.py#L162-L167: Trail.distanceTrail.strength、関連付けの subjectobjectweightattributions、および max_depth 境界を検証してください。

As per path instructions: テストでは未検証のエッジケースと不完全なアサーションを指摘します。

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@sdk/typescript/tests/integration/client.test.ts` around lines 159 - 164,
両SDKの paths
統合テストを完全なレスポンス契約まで拡張してください。sdk/typescript/tests/integration/client.test.ts の
ctx.paths と threads の検証に Trail.distance、Trail.strength、関連付けの
subject・object・weight・attributions、および max_depth
境界のアサーションを追加してください。sdk/python/tests/integration/test_full_loop.py の対応する paths
テストにも同じ検証を追加し、既存の単一路径アサーションを維持してください。

Source: Path instructions

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/api/explore.rs`:
- Around line 195-202: Update the search logging call in the relevant explore
handler to remove the externally supplied context, origins, and targets fields
from tracing::info!. Keep only the search operation context, request-independent
metadata, and the hit count (hits = result.total), while preserving the existing
TAGURU_LOG_SEARCHES-controlled logging behavior.

In `@src/mcp/schema.rs`:
- Around line 423-436: Update the max_depth property in the paths schema to
declare integer bounds matching the API contract: minimum 0 and maximum 10. Keep
its existing description and all other schema properties unchanged.

---

Nitpick comments:
In `@sdk/typescript/tests/integration/client.test.ts`:
- Around line 159-164: 両SDKの paths
統合テストを完全なレスポンス契約まで拡張してください。sdk/typescript/tests/integration/client.test.ts の
ctx.paths と threads の検証に Trail.distance、Trail.strength、関連付けの
subject・object・weight・attributions、および max_depth
境界のアサーションを追加してください。sdk/python/tests/integration/test_full_loop.py の対応する paths
テストにも同じ検証を追加し、既存の単一路径アサーションを維持してください。

In `@src/context/traverse.rs`:
- Around line 1137-1149: Add a test near
paths_returns_nothing_for_unknowns_zero_depth_or_self that verifies paths
deduplicates repeated origins while traversing every distinct origin. Build
separate trails from two origins to one target, assert repeated input such as
["a", "a"] yields total 1, and assert ["a", "b"] yields total 2.

In `@src/llm-protocol.md`:
- Around line 65-70: 項目5と「/contexts/{name}/citations」の引用解決対象に paths
を追加し、trails_out と同様に paths 内の section/locator を解決するよう llm-protocol.md
の列挙を更新してください。
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 640460a6-d6af-4bb0-b1cf-650bb2514e22

📥 Commits

Reviewing files that changed from the base of the PR and between 2baf27d and 42438f3.

⛔ Files ignored due to path filters (1)
  • sdk/python/uv.lock is excluded by !**/*.lock
📒 Files selected for processing (33)
  • CHANGELOG.md
  • README.md
  • docs/concepts.html
  • docs/modeling.html
  • sdk/python/src/taguru/__init__.py
  • sdk/python/src/taguru/_async/client.py
  • sdk/python/src/taguru/_models.py
  • sdk/python/src/taguru/_sync/client.py
  • sdk/python/tests/integration/test_full_loop.py
  • sdk/python/tests/unit/test_wire_contract.py
  • sdk/spec/surface.yaml
  • sdk/typescript/src/client.ts
  • sdk/typescript/src/index.ts
  • sdk/typescript/src/models.ts
  • sdk/typescript/tests/integration/client.test.ts
  • sdk/typescript/tests/unit/wire-contract.test.ts
  • src/api.rs
  • src/api/explore.rs
  • src/auth.rs
  • src/context.rs
  • src/context/traverse.rs
  • src/llm-protocol.md
  • src/main.rs
  • src/mcp.rs
  • src/mcp/route.rs
  • src/mcp/schema.rs
  • src/metrics/taxonomy.rs
  • tests/fixtures/wire/http/paths.json
  • tests/fixtures/wire/shapes.json
  • tests/http_api/contract.rs
  • tests/http_api/mcp_basics.rs
  • tests/http_api/retrieval_core.rs
  • tests/http_api/schema_type_label.rs

Comment thread src/api/explore.rs
Comment thread src/mcp/schema.rs
CodeRabbit on PR #424: the paths tool's max_depth declared only
"integer", so a negative value would pass MCP schema validation and
surface as a 422 deserialization failure server-side — the exact
failure mode every limit property's minimum: 0 exists to catch early.
Applied to explore's max_depth too, which had the same gap. No
maximum: 10, deliberately: the server clamps larger depths rather
than refusing them (same contract as every limit, which caps at 1000
while declaring only the minimum), and a schema maximum would make
MCP refuse what HTTP accepts.

Claude-Session: https://claude.ai/code/session_014RfogjbkTt5f14rz8fzYgP
@t0k0sh1
t0k0sh1 merged commit 6d5c596 into main Aug 5, 2026
9 checks passed
@t0k0sh1
t0k0sh1 deleted the 418-paths-walk branch August 5, 2026 06:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

paths: walk between two concepts (POST /contexts/{name}/paths)

1 participant