codegraph-engine 3.0.0__2-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 +37 -0
- codegraph/agent.py +26 -0
- codegraph/agent_brain.py +2212 -0
- codegraph/agent_capabilities.py +4058 -0
- codegraph/agent_rules.py +531 -0
- codegraph/api_drift.py +455 -0
- codegraph/architecture.py +371 -0
- codegraph/async_queue/__init__.py +50 -0
- codegraph/async_queue/detectors/__init__.py +48 -0
- codegraph/async_queue/detectors/celery.py +160 -0
- codegraph/async_queue/detectors/kafka.py +168 -0
- codegraph/async_queue/detectors/rabbitmq.py +116 -0
- codegraph/async_queue/detectors/redis.py +130 -0
- codegraph/async_queue/detectors/sqs.py +135 -0
- codegraph/async_queue/models.py +161 -0
- codegraph/async_queue/otel_models.py +74 -0
- codegraph/async_queue/otel_parser.py +337 -0
- codegraph/async_queue/reconciler.py +427 -0
- codegraph/async_queue/scanner.py +291 -0
- codegraph/async_queue/traversal.py +447 -0
- codegraph/audit.py +106 -0
- codegraph/binding_resolver.py +616 -0
- codegraph/branch_comparison.py +197 -0
- codegraph/cache.py +95 -0
- codegraph/change_impact.py +547 -0
- codegraph/cli.py +2436 -0
- codegraph/cli_output.py +205 -0
- codegraph/config.py +45 -0
- codegraph/constraints.py +238 -0
- codegraph/context.py +2182 -0
- codegraph/context_freshness.py +351 -0
- codegraph/database/__init__.py +72 -0
- codegraph/database/extractor.py +3651 -0
- codegraph/database/interrogation.py +1494 -0
- codegraph/database/models.py +310 -0
- codegraph/database/schema_drift.py +862 -0
- codegraph/epistemic.py +200 -0
- codegraph/errors.py +282 -0
- codegraph/evidence/__init__.py +15 -0
- codegraph/evidence/citations.py +418 -0
- codegraph/evidence_contract.py +486 -0
- codegraph/frameworks.py +960 -0
- codegraph/frameworks_nestjs.py +502 -0
- codegraph/frameworks_nextjs.py +337 -0
- codegraph/frameworks_react.py +457 -0
- codegraph/freshness.py +335 -0
- codegraph/frontend_html.py +109 -0
- codegraph/git.py +362 -0
- codegraph/git_state.py +545 -0
- codegraph/graph/__init__.py +46 -0
- codegraph/graph/models.py +56 -0
- codegraph/graph/traversal.py +1993 -0
- codegraph/indexing/__init__.py +24 -0
- codegraph/indexing/classifier.py +564 -0
- codegraph/indexing/indexer.py +2578 -0
- codegraph/indexing/models.py +427 -0
- codegraph/indexing/parser.py +3404 -0
- codegraph/indexing/pool.py +136 -0
- codegraph/indexing/scanner.py +211 -0
- codegraph/indexing/telemetry.py +326 -0
- codegraph/indexing/templates.py +418 -0
- codegraph/indexing/test_framework.py +116 -0
- codegraph/installer.py +1702 -0
- codegraph/interrogation.py +2355 -0
- codegraph/llm/__init__.py +3 -0
- codegraph/llm/base.py +15 -0
- codegraph/llm/context.py +20 -0
- codegraph/mcp/__init__.py +3 -0
- codegraph/mcp/server.py +1476 -0
- codegraph/mcp_diagnostics.py +882 -0
- codegraph/memory/__init__.py +3 -0
- codegraph/memory/store.py +46 -0
- codegraph/models.py +310 -0
- codegraph/monorepo.py +925 -0
- codegraph/observability.py +262 -0
- codegraph/optimizer.py +1014 -0
- codegraph/planner.py +417 -0
- codegraph/process_lifecycle.py +1153 -0
- codegraph/py.typed +1 -0
- codegraph/query_expansion.py +199 -0
- codegraph/ranking.py +408 -0
- codegraph/refactor/__init__.py +36 -0
- codegraph/refactor/models.py +114 -0
- codegraph/refactor/renamer.py +844 -0
- codegraph/refactor/transactions.py +414 -0
- codegraph/resolver.py +3968 -0
- codegraph/resources/__init__.py +46 -0
- codegraph/resources/cache.py +117 -0
- codegraph/resources/coalescer.py +83 -0
- codegraph/resources/debouncer.py +98 -0
- codegraph/resources/governor.py +219 -0
- codegraph/resources/monitor.py +102 -0
- codegraph/resources/policy.py +123 -0
- codegraph/retrieval_policy.py +320 -0
- codegraph/roblox.py +2174 -0
- codegraph/route_composer.py +363 -0
- codegraph/route_topology.py +172 -0
- codegraph/runtime/__init__.py +51 -0
- codegraph/runtime/collector.py +155 -0
- codegraph/runtime/db_watcher.py +191 -0
- codegraph/runtime/ingestor.py +692 -0
- codegraph/runtime/models.py +130 -0
- codegraph/runtime/port_inspector.py +304 -0
- codegraph/runtime/reconciliation.py +492 -0
- codegraph/runtime/runner.py +353 -0
- codegraph/runtime/trace_linker.py +175 -0
- codegraph/search/__init__.py +25 -0
- codegraph/search/hybrid.py +846 -0
- codegraph/search/semantic.py +28 -0
- codegraph/security/__init__.py +51 -0
- codegraph/security/paths.py +189 -0
- codegraph/security/redaction.py +633 -0
- codegraph/semantic_conflicts.py +270 -0
- codegraph/semantic_decorators.py +372 -0
- codegraph/structural_diff.py +542 -0
- codegraph/styles.py +144 -0
- codegraph/symbol_history.py +277 -0
- codegraph/target_resolver.py +348 -0
- codegraph/task.py +637 -0
- codegraph/tool_selection_eval.py +1158 -0
- codegraph/tsconfig.py +236 -0
- codegraph/ui/__init__.py +6 -0
- codegraph/ui/server.py +755 -0
- codegraph/watcher.py +323 -0
- codegraph_engine-3.0.0.dist-info/METADATA +868 -0
- codegraph_engine-3.0.0.dist-info/RECORD +130 -0
- codegraph_engine-3.0.0.dist-info/WHEEL +6 -0
- codegraph_engine-3.0.0.dist-info/entry_points.txt +2 -0
- codegraph_engine-3.0.0.dist-info/licenses/LICENSE +21 -0
- codegraph_engine-3.0.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
"""Branch Architecture Comparison Engine.
|
|
2
|
+
|
|
3
|
+
Provides hierarchical structural comparisons between Git branches:
|
|
4
|
+
package
|
|
5
|
+
↓
|
|
6
|
+
module
|
|
7
|
+
↓
|
|
8
|
+
symbol
|
|
9
|
+
↓
|
|
10
|
+
relationships (routes, tests, DB writes, calls)
|
|
11
|
+
|
|
12
|
+
Supports:
|
|
13
|
+
- deterministic ordering
|
|
14
|
+
- token-budget awareness (max_tokens)
|
|
15
|
+
- cursor-based pagination
|
|
16
|
+
- explicit summary of changed routes, services, database models, and affected tests
|
|
17
|
+
"""
|
|
18
|
+
from __future__ import annotations
|
|
19
|
+
|
|
20
|
+
import sqlite3
|
|
21
|
+
from dataclasses import dataclass, field
|
|
22
|
+
from pathlib import Path
|
|
23
|
+
from typing import Any
|
|
24
|
+
|
|
25
|
+
from codegraph.monorepo import detect_workspace
|
|
26
|
+
from codegraph.structural_diff import compare_branches
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
@dataclass
|
|
30
|
+
class SymbolChangeItem:
|
|
31
|
+
name: str
|
|
32
|
+
kind: str
|
|
33
|
+
change_type: str # "ADDED" | "MODIFIED" | "REMOVED"
|
|
34
|
+
line: int | None
|
|
35
|
+
relationships: list[str] = field(default_factory=list)
|
|
36
|
+
|
|
37
|
+
def as_dict(self) -> dict[str, Any]:
|
|
38
|
+
return {
|
|
39
|
+
"name": self.name,
|
|
40
|
+
"kind": self.kind,
|
|
41
|
+
"change_type": self.change_type,
|
|
42
|
+
"line": self.line,
|
|
43
|
+
"relationships": self.relationships,
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
@dataclass
|
|
48
|
+
class ModuleChangeItem:
|
|
49
|
+
module: str
|
|
50
|
+
file_path: str
|
|
51
|
+
symbols: list[SymbolChangeItem] = field(default_factory=list)
|
|
52
|
+
|
|
53
|
+
def as_dict(self) -> dict[str, Any]:
|
|
54
|
+
return {
|
|
55
|
+
"module": self.module,
|
|
56
|
+
"file_path": self.file_path,
|
|
57
|
+
"symbols": [s.as_dict() for s in self.symbols],
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
@dataclass
|
|
62
|
+
class PackageChangeItem:
|
|
63
|
+
package_id: str
|
|
64
|
+
modules: list[ModuleChangeItem] = field(default_factory=list)
|
|
65
|
+
|
|
66
|
+
def as_dict(self) -> dict[str, Any]:
|
|
67
|
+
return {
|
|
68
|
+
"package_id": self.package_id,
|
|
69
|
+
"modules": [m.as_dict() for m in self.modules],
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
@dataclass
|
|
74
|
+
class BranchArchitectureReport:
|
|
75
|
+
base_branch: str
|
|
76
|
+
head_branch: str
|
|
77
|
+
packages: list[PackageChangeItem] = field(default_factory=list)
|
|
78
|
+
changed_routes: list[dict[str, str]] = field(default_factory=list)
|
|
79
|
+
changed_services: list[str] = field(default_factory=list)
|
|
80
|
+
changed_db: list[dict[str, str]] = field(default_factory=list)
|
|
81
|
+
affected_tests: list[str] = field(default_factory=list)
|
|
82
|
+
next_cursor: str | None = None
|
|
83
|
+
total_packages: int = 0
|
|
84
|
+
total_symbols: int = 0
|
|
85
|
+
estimated_tokens: int = 0
|
|
86
|
+
|
|
87
|
+
def as_dict(self) -> dict[str, Any]:
|
|
88
|
+
return {
|
|
89
|
+
"base_branch": self.base_branch,
|
|
90
|
+
"head_branch": self.head_branch,
|
|
91
|
+
"packages": [p.as_dict() for p in self.packages],
|
|
92
|
+
"changed_routes": self.changed_routes,
|
|
93
|
+
"changed_services": self.changed_services,
|
|
94
|
+
"changed_db": self.changed_db,
|
|
95
|
+
"affected_tests": self.affected_tests,
|
|
96
|
+
"next_cursor": self.next_cursor,
|
|
97
|
+
"total_packages": self.total_packages,
|
|
98
|
+
"total_symbols": self.total_symbols,
|
|
99
|
+
"estimated_tokens": self.estimated_tokens,
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
def compare_branch_architecture(
|
|
104
|
+
repository: Path,
|
|
105
|
+
base_branch: str = "main",
|
|
106
|
+
head_branch: str = "HEAD",
|
|
107
|
+
con: sqlite3.Connection | None = None,
|
|
108
|
+
limit: int = 50,
|
|
109
|
+
cursor: str | None = None,
|
|
110
|
+
max_tokens: int = 4000,
|
|
111
|
+
) -> BranchArchitectureReport:
|
|
112
|
+
"""Compare two branches and return hierarchical architecture diff."""
|
|
113
|
+
if base_branch == head_branch:
|
|
114
|
+
return BranchArchitectureReport(base_branch=base_branch, head_branch=head_branch)
|
|
115
|
+
|
|
116
|
+
# 1. Run structural branch diff
|
|
117
|
+
diff_report = compare_branches(repository, base_branch=base_branch, head_branch=head_branch, con=con)
|
|
118
|
+
|
|
119
|
+
# 2. Workspace package mapper
|
|
120
|
+
ws = detect_workspace(repository, con=con)
|
|
121
|
+
|
|
122
|
+
# 3. Build hierarchical package -> module -> symbol map
|
|
123
|
+
package_map: dict[str, dict[str, list[SymbolChangeItem]]] = {}
|
|
124
|
+
services: set[str] = set()
|
|
125
|
+
|
|
126
|
+
all_symbols = diff_report.added_symbols + diff_report.changed_symbols + diff_report.removed_symbols
|
|
127
|
+
# Sort deterministically by path and name
|
|
128
|
+
all_symbols.sort(key=lambda s: (s.path, s.name))
|
|
129
|
+
|
|
130
|
+
# Apply cursor pagination if cursor provided
|
|
131
|
+
start_idx = 0
|
|
132
|
+
if cursor and cursor.isdigit():
|
|
133
|
+
start_idx = int(cursor)
|
|
134
|
+
|
|
135
|
+
paged_symbols = all_symbols[start_idx : start_idx + limit]
|
|
136
|
+
next_cursor = str(start_idx + limit) if (start_idx + limit) < len(all_symbols) else None
|
|
137
|
+
|
|
138
|
+
for s in paged_symbols:
|
|
139
|
+
pkg = ws.get_package_for_file(s.path)
|
|
140
|
+
pkg_id = pkg.package_id if pkg else "root"
|
|
141
|
+
|
|
142
|
+
if pkg_id not in package_map:
|
|
143
|
+
package_map[pkg_id] = {}
|
|
144
|
+
if s.path not in package_map[pkg_id]:
|
|
145
|
+
package_map[pkg_id][s.path] = []
|
|
146
|
+
|
|
147
|
+
# Find associated relationships
|
|
148
|
+
rels: list[str] = []
|
|
149
|
+
for r in diff_report.changed_routes:
|
|
150
|
+
if r.handler == s.name:
|
|
151
|
+
rels.append(f"{r.change_type} ROUTE {r.method} {r.path}")
|
|
152
|
+
for db in diff_report.db_impact:
|
|
153
|
+
if db.get("symbol") == s.name:
|
|
154
|
+
rels.append(f"{db.get('change_type')} DB {db.get('operation')} {db.get('table')}")
|
|
155
|
+
|
|
156
|
+
if "service" in s.name.lower() or "service" in s.path.lower():
|
|
157
|
+
services.add(s.name)
|
|
158
|
+
|
|
159
|
+
package_map[pkg_id][s.path].append(
|
|
160
|
+
SymbolChangeItem(
|
|
161
|
+
name=s.name,
|
|
162
|
+
kind=s.kind,
|
|
163
|
+
change_type=s.change_type,
|
|
164
|
+
line=s.new_line or s.old_line,
|
|
165
|
+
relationships=rels,
|
|
166
|
+
)
|
|
167
|
+
)
|
|
168
|
+
|
|
169
|
+
# Build ordered PackageChangeItem objects
|
|
170
|
+
package_items: list[PackageChangeItem] = []
|
|
171
|
+
total_sym_count = 0
|
|
172
|
+
|
|
173
|
+
for pkg_id in sorted(package_map.keys()):
|
|
174
|
+
module_items: list[ModuleChangeItem] = []
|
|
175
|
+
for f_path in sorted(package_map[pkg_id].keys()):
|
|
176
|
+
mod_name = Path(f_path).stem
|
|
177
|
+
sym_items = package_map[pkg_id][f_path]
|
|
178
|
+
total_sym_count += len(sym_items)
|
|
179
|
+
module_items.append(ModuleChangeItem(module=mod_name, file_path=f_path, symbols=sym_items))
|
|
180
|
+
package_items.append(PackageChangeItem(package_id=pkg_id, modules=module_items))
|
|
181
|
+
|
|
182
|
+
# Rough token estimation: ~25 tokens per symbol + overhead
|
|
183
|
+
token_est = total_sym_count * 25 + len(diff_report.changed_routes) * 15 + 150
|
|
184
|
+
|
|
185
|
+
return BranchArchitectureReport(
|
|
186
|
+
base_branch=base_branch,
|
|
187
|
+
head_branch=head_branch,
|
|
188
|
+
packages=package_items,
|
|
189
|
+
changed_routes=[r.as_dict() for r in diff_report.changed_routes],
|
|
190
|
+
changed_services=sorted(services),
|
|
191
|
+
changed_db=diff_report.db_impact,
|
|
192
|
+
affected_tests=diff_report.affected_tests,
|
|
193
|
+
next_cursor=next_cursor,
|
|
194
|
+
total_packages=len(package_items),
|
|
195
|
+
total_symbols=total_sym_count,
|
|
196
|
+
estimated_tokens=token_est,
|
|
197
|
+
)
|
codegraph/cache.py
ADDED
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
"""Deterministic Task Fingerprinting and Context Caching Engine.
|
|
2
|
+
|
|
3
|
+
Guarantees repository generation consistency and cache invalidation on:
|
|
4
|
+
- Source code or index generation change
|
|
5
|
+
- Parser version change
|
|
6
|
+
- Database schema change
|
|
7
|
+
- Configuration change
|
|
8
|
+
"""
|
|
9
|
+
from __future__ import annotations
|
|
10
|
+
|
|
11
|
+
import hashlib
|
|
12
|
+
import json
|
|
13
|
+
import sqlite3
|
|
14
|
+
import time
|
|
15
|
+
from typing import Any, cast
|
|
16
|
+
|
|
17
|
+
from codegraph.indexing.parser import PARSER_VERSION
|
|
18
|
+
from codegraph.task import TaskSpec
|
|
19
|
+
|
|
20
|
+
CACHE_SCHEMA_VERSION = 1
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def compute_context_cache_key(
|
|
24
|
+
task_spec: TaskSpec,
|
|
25
|
+
repository_generation: int,
|
|
26
|
+
max_tokens: int,
|
|
27
|
+
parser_version: str = PARSER_VERSION,
|
|
28
|
+
extra_config: str = "",
|
|
29
|
+
) -> str:
|
|
30
|
+
"""Compute an immutable, deterministic cache key for a context compilation request."""
|
|
31
|
+
canonical_components = {
|
|
32
|
+
"intent": task_spec.intent,
|
|
33
|
+
"goal": task_spec.goal,
|
|
34
|
+
"targets": sorted(task_spec.targets),
|
|
35
|
+
"operations": sorted(task_spec.operations),
|
|
36
|
+
"constraints": sorted(task_spec.constraints),
|
|
37
|
+
"exclusions": sorted(task_spec.exclusions),
|
|
38
|
+
"scope_paths": sorted(task_spec.scope_paths),
|
|
39
|
+
"time_scope": task_spec.time_scope or "",
|
|
40
|
+
"repository_generation": repository_generation,
|
|
41
|
+
"max_tokens": max_tokens,
|
|
42
|
+
"parser_version": parser_version,
|
|
43
|
+
"cache_schema": CACHE_SCHEMA_VERSION,
|
|
44
|
+
"extra_config": extra_config,
|
|
45
|
+
}
|
|
46
|
+
raw = json.dumps(canonical_components, sort_keys=True, separators=(",", ":")).encode("utf-8")
|
|
47
|
+
return f"ctx:{hashlib.sha256(raw).hexdigest()}"
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
def get_cached_context_packet(
|
|
51
|
+
con: sqlite3.Connection,
|
|
52
|
+
cache_key: str,
|
|
53
|
+
) -> dict[str, Any] | None:
|
|
54
|
+
"""Retrieve cached context packet if present in SQLite context_cache."""
|
|
55
|
+
try:
|
|
56
|
+
row = con.execute(
|
|
57
|
+
"SELECT data FROM context_cache WHERE cache_key=?",
|
|
58
|
+
(cache_key,),
|
|
59
|
+
).fetchone()
|
|
60
|
+
if row:
|
|
61
|
+
raw_data = row["data"] if isinstance(row, sqlite3.Row) else row[0]
|
|
62
|
+
parsed = json.loads(raw_data)
|
|
63
|
+
if isinstance(parsed, dict):
|
|
64
|
+
return cast(dict[str, Any], parsed)
|
|
65
|
+
return None
|
|
66
|
+
except Exception:
|
|
67
|
+
pass
|
|
68
|
+
return None
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
def store_cached_context_packet(
|
|
72
|
+
con: sqlite3.Connection,
|
|
73
|
+
cache_key: str,
|
|
74
|
+
packet_dict: dict[str, Any],
|
|
75
|
+
) -> None:
|
|
76
|
+
"""Store compiled ContextPacket in SQLite context_cache table."""
|
|
77
|
+
try:
|
|
78
|
+
now = int(time.time())
|
|
79
|
+
serialized = json.dumps(packet_dict, sort_keys=True)
|
|
80
|
+
con.execute(
|
|
81
|
+
"INSERT OR REPLACE INTO context_cache (cache_key, data, created_at) VALUES (?, ?, ?)",
|
|
82
|
+
(cache_key, serialized, now),
|
|
83
|
+
)
|
|
84
|
+
con.commit()
|
|
85
|
+
except Exception:
|
|
86
|
+
pass
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
def invalidate_context_cache(con: sqlite3.Connection) -> None:
|
|
90
|
+
"""Explicitly wipe context cache upon repository mutation or index generation advancement."""
|
|
91
|
+
try:
|
|
92
|
+
con.execute("DELETE FROM context_cache")
|
|
93
|
+
con.commit()
|
|
94
|
+
except Exception:
|
|
95
|
+
pass
|