code-review-graph-codeblackwell 2.3.6.post1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (74) hide show
  1. code_review_graph/__init__.py +20 -0
  2. code_review_graph/__main__.py +4 -0
  3. code_review_graph/analysis.py +410 -0
  4. code_review_graph/changes.py +409 -0
  5. code_review_graph/cli.py +1255 -0
  6. code_review_graph/communities.py +874 -0
  7. code_review_graph/constants.py +23 -0
  8. code_review_graph/context_savings.py +317 -0
  9. code_review_graph/custom_languages.py +322 -0
  10. code_review_graph/daemon.py +1009 -0
  11. code_review_graph/daemon_cli.py +320 -0
  12. code_review_graph/docs/LLM-OPTIMIZED-REFERENCE.md +71 -0
  13. code_review_graph/embeddings.py +1006 -0
  14. code_review_graph/enrich.py +303 -0
  15. code_review_graph/eval/__init__.py +33 -0
  16. code_review_graph/eval/benchmarks/__init__.py +1 -0
  17. code_review_graph/eval/benchmarks/agent_baseline.py +193 -0
  18. code_review_graph/eval/benchmarks/build_performance.py +60 -0
  19. code_review_graph/eval/benchmarks/flow_completeness.py +36 -0
  20. code_review_graph/eval/benchmarks/impact_accuracy.py +220 -0
  21. code_review_graph/eval/benchmarks/multi_hop_retrieval.py +125 -0
  22. code_review_graph/eval/benchmarks/search_quality.py +59 -0
  23. code_review_graph/eval/benchmarks/token_efficiency.py +143 -0
  24. code_review_graph/eval/configs/code-review-graph.yaml +50 -0
  25. code_review_graph/eval/configs/express.yaml +45 -0
  26. code_review_graph/eval/configs/fastapi.yaml +48 -0
  27. code_review_graph/eval/configs/flask.yaml +50 -0
  28. code_review_graph/eval/configs/gin.yaml +51 -0
  29. code_review_graph/eval/configs/httpx.yaml +48 -0
  30. code_review_graph/eval/reporter.py +301 -0
  31. code_review_graph/eval/runner.py +211 -0
  32. code_review_graph/eval/scorer.py +85 -0
  33. code_review_graph/eval/token_benchmark.py +182 -0
  34. code_review_graph/exports.py +409 -0
  35. code_review_graph/flows.py +698 -0
  36. code_review_graph/graph.py +1427 -0
  37. code_review_graph/graph_diff.py +122 -0
  38. code_review_graph/hints.py +384 -0
  39. code_review_graph/incremental.py +1245 -0
  40. code_review_graph/jedi_resolver.py +303 -0
  41. code_review_graph/main.py +1079 -0
  42. code_review_graph/memory.py +142 -0
  43. code_review_graph/migrations.py +284 -0
  44. code_review_graph/parser.py +6957 -0
  45. code_review_graph/postprocessing.py +134 -0
  46. code_review_graph/prompts.py +159 -0
  47. code_review_graph/refactor.py +852 -0
  48. code_review_graph/registry.py +319 -0
  49. code_review_graph/rescript_resolver.py +206 -0
  50. code_review_graph/search.py +447 -0
  51. code_review_graph/skills.py +1481 -0
  52. code_review_graph/spring_resolver.py +200 -0
  53. code_review_graph/temporal_resolver.py +199 -0
  54. code_review_graph/token_benchmark.py +125 -0
  55. code_review_graph/tools/__init__.py +156 -0
  56. code_review_graph/tools/_common.py +176 -0
  57. code_review_graph/tools/analysis_tools.py +184 -0
  58. code_review_graph/tools/build.py +541 -0
  59. code_review_graph/tools/community_tools.py +246 -0
  60. code_review_graph/tools/context.py +152 -0
  61. code_review_graph/tools/docs.py +274 -0
  62. code_review_graph/tools/flows_tools.py +176 -0
  63. code_review_graph/tools/query.py +692 -0
  64. code_review_graph/tools/refactor_tools.py +168 -0
  65. code_review_graph/tools/registry_tools.py +125 -0
  66. code_review_graph/tools/review.py +477 -0
  67. code_review_graph/tsconfig_resolver.py +257 -0
  68. code_review_graph/visualization.py +2184 -0
  69. code_review_graph/wiki.py +305 -0
  70. code_review_graph_codeblackwell-2.3.6.post1.dist-info/METADATA +718 -0
  71. code_review_graph_codeblackwell-2.3.6.post1.dist-info/RECORD +74 -0
  72. code_review_graph_codeblackwell-2.3.6.post1.dist-info/WHEEL +4 -0
  73. code_review_graph_codeblackwell-2.3.6.post1.dist-info/entry_points.txt +3 -0
  74. code_review_graph_codeblackwell-2.3.6.post1.dist-info/licenses/LICENSE +21 -0
