Skip to content

Commit 645d438

Browse files
HumanBean17claude
andcommitted
fix(jrag): inspect forwards --service/--module to resolve_query
inspect inherited --service/--module/--limit from _common_parser but, unlike every other command, neither applied nor warned on them. --limit is genuinely N/A (describe_v2 returns one node); --service/--module were missed wiring — resolve_query already accepts them to disambiguate cross-service name collisions, and find + the traversal commands already forward them. Now forwards microservice=args.service or "", module=args.module or "" so an ambiguous simple name (e.g. UserController in service-a vs service-b) resolves to a single node when --service is given. No-flag path unchanged ("" matches resolve_query's default). Adds test_inspect_service_flag_disambiguates_collision on the route_extraction_smoke fixture (UserController as smoke.a.* / smoke.b.*). Co-Authored-By: Claude <noreply@anthropic.com>
1 parent 785ab4a commit 645d438

2 files changed

Lines changed: 64 additions & 1 deletion

File tree

java_codebase_rag/jrag.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1556,7 +1556,10 @@ def _cmd_inspect(args: argparse.Namespace) -> int:
15561556
print(render(env, fmt=args.format, detail=args.detail))
15571557
return 2
15581558

1559-
# Resolve the query
1559+
# Resolve the query. Forward --service/--module so an ambiguous name
1560+
# (same name across services) disambiguates by microservice/module, the
1561+
# same way find and the traversal commands do. Without this, inspect
1562+
# silently ignored these inherited flags (resolve_query accepts them).
15601563
node, env = resolve_query(
15611564
args.query,
15621565
hint_kind=args.kind,
@@ -1565,6 +1568,8 @@ def _cmd_inspect(args: argparse.Namespace) -> int:
15651568
fqn_contains=args.fqn_contains,
15661569
cfg=cfg,
15671570
graph=graph,
1571+
microservice=args.service or "",
1572+
module=args.module or "",
15681573
)
15691574

15701575
if env.status != "ok":

tests/test_jrag_locate.py

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -434,6 +434,64 @@ def test_inspect_ambiguous_returns_candidates(corpus_root: Path, ladybug_db_path
434434
assert payload.get("message"), "not_found must carry a message"
435435

436436

437+
# ----- Test 12b: inspect --service disambiguates a cross-service name collision -----
438+
439+
440+
def test_inspect_service_flag_disambiguates_collision(
441+
ladybug_db_path_route_extraction_smoke: Path,
442+
) -> None:
443+
"""--service is forwarded to resolve_query (regression: inspect used to
444+
silently ignore the inherited --service/--module flags).
445+
446+
The route_extraction_smoke corpus has ``UserController`` as two DISTINCT
447+
types across services — ``smoke.a.UserController`` (service-a) and
448+
``smoke.b.UserController`` (service-b). By simple name the resolve is
449+
``ambiguous`` (two genuinely-different types; the class-vs-constructor
450+
auto-pick never collapses two distinct classes). Passing
451+
``--service service-a`` must narrow resolve_v2 to smoke.a.UserController
452+
and yield ``ok`` with exactly that one resolved node.
453+
454+
(The fqn_collision_smoke fixture does NOT work here: both copies share the
455+
SAME fqn ``com.example.SharedDto``, so the graph builder merges them into a
456+
single node and the baseline resolve is already ``ok``.)
457+
"""
458+
fixture_root = Path(__file__).parent / "fixtures" / "route_extraction_smoke"
459+
env = os.environ.copy()
460+
env["JAVA_CODEBASE_RAG_SOURCE_ROOT"] = str(fixture_root)
461+
env["JAVA_CODEBASE_RAG_INDEX_DIR"] = str(ladybug_db_path_route_extraction_smoke.parent)
462+
463+
# Baseline: by simple name, UserController is ambiguous across the two services.
464+
base = _run_jrag(["inspect", "UserController", "--format", "json"], env=env)
465+
assert base.returncode in (0, 2), f"baseline rc={base.returncode}\n{base.stdout}"
466+
base_payload = json.loads(base.stdout)
467+
assert base_payload["status"] == "ambiguous", (
468+
f"expected ambiguous baseline, got {base_payload['status']}: {base.stdout}"
469+
)
470+
assert len(base_payload.get("candidates", [])) > 1, (
471+
f"baseline must expose >1 candidate: {base.stdout}"
472+
)
473+
474+
# Fix under test: --service narrows resolve_v2 to the service-a node.
475+
scoped = _run_jrag(
476+
["inspect", "UserController", "--service", "service-a", "--format", "json"], env=env
477+
)
478+
assert scoped.returncode == 0, (
479+
f"inspect --service failed: rc={scoped.returncode}\nstdout={scoped.stdout}\nstderr={scoped.stderr}"
480+
)
481+
scoped_payload = json.loads(scoped.stdout)
482+
assert scoped_payload["status"] == "ok", (
483+
f"--service service-a should disambiguate to ok, got {scoped_payload['status']}: {scoped.stdout}"
484+
)
485+
nodes = scoped_payload.get("nodes", {})
486+
assert len(nodes) == 1, (
487+
f"expected exactly one resolved node, got {len(nodes)}: {scoped.stdout}"
488+
)
489+
resolved_fqn = next(iter(nodes.values())).get("fqn", "")
490+
assert resolved_fqn == "smoke.a.UserController", (
491+
f"--service service-a should resolve smoke.a.UserController, got {resolved_fqn}"
492+
)
493+
494+
437495
# ----- Test 13: inspect populates file_location -----
438496

439497

0 commit comments

Comments
 (0)