codegraph-engine 2.1.2__py3-none-any.whl → 2.1.3__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.
codegraph/__init__.py CHANGED
@@ -1,6 +1,6 @@
1
1
  """CodeGraph MCP: local, evidence-backed codebase intelligence."""
2
2
 
3
- __version__ = "2.1.2"
3
+ __version__ = "2.1.3"
4
4
  from codegraph.errors import (
5
5
  CodeGraphError,
6
6
  ErrorCode,
codegraph/frameworks.py CHANGED
@@ -79,6 +79,7 @@ class RouteDetection:
79
79
  resolution_status: str = "RESOLVED" # RESOLVED | UNRESOLVED | AMBIGUOUS
80
80
  evidence: str = ""
81
81
  module: str = ""
82
+ endpoint_id_override: str | None = None
82
83
 
83
84
  @property
84
85
  def route_signature(self) -> str:
@@ -87,13 +88,18 @@ class RouteDetection:
87
88
 
88
89
  @property
89
90
  def endpoint_id(self) -> str:
90
- """Stable, globally unique endpoint identifier scoped by module to prevent collisions."""
91
- if self.module:
92
- mod = self.module
93
- else:
94
- from codegraph.indexing.models import normalize_module
95
- mod = normalize_module(self.file_path)
96
- return f"API_ENDPOINT:{mod}:{self.http_method} {self.normalized_route}"
91
+ """Stable, deterministic, globally unique endpoint identifier for a route declaration."""
92
+ if self.endpoint_id_override:
93
+ return self.endpoint_id_override
94
+
95
+ clean_path = self.file_path.replace("\\", "/").strip()
96
+ while clean_path.startswith("./"):
97
+ clean_path = clean_path[2:]
98
+ clean_path = clean_path.lstrip("/") or "root"
99
+
100
+ handler_part = f"#{self.handler_name}" if self.handler_name else ""
101
+ fw_part = f":{self.framework}" if self.framework else ""
102
+ return f"API_ENDPOINT{fw_part}:{clean_path}:{self.line}:{self.http_method} {self.normalized_route}{handler_part}"
97
103
 
98
104
  def as_dict(self) -> dict[str, object]:
99
105
  return {
@@ -655,7 +655,18 @@ class Indexer:
655
655
  con.executemany(
656
656
  "INSERT INTO framework_routes(endpoint_id, framework, http_method, route_path, "
657
657
  "normalized_route, handler_name, handler_canonical_id, file_path, line, evidence, confidence) "
658
- "VALUES (?,?,?,?,?,?,?,?,?,?,?)",
658
+ "VALUES (?,?,?,?,?,?,?,?,?,?,?) "
659
+ "ON CONFLICT(endpoint_id) DO UPDATE SET "
660
+ "framework=excluded.framework, "
661
+ "http_method=excluded.http_method, "
662
+ "route_path=excluded.route_path, "
663
+ "normalized_route=excluded.normalized_route, "
664
+ "handler_name=excluded.handler_name, "
665
+ "handler_canonical_id=excluded.handler_canonical_id, "
666
+ "file_path=excluded.file_path, "
667
+ "line=excluded.line, "
668
+ "evidence=excluded.evidence, "
669
+ "confidence=excluded.confidence",
659
670
  [
660
671
  (
661
672
  r.endpoint_id,
@@ -794,6 +805,7 @@ class Indexer:
794
805
  line=int(r["line"]),
795
806
  evidence=str(r["evidence"]),
796
807
  confidence=str(r["confidence"]),
808
+ endpoint_id_override=str(r["endpoint_id"]),
797
809
  )
798
810
  for r in rt_rows
799
811
  ]
@@ -930,6 +942,20 @@ def check_database_health(con: sqlite3.Connection, repository: Path | None = Non
930
942
  if parser_ver and parser_ver != PARSER_VERSION:
931
943
  issues.append(f"Parser version mismatch: indexed with {parser_ver}, active parser is {PARSER_VERSION}.")
932
944
 
945
+ # 8. Orphan framework routes
946
+ orphan_routes = con.execute(
947
+ "SELECT count(*) FROM framework_routes r LEFT JOIN files f ON r.file_path = f.path WHERE f.path IS NULL"
948
+ ).fetchone()[0]
949
+ if orphan_routes > 0:
950
+ issues.append(f"Found {orphan_routes} orphan route(s) referencing non-existent files.")
951
+
952
+ # 9. Duplicate endpoint IDs
953
+ dup_routes = con.execute(
954
+ "SELECT endpoint_id, count(*) FROM framework_routes GROUP BY endpoint_id HAVING count(*) > 1"
955
+ ).fetchall()
956
+ if dup_routes:
957
+ issues.append(f"Found {len(dup_routes)} duplicate route endpoint ID(s).")
958
+
933
959
  status = "OK" if not issues else "ISSUES_FOUND"
934
960
  return {
935
961
  "status": status,
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: codegraph-engine
3
- Version: 2.1.2
3
+ Version: 2.1.3
4
4
  Summary: Evidence-backed local codebase intelligence for MCP clients
5
5
  Author: CodeGraph contributors
6
6
  License-Expression: MIT
@@ -1,4 +1,4 @@
1
- codegraph/__init__.py,sha256=79b7HvT1to9TpPMt04Kt_qVbBIwZwVr06vQh9ArQxHU,845
1
+ codegraph/__init__.py,sha256=thPpcGX8Jit9lAYlhWDftcMUr5nLgXns6eHeIGUD81Q,845
2
2
  codegraph/agent.py,sha256=We0TWEXSMBBz6t2NQEGPB6gv-2P1IwyCmxoFGPN_CBA,911
3
3
  codegraph/architecture.py,sha256=m6RZgXDMoDkSx8KO0xuQHtz5rT0h5B7Jjh1yVE2H2LI,12069
4
4
  codegraph/audit.py,sha256=j6fFL6b4vKfnAdUYU7goqQBv4ysrxy-ecBJvT8rYoSI,3301
@@ -9,7 +9,7 @@ codegraph/constraints.py,sha256=AR_d07ENmbcDhWmcbruy4DvBYXsEdvSwkatyQ6JO-dE,8554
9
9
  codegraph/context.py,sha256=S_NJ6obPrdmlpA0RO6qD-L06d8sU-UaujzllZ1I2pSI,52219
10
10
  codegraph/epistemic.py,sha256=ShvLKjRBE6FKCBc1oARDji-NIyw3Molyrj3Eu8TzY3g,2465
11
11
  codegraph/errors.py,sha256=uzuXQe1NsOXV94xr0nmjvINPidGiTc9705tKqT928jQ,9967
12
- codegraph/frameworks.py,sha256=ZdBnA0WExyJ0ShgUHxSlB82xHF24wO32b_PReVyqWnk,16165
12
+ codegraph/frameworks.py,sha256=Cdv8NBr0Hb920rZStiZUMZFY-3Whcj2YUHVP2VU-2mE,16491
13
13
  codegraph/freshness.py,sha256=PVV7pLFz2xfDIj2DhLWB85ppn-0GZyxjoglxEdr3GBY,10041
14
14
  codegraph/git.py,sha256=DLFsvuOKiCLiBXMuxRCoMK06y1FaxT_D13pwpIA1Jek,8528
15
15
  codegraph/interrogation.py,sha256=jQ7AQOLJBeWgJe3P1qduYb4toRaDRcM8reB1xtNoT9c,54755
@@ -31,7 +31,7 @@ codegraph/graph/models.py,sha256=qq7RY4CkoDof8GS4cJIznfIB239Wo83yq2cOaIvUrXY,930
31
31
  codegraph/graph/traversal.py,sha256=3gLp1drVLCSRpRVQYtfAmi_6nZOES-pd9C2zE3vfvuA,49848
32
32
  codegraph/indexing/__init__.py,sha256=Svr4c_L0j3neb5WiTcWDYPyqAdvpsuOIBhOAXFvBv1E,149
33
33
  codegraph/indexing/classifier.py,sha256=PKY54vjj2RFk665xXYctIZuzR8OshIfFdzGuOWfuAfQ,7101
34
- codegraph/indexing/indexer.py,sha256=2HEi2DOW3JGm9xnuVXIm6n8sngkvjeCNIu7p3gSxbqY,37908
34
+ codegraph/indexing/indexer.py,sha256=XEOz0C522QJdJypqWnGBXbSlgjfvp-DIDAbM_I_P6bE,39158
35
35
  codegraph/indexing/models.py,sha256=h0ssLYF2Hbw5Ma05Lz4hXnxsoQXCrhZEdvgQHV2YzNU,11612
36
36
  codegraph/indexing/parser.py,sha256=YhR8_xs9gDGO95sw2oq3SfQwwZIw5fla5TjXVc6d4UM,46643
37
37
  codegraph/indexing/scanner.py,sha256=jEbqnDeAtxrNqMKuMHvW63C3U08SxpSzfYEJ3l7B6gU,6375
@@ -55,9 +55,9 @@ codegraph/search/hybrid.py,sha256=pqdRZSwe7wEEETxmUjV5Ns7_oxus60jggnOPNRfFpg0,96
55
55
  codegraph/search/semantic.py,sha256=QZaJVEoOZIZrp4O6SmUAzMiqMPfopgmPSpqzL3T7GVg,836
56
56
  codegraph/security/__init__.py,sha256=QsucVn1YOuC1IFrd9-EHeZd9kdHv8XUQgRZ9bTz_6_4,142
57
57
  codegraph/security/paths.py,sha256=BtiVvDgMzfL7_Dj3COt6B2Aui4A7hH13QwPUgl5-7No,1241
58
- codegraph_engine-2.1.2.dist-info/licenses/LICENSE,sha256=I6wm9APPQhaH4Cj9H9z8I2jahgYh7ik-9x7wFrmsGOo,1079
59
- codegraph_engine-2.1.2.dist-info/METADATA,sha256=1TV7fwB6BD6GdRxajmumnqA-z5iuDRmd9Uslo8b6za4,13309
60
- codegraph_engine-2.1.2.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
61
- codegraph_engine-2.1.2.dist-info/entry_points.txt,sha256=U2xQ3yhqOaaDyFtV9p7N0FDref1VEk56RE_Bnvrnycc,48
62
- codegraph_engine-2.1.2.dist-info/top_level.txt,sha256=RqBj9sPbifZTb9aeHtnbxTgKJvfHIQdmYE1Brv8Wdkg,10
63
- codegraph_engine-2.1.2.dist-info/RECORD,,
58
+ codegraph_engine-2.1.3.dist-info/licenses/LICENSE,sha256=I6wm9APPQhaH4Cj9H9z8I2jahgYh7ik-9x7wFrmsGOo,1079
59
+ codegraph_engine-2.1.3.dist-info/METADATA,sha256=5ZWgJ24vTGtBD7TQ1eOhRr2FlizC9vGNDBplfBCN49s,13309
60
+ codegraph_engine-2.1.3.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
61
+ codegraph_engine-2.1.3.dist-info/entry_points.txt,sha256=U2xQ3yhqOaaDyFtV9p7N0FDref1VEk56RE_Bnvrnycc,48
62
+ codegraph_engine-2.1.3.dist-info/top_level.txt,sha256=RqBj9sPbifZTb9aeHtnbxTgKJvfHIQdmYE1Brv8Wdkg,10
63
+ codegraph_engine-2.1.3.dist-info/RECORD,,