@@ -0,0 +1,176 @@
1
+ """Tools 10, 11: list_flows, get_flow."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from pathlib import Path
6
+ from typing import Any
7
+
8
+ from ..flows import get_flow_by_id, get_flows
9
+ from ..hints import generate_hints, get_session
10
+ from ._common import _get_store
11
+
12
+ # ---------------------------------------------------------------------------
13
+ # Tool 10: list_flows [EXPLORE]
14
+ # ---------------------------------------------------------------------------
15
+
16
+
17
+ def list_flows(
18
+ repo_root: str | None = None,
19
+ sort_by: str = "criticality",
20
+ limit: int = 50,
21
+ kind: str | None = None,
22
+ detail_level: str = "standard",
23
+ ) -> dict[str, Any]:
24
+ """List execution flows in the codebase, sorted by criticality.
25
+
26
+ [EXPLORE] Retrieves stored execution flows from the knowledge graph.
27
+ Each flow represents a call chain starting from an entry point
28
+ (e.g. HTTP handler, CLI command, test function).
29
+
30
+ Args:
31
+ repo_root: Repository root path. Auto-detected if omitted.
32
+ sort_by: Sort column: criticality, depth, node_count, file_count,
33
+ or name.
34
+ limit: Maximum flows to return (default: 50).
35
+ kind: Optional filter by entry point kind (e.g. "Test", "Function").
36
+ detail_level: "standard" (default) returns full flow data;
37
+ "minimal" returns only name, criticality, and
38
+ node_count per flow.
39
+
40
+ Returns:
41
+ List of flows with criticality scores.
42
+ """
43
+ store, root = _get_store(repo_root)
44
+ try:
45
+ fetch_limit = (
46
+ limit if not kind else limit * 10
47
+ ) # fetch more when filtering
48
+ flows = get_flows(store, sort_by=sort_by, limit=fetch_limit)
49
+
50
+ if kind:
51
+ filtered = []
52
+ for f in flows:
53
+ ep_id = f.get("entry_point_id")
54
+ if ep_id is not None:
55
+ node_kind = store.get_node_kind_by_id(ep_id)
56
+ if node_kind == kind:
57
+ filtered.append(f)
58
+ flows = filtered[:limit]
59
+
60
+ if detail_level == "minimal":
61
+ flows = [
62
+ {
63
+ "name": f["name"],
64
+ "criticality": f["criticality"],
65
+ "node_count": f["node_count"],
66
+ }
67
+ for f in flows
68
+ ]
69
+
70
+ result: dict[str, object] = {
71
+ "status": "ok",
72
+ "summary": f"Found {len(flows)} execution flow(s)",
73
+ "flows": flows,
74
+ }
75
+ result["_hints"] = generate_hints(
76
+ "list_flows", result, get_session()
77
+ )
78
+ return result
79
+ except Exception as exc:
80
+ return {"status": "error", "error": str(exc)}
81
+ finally:
82
+ store.close()
83
+
84
+
85
+ # ---------------------------------------------------------------------------
86
+ # Tool 11: get_flow [EXPLORE]
87
+ # ---------------------------------------------------------------------------
88
+
89
+
90
+ def get_flow(
91
+ flow_id: int | None = None,
92
+ flow_name: str | None = None,
93
+ include_source: bool = False,
94
+ repo_root: str | None = None,
95
+ ) -> dict[str, Any]:
96
+ """Get details of a single execution flow.
97
+
98
+ [EXPLORE] Retrieves full path details for a flow, including each step's
99
+ function name, file, and line numbers. Optionally includes source
100
+ snippets for every step in the path.
101
+
102
+ Args:
103
+ flow_id: Database ID of the flow (from list_flows).
104
+ flow_name: Name to search for (partial match). Ignored if flow_id
105
+ given.
106
+ include_source: If True, include source code snippets for each step.
107
+ repo_root: Repository root path. Auto-detected if omitted.
108
+
109
+ Returns:
110
+ Flow details with steps, or not_found status.
111
+ """
112
+ store, root = _get_store(repo_root)
113
+ try:
114
+ flow: dict | None = None
115
+
116
+ if flow_id is not None:
117
+ flow = get_flow_by_id(store, flow_id)
118
+ elif flow_name is not None:
119
+ # Search flows by name match
120
+ all_flows = get_flows(
121
+ store, sort_by="criticality", limit=500
122
+ )
123
+ for f in all_flows:
124
+ if flow_name.lower() in f["name"].lower():
125
+ flow = get_flow_by_id(store, f["id"])
126
+ break
127
+
128
+ if flow is None:
129
+ return {
130
+ "status": "not_found",
131
+ "summary": "No flow found matching the given criteria.",
132
+ }
133
+
134
+ # Optionally include source snippets for each step
135
+ if include_source and "steps" in flow:
136
+ for step in flow["steps"]:
137
+ fp = Path(step["file"]) if step.get("file") else None
138
+ if fp is not None and not fp.is_absolute():
139
+ fp = root / fp
140
+ file_path = fp
141
+ if file_path and file_path.is_file():
142
+ try:
143
+ lines = file_path.read_text(
144
+ errors="replace"
145
+ ).splitlines()
146
+ start = max(
147
+ 0, (step.get("line_start") or 1) - 1
148
+ )
149
+ end = min(
150
+ len(lines),
151
+ step.get("line_end") or len(lines),
152
+ )
153
+ step["source"] = "\n".join(
154
+ f"{i + 1}: {lines[i]}"
155
+ for i in range(start, end)
156
+ )
157
+ except (OSError, UnicodeDecodeError):
158
+ step["source"] = "(could not read file)"
159
+
160
+ result = {
161
+ "status": "ok",
162
+ "summary": (
163
+ f"Flow '{flow['name']}': {flow['node_count']} nodes, "
164
+ f"depth {flow['depth']}, "
165
+ f"criticality {flow['criticality']:.4f}"
166
+ ),
167
+ "flow": flow,
168
+ }
169
+ result["_hints"] = generate_hints(
170
+ "get_flow", result, get_session()
171
+ )
172
+ return result
173
+ except Exception as exc:
174
+ return {"status": "error", "error": str(exc)}
175
+ finally:
176
+ store.close()