Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
104 changes: 60 additions & 44 deletions code_review_graph/hints.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,153 +12,169 @@
from collections import deque
from typing import Any

# ---- intent categories and their characteristic tool names ----
# ---- intent categories and their characteristic public MCP tool names ----
# Keep these keyed on exported MCP tool names only. Do not substitute
# internal helper names from implementation modules here.

_INTENT_TOOLS: dict[str, set[str]] = {
"reviewing": {
"detect_changes", "get_review_context", "get_affected_flows", "get_impact_radius",
"detect_changes_tool", "get_review_context_tool", "get_affected_flows_tool", "get_impact_radius_tool",
},
"debugging": {
"query_graph", "get_flow", "semantic_search_nodes",
"query_graph_tool", "get_flow_tool", "semantic_search_nodes_tool",
},
"refactoring": {
"refactor", "find_dead_code", "suggest_refactorings",
"refactor_tool", "apply_refactor_tool",
},
"exploring": {
"list_communities", "get_architecture_overview", "list_flows", "list_graph_stats",
"list_communities_tool", "get_architecture_overview_tool", "list_flows_tool", "list_graph_stats_tool",
},
}

# ---- workflow adjacency: for each tool, which tools are useful next ----

_WORKFLOW: dict[str, list[dict[str, str]]] = {
"list_flows": [
"list_flows_tool": [
{
"tool": "get_flow",
"tool": "get_flow_tool",
"suggestion": "Drill into a specific flow for step-by-step details",
},
{
"tool": "get_affected_flows",
"tool": "get_affected_flows_tool",
"suggestion": "Check which flows are affected by recent changes",
},
{
"tool": "get_architecture_overview",
"tool": "get_architecture_overview_tool",
"suggestion": "See the high-level architecture",
},
],
"get_flow": [
"get_flow_tool": [
{
"tool": "query_graph",
"tool": "query_graph_tool",
"suggestion": "Inspect callers/callees of a step in this flow",
},
{
"tool": "get_affected_flows",
"tool": "get_affected_flows_tool",
"suggestion": "Check if changes affect this flow",
},
{
"tool": "list_flows",
"tool": "list_flows_tool",
"suggestion": "Browse other execution flows",
},
],
"get_affected_flows": [
"get_affected_flows_tool": [
{
"tool": "detect_changes",
"tool": "detect_changes_tool",
"suggestion": "Get risk-scored change analysis",
},
{
"tool": "get_flow",
"tool": "get_flow_tool",
"suggestion": "Inspect a specific affected flow",
},
{
"tool": "get_review_context",
"tool": "get_review_context_tool",
"suggestion": "Build a full review context for the changes",
},
],
"list_communities": [
"list_communities_tool": [
{
"tool": "get_community",
"tool": "get_community_tool",
"suggestion": "Inspect a specific community's members",
},
{
"tool": "get_architecture_overview",
"tool": "get_architecture_overview_tool",
"suggestion": "See cross-community coupling and warnings",
},
{
"tool": "list_flows",
"tool": "list_flows_tool",
"suggestion": "See execution flows across communities",
},
],
"get_community": [
"get_community_tool": [
{
"tool": "query_graph",
"tool": "query_graph_tool",
"suggestion": "Explore callers/callees of community members",
},
{
"tool": "list_communities",
"tool": "list_communities_tool",
"suggestion": "Browse other communities",
},
{
"tool": "get_architecture_overview",
"tool": "get_architecture_overview_tool",
"suggestion": "See how this community fits the architecture",
},
],
"get_architecture_overview": [
"get_architecture_overview_tool": [
{
"tool": "list_communities",
"tool": "list_communities_tool",
"suggestion": "Drill into individual communities",
},
{
"tool": "detect_changes",
"tool": "detect_changes_tool",
"suggestion": "See how recent changes affect the architecture",
},
{
"tool": "list_flows",
"tool": "list_flows_tool",
"suggestion": "Explore execution flows",
},
],
"detect_changes": [
"detect_changes_tool": [
{
"tool": "get_review_context",
"tool": "get_review_context_tool",
"suggestion": "Build a full review context with source snippets",
},
{
"tool": "get_affected_flows",
"tool": "get_affected_flows_tool",
"suggestion": "See which execution flows are affected",
},
{
"tool": "get_impact_radius",
"tool": "get_impact_radius_tool",
"suggestion": "Expand the blast radius analysis",
},
{
"tool": "refactor",
"tool": "refactor_tool",
"suggestion": "Look for refactoring opportunities in changed code",
},
],
"refactor": [
"refactor_tool": [
{
"tool": "query_graph",
"tool": "apply_refactor_tool",
"suggestion": "Apply a reviewed rename preview",
},
{
"tool": "semantic_search_nodes_tool",
"suggestion": "Find related symbols to also rename",
},
{
"tool": "query_graph_tool",
"suggestion": "Verify call sites before applying a rename",
},
],
"apply_refactor_tool": [
{
"tool": "detect_changes",
"suggestion": "Check risk of the refactored code",
"tool": "detect_changes_tool",
"suggestion": "Check the impact of the applied refactor",
},
{
"tool": "semantic_search_nodes",
"suggestion": "Find related symbols to also rename",
"tool": "get_affected_flows_tool",
"suggestion": "See which execution flows may have changed",
},
{
"tool": "query_graph_tool",
"suggestion": "Inspect remaining call sites or rename fallout",
},
],
"semantic_search_nodes": [
"semantic_search_nodes_tool": [
{
"tool": "query_graph",
"tool": "query_graph_tool",
"suggestion": "Inspect callers/callees of a search result",
},
{
"tool": "get_flow",
"tool": "get_flow_tool",
"suggestion": "See the execution flow through a matched node",
},
{
"tool": "get_impact_radius",
"tool": "get_impact_radius_tool",
"suggestion": "Check the blast radius from matched nodes",
},
],
Expand Down
69 changes: 36 additions & 33 deletions code_review_graph/prompts.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
"""MCP prompt templates for Code Review Graph.

Provides 5 pre-built prompt workflows, all enforcing token-efficient
detail_level="minimal" first patterns with get_minimal_context entry point.
detail_level="minimal" first patterns with get_minimal_context_tool entry point.

1. review_changes - pre-commit review using detect_changes + affected_flows
1. review_changes - pre-commit review using detect_changes_tool + get_affected_flows_tool
2. architecture_map - architecture docs using communities, flows, Mermaid
3. debug_issue - guided debugging using search, flow tracing
4. onboard_developer - new dev orientation using stats, architecture, flows
Expand All @@ -17,15 +17,15 @@
_TOKEN_EFFICIENCY_PREAMBLE = ( # nosec B105 — prompt template, not a password
"""\
## Rules for Token-Efficient Graph Usage
1. ALWAYS call `get_minimal_context` first with a task description.
1. ALWAYS call `get_minimal_context_tool` first with a task description.
2. Use `detail_level="minimal"` on all tool calls unless the minimal output \
is insufficient.
3. Only escalate to `detail_level="standard"` or `"verbose"` for the specific \
entities that need deeper inspection.
4. Never request more than 3 tool calls per turn unless absolutely necessary.
5. Prefer targeted queries (query_graph with a specific symbol) over broad \
scans (list_communities with full members).
6. When reviewing changes: detect_changes(detail_level="minimal") → only \
5. Prefer targeted queries (query_graph_tool with a specific symbol) over broad \
scans (list_communities_tool with full members).
6. When reviewing changes: detect_changes_tool(detail_level="minimal") → only \
expand on high-risk items.
"""
)
Expand All @@ -51,22 +51,22 @@ def review_changes_prompt(base: str = "HEAD~1") -> list[Message]:
return _user(
f"{_TOKEN_EFFICIENCY_PREAMBLE}\n"
f"## Review Workflow\n"
f'1. Call `get_minimal_context(task="review changes against '
f'1. Call `get_minimal_context_tool(task="review changes against '
f'{base}")` to get risk overview.\n'
f'2. If risk is "low": call '
f'`detect_changes(detail_level="minimal")` → report summary '
f'`detect_changes_tool(detail_level="minimal")` → report summary '
f"+ any test gaps.\n"
f'3. If risk is "medium" or "high":\n'
f' a. Call `detect_changes(detail_level="standard")` for '
f' a. Call `detect_changes_tool(detail_level="standard")` for '
f"full change list.\n"
f" b. For each high-risk function, call "
f'`query_graph(pattern="callers_of", target=<func>, '
f'`query_graph_tool(pattern="callers_of", target=<func>, '
f'detail_level="minimal")`.\n'
f' c. Call `get_affected_flows(detail_level="minimal")` '
f' c. Call `get_affected_flows_tool(detail_level="minimal")` '
f"only if >3 changed functions.\n"
f"4. Summarize: risk level, what changed, test gaps, "
f"specific improvements needed.\n\n"
f"Do NOT call get_review_context unless you need source code "
f"Do NOT call get_review_context_tool unless you need source code "
f"snippets for a specific function."
)

Expand All @@ -76,12 +76,12 @@ def architecture_map_prompt() -> list[Message]:
return _user(
f"{_TOKEN_EFFICIENCY_PREAMBLE}\n"
"## Architecture Mapping Workflow\n"
'1. Call `get_minimal_context(task="map architecture")`.\n'
'2. Call `get_architecture_overview(detail_level="minimal")` '
'1. Call `get_minimal_context_tool(task="map architecture")`.\n'
'2. Call `get_architecture_overview_tool(detail_level="minimal")` '
"for community coupling summary.\n"
'3. Call `list_flows(detail_level="minimal")` for critical '
'3. Call `list_flows_tool(detail_level="minimal")` for critical '
"flow names + criticality scores.\n"
"4. Only call `get_community(name=<X>, "
"4. Only call `get_community_tool(name=<X>, "
'detail_level="standard")` for the 1-2 communities the user '
"is most interested in.\n"
"5. Produce a concise Mermaid diagram showing communities as "
Expand All @@ -99,17 +99,17 @@ def debug_issue_prompt(description: str = "") -> list[Message]:
return _user(
f"{_TOKEN_EFFICIENCY_PREAMBLE}\n"
"## Debug Workflow\n"
f'1. Call `get_minimal_context(task="debug: '
f'1. Call `get_minimal_context_tool(task="debug: '
f'{desc_part}")`.\n'
"2. Call `semantic_search_nodes(query=<keywords from "
"2. Call `semantic_search_nodes_tool(query=<keywords from "
'description>, detail_level="minimal", limit=5)`.\n'
"3. For the top 1-2 results, call "
'`query_graph(pattern="callers_of", target=<name>, '
'`query_graph_tool(pattern="callers_of", target=<name>, '
'detail_level="minimal")`.\n'
"4. If the issue involves execution flow: call "
"`get_flow(name=<relevant flow>)` for the single most "
"`get_flow_tool(name=<relevant flow>)` for the single most "
"relevant flow.\n"
"5. Only call `get_review_context` or `get_impact_radius` "
"5. Only call `get_review_context_tool` or `get_impact_radius_tool` "
"if you need to trace the blast radius of a specific change."
)

Expand All @@ -119,13 +119,13 @@ def onboard_developer_prompt() -> list[Message]:
return _user(
f"{_TOKEN_EFFICIENCY_PREAMBLE}\n"
"## Onboarding Workflow\n"
'1. Call `get_minimal_context(task="onboard developer")`.\n'
"2. Call `list_graph_stats()` for technology overview.\n"
'3. Call `get_architecture_overview(detail_level="minimal")` '
'1. Call `get_minimal_context_tool(task="onboard developer")`.\n'
"2. Call `list_graph_stats_tool()` for technology overview.\n"
'3. Call `get_architecture_overview_tool(detail_level="minimal")` '
"for the 30-second mental model.\n"
'4. Call `list_communities(detail_level="minimal")` — '
'4. Call `list_communities_tool(detail_level="minimal")` — '
"present as a table of module names + sizes.\n"
'5. Call `list_flows(detail_level="minimal")` — highlight '
'5. Call `list_flows_tool(detail_level="minimal")` — highlight '
"the top 3 critical flows.\n"
"6. Only drill into a specific community or flow if the "
"developer asks."
Expand All @@ -141,19 +141,22 @@ def pre_merge_check_prompt(base: str = "HEAD~1") -> list[Message]:
return _user(
f"{_TOKEN_EFFICIENCY_PREAMBLE}\n"
"## Pre-Merge Check Workflow\n"
'1. Call `get_minimal_context(task="pre-merge check")`.\n'
'2. Call `detect_changes(detail_level="minimal")` for risk '
'1. Call `get_minimal_context_tool(task="pre-merge check")`.\n'
'2. Call `detect_changes_tool(detail_level="minimal")` for risk '
"score and test gaps.\n"
"3. If risk > 0.4: call "
'`get_affected_flows(detail_level="minimal")`.\n'
'`get_affected_flows_tool(detail_level="minimal")`.\n'
"4. If test_gap_count > 0: call "
'`query_graph(pattern="tests_for", '
'`query_graph_tool(pattern="tests_for", '
'target=<each untested function>, detail_level="minimal")` '
"for up to 3 functions.\n"
'5. Call `refactor(mode="dead_code", '
'5. Call `refactor_tool(mode="dead_code", '
'detail_level="minimal")` to check for newly dead code.\n'
"6. Only call `find_large_functions` or `get_impact_radius` "
"6. If you are planning a rename, also call "
"`semantic_search_nodes_tool(detail_level=\"minimal\")` to find "
"related symbols to also rename.\n"
"7. Only call `find_large_functions_tool` or `get_impact_radius_tool` "
"if risk > 0.7.\n"
"7. Output: GO/NO-GO recommendation with 1-sentence "
"8. Output: GO/NO-GO recommendation with 1-sentence "
"justification + list of required follow-ups."
)
Loading