java-codebase-rag 0.11.2__py3-none-any.whl → 0.12.1__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 (73) hide show
  1. java_codebase_rag-0.12.1.dist-info/METADATA +35 -0
  2. java_codebase_rag-0.12.1.dist-info/RECORD +4 -0
  3. {java_codebase_rag-0.11.2.dist-info → java_codebase_rag-0.12.1.dist-info}/WHEEL +1 -1
  4. java_codebase_rag/_fdlimit.py +0 -56
  5. java_codebase_rag/_stdio.py +0 -32
  6. java_codebase_rag/_version.py +0 -35
  7. java_codebase_rag/absence/__init__.py +0 -0
  8. java_codebase_rag/absence/absence_diagnosis.py +0 -700
  9. java_codebase_rag/absence/absence_types.py +0 -124
  10. java_codebase_rag/absence/absence_vocab.py +0 -460
  11. java_codebase_rag/analysis/__init__.py +0 -0
  12. java_codebase_rag/analysis/pr_analysis.py +0 -563
  13. java_codebase_rag/analysis/resolve_service.py +0 -740
  14. java_codebase_rag/ast/__init__.py +0 -0
  15. java_codebase_rag/ast/ast_java.py +0 -2825
  16. java_codebase_rag/ast/brownfield_events.py +0 -58
  17. java_codebase_rag/ast/chunk_heuristics.py +0 -62
  18. java_codebase_rag/cli.py +0 -1215
  19. java_codebase_rag/cli_format.py +0 -85
  20. java_codebase_rag/cli_progress.py +0 -94
  21. java_codebase_rag/config.py +0 -833
  22. java_codebase_rag/eval/__init__.py +0 -1
  23. java_codebase_rag/eval/ground_truth.py +0 -100
  24. java_codebase_rag/eval/metrics.py +0 -107
  25. java_codebase_rag/eval/runner.py +0 -556
  26. java_codebase_rag/graph/__init__.py +0 -0
  27. java_codebase_rag/graph/build_ast_graph.py +0 -4471
  28. java_codebase_rag/graph/graph_enrich.py +0 -1937
  29. java_codebase_rag/graph/graph_types.py +0 -224
  30. java_codebase_rag/graph/java_ontology.py +0 -465
  31. java_codebase_rag/graph/ladybug_queries.py +0 -2213
  32. java_codebase_rag/graph/path_filtering.py +0 -477
  33. java_codebase_rag/index/__init__.py +0 -0
  34. java_codebase_rag/index/java_index_flow_lancedb.py +0 -734
  35. java_codebase_rag/index/java_index_v1_common.py +0 -33
  36. java_codebase_rag/install_data/__init__.py +0 -0
  37. java_codebase_rag/install_data/agents/explorer-rag-cli.md +0 -108
  38. java_codebase_rag/install_data/agents/explorer-rag-enhanced.md +0 -152
  39. java_codebase_rag/install_data/skills/explore-codebase/SKILL.md +0 -165
  40. java_codebase_rag/install_data/skills/explore-codebase-cli/SKILL.md +0 -107
  41. java_codebase_rag/installer.py +0 -2188
  42. java_codebase_rag/jrag.py +0 -4531
  43. java_codebase_rag/jrag_envelope.py +0 -1107
  44. java_codebase_rag/jrag_hints.py +0 -204
  45. java_codebase_rag/jrag_render.py +0 -926
  46. java_codebase_rag/lance_optimize.py +0 -264
  47. java_codebase_rag/mcp/__init__.py +0 -0
  48. java_codebase_rag/mcp/mcp_hints.py +0 -932
  49. java_codebase_rag/mcp/mcp_v2.py +0 -1916
  50. java_codebase_rag/mcp/server.py +0 -884
  51. java_codebase_rag/pipeline.py +0 -531
  52. java_codebase_rag/progress.py +0 -570
  53. java_codebase_rag/read_payloads.py +0 -781
  54. java_codebase_rag/search/__init__.py +0 -0
  55. java_codebase_rag/search/index_common.py +0 -10
  56. java_codebase_rag/search/search_lancedb.py +0 -1296
  57. java_codebase_rag/search/search_lexical.py +0 -449
  58. java_codebase_rag/search/search_scoring.py +0 -523
  59. java_codebase_rag/watch/__init__.py +0 -0
  60. java_codebase_rag/watch/client.py +0 -230
  61. java_codebase_rag/watch/daemon.py +0 -396
  62. java_codebase_rag/watch/lock.py +0 -201
  63. java_codebase_rag/watch/paths.py +0 -76
  64. java_codebase_rag/watch/protocol.py +0 -122
  65. java_codebase_rag/watch/server.py +0 -273
  66. java_codebase_rag/watch/warm.py +0 -105
  67. java_codebase_rag/watch/watcher.py +0 -370
  68. java_codebase_rag-0.11.2.dist-info/METADATA +0 -331
  69. java_codebase_rag-0.11.2.dist-info/RECORD +0 -71
  70. java_codebase_rag-0.11.2.dist-info/entry_points.txt +0 -4
  71. java_codebase_rag-0.11.2.dist-info/licenses/LICENSE +0 -21
  72. java_codebase_rag-0.11.2.dist-info/top_level.txt +0 -1
  73. /java_codebase_rag/__init__.py → /java_codebase_rag-0.12.1.dist-info/top_level.txt +0 -0
@@ -1,224 +0,0 @@
1
- """Shared graph types and helpers used by mcp_v2 and resolve_service.
2
-
3
- This is the neutral, acyclic shared module. It must NOT import from
4
- ``mcp_v2`` or ``resolve_service`` — both of those import FROM here.
5
- """
6
-
7
- from __future__ import annotations
8
-
9
- from typing import Any, Literal
10
-
11
- from pydantic import BaseModel
12
-
13
- from java_codebase_rag.graph.ladybug_queries import LadybugGraph
14
- from java_codebase_rag.mcp.mcp_hints import generate_hints
15
-
16
- __all__ = [
17
- "NodeRef",
18
- "StructuredHint",
19
- "set_hints_enabled",
20
- "_hints_or_skip",
21
- "_node_kind_from_id",
22
- "_resolve_node_kind",
23
- "_node_ref_from_row",
24
- "_to_structured_hints",
25
- ]
26
-
27
-
28
- class NodeRef(BaseModel):
29
- id: str
30
- kind: Literal["symbol", "route", "client", "producer", "unresolved_call_site"]
31
- fqn: str
32
- name: str | None = None
33
- symbol_kind: str | None = None
34
- microservice: str | None = None
35
- module: str | None = None
36
- role: str | None = None
37
- generated: bool | None = None
38
- generated_by: str | None = None
39
- # Identity-adjacent fields consumed by ``jrag_envelope.node_key`` (keying)
40
- # and ``project_node`` allow-lists (rendering) so find filter-mode nodes
41
- # carry the same rich shape as the dedicated listings (http-routes /
42
- # http-clients / producers). All optional with default None: existing
43
- # NodeRef constructors are unaffected and ``_drop_empty`` strips unset
44
- # fields at the JSON boundary.
45
- method: str | None = None
46
- path: str | None = None
47
- framework: str | None = None
48
- member_fqn: str | None = None
49
- target_service: str | None = None
50
- client_kind: str | None = None
51
- topic: str | None = None
52
- broker: str | None = None
53
- producer_kind: str | None = None
54
- filename: str | None = None
55
- start_line: int | None = None
56
- resolved: bool | None = None
57
-
58
-
59
- class StructuredHint(BaseModel):
60
- label: str = ""
61
- tool: Literal["search", "find", "describe", "neighbors", "resolve"]
62
- args: dict[str, Any]
63
- actionable: bool = True
64
- reason: str = ""
65
-
66
-
67
- # Module-level flag set by server.py at startup from resolved config.
68
- # Single source of truth — both mcp_v2 and resolve_service read this via
69
- # _hints_or_skip, and server.py sets it via set_hints_enabled (re-exported
70
- # by mcp_v2 for back-comat).
71
- _hints_enabled: bool = True
72
-
73
-
74
- def set_hints_enabled(enabled: bool) -> None:
75
- global _hints_enabled
76
- _hints_enabled = enabled
77
-
78
-
79
- def _hints_or_skip(tool: str, payload: dict) -> tuple[list, list]:
80
- return generate_hints(tool, payload) if _hints_enabled else ([], [])
81
-
82
-
83
- def _node_kind_from_id(
84
- id_str: str,
85
- ) -> Literal["symbol", "route", "client", "producer", "unresolved_call_site"]:
86
- if id_str.startswith("ucs:"):
87
- return "unresolved_call_site"
88
- if id_str.startswith("sym:"):
89
- return "symbol"
90
- if id_str.startswith("route:") or id_str.startswith("r:"):
91
- return "route"
92
- if id_str.startswith("client:") or id_str.startswith("c:"):
93
- return "client"
94
- if id_str.startswith("producer:") or id_str.startswith("p:"):
95
- return "producer"
96
- raise ValueError(f"Unknown id prefix for `{id_str}`")
97
-
98
-
99
- def _resolve_node_kind(
100
- graph: LadybugGraph,
101
- node_id: str,
102
- ) -> Literal["symbol", "route", "client", "producer", "unresolved_call_site"]:
103
- try:
104
- return _node_kind_from_id(node_id)
105
- except ValueError:
106
- pass
107
- if graph._rows("MATCH (n:Symbol) WHERE n.id = $id RETURN n.id AS id LIMIT 1", {"id": node_id}): # noqa: SLF001
108
- return "symbol"
109
- if graph._rows("MATCH (n:Route) WHERE n.id = $id RETURN n.id AS id LIMIT 1", {"id": node_id}): # noqa: SLF001
110
- return "route"
111
- if graph._rows("MATCH (n:Client) WHERE n.id = $id RETURN n.id AS id LIMIT 1", {"id": node_id}): # noqa: SLF001
112
- return "client"
113
- if graph._rows("MATCH (n:Producer) WHERE n.id = $id RETURN n.id AS id LIMIT 1", {"id": node_id}): # noqa: SLF001
114
- return "producer"
115
- raise ValueError(f"Unknown id prefix for `{node_id}`")
116
-
117
-
118
- def _node_ref_from_row(kind: Literal["symbol", "route", "client", "producer"], row: dict[str, Any]) -> NodeRef:
119
- """Map a graph store row to a :class:`NodeRef`.
120
-
121
- ``fqn`` is set to each kind's documented natural identifier (README
122
- §"jrag — agent CLI") so ``jrag_envelope.node_key`` (which checks ``fqn``
123
- first) keys nodes correctly and no raw graph id leaks:
124
-
125
- * symbol -> symbol fqn
126
- * route -> ``"METHOD path"`` (HTTP endpoint); ``"topic:<name>"`` when a
127
- kafka topic surfaces as :Route; ``""`` for a phantom route
128
- (node_key then falls through to the composed ``file``)
129
- * client -> ``"member_fqn->target_service"``
130
- * producer-> ``"topic:<name>"``
131
-
132
- Rich detail (member_fqn / target_service / method / path / topic /
133
- framework / filename / start_line / resolved) is populated alongside so
134
- find filter-mode nodes render with the same shape as the dedicated
135
- listings (``http-routes`` / ``http-clients`` / ``producers``) instead of
136
- collapsing to ``{"kind": ...}`` after the envelope's projection+drop-empty.
137
- """
138
- microservice = str(row.get("microservice") or "") or None
139
- module = str(row.get("module") or "") or None
140
- filename = str(row.get("filename") or "") or None
141
- start_line = row.get("start_line")
142
- try:
143
- start_line = int(start_line) if start_line not in (None, "") else None
144
- except (TypeError, ValueError):
145
- start_line = None
146
- resolved_raw = row.get("resolved")
147
- resolved = bool(resolved_raw) if resolved_raw is not None else None
148
- nid = str(row.get("id") or "")
149
-
150
- if kind == "symbol":
151
- fqn = str(row.get("fqn") or "")
152
- role = str(row.get("role") or "") or None
153
- symbol_kind_val = str(row.get("symbol_kind") or row.get("kind") or "").strip()
154
- symbol_kind = symbol_kind_val or None
155
- return NodeRef(
156
- id=nid, kind="symbol", fqn=fqn,
157
- name=str(row.get("name") or "") or None,
158
- symbol_kind=symbol_kind,
159
- microservice=microservice, module=module, role=role,
160
- filename=filename, start_line=start_line,
161
- generated=bool(row.get("generated")) if row.get("generated") is not None else None,
162
- generated_by=str(row.get("generated_by")) if row.get("generated_by") else None,
163
- )
164
-
165
- if kind == "route":
166
- method = str(row.get("method") or "")
167
- path = str(row.get("path_template") or row.get("path") or "")
168
- topic = str(row.get("topic") or "") or None
169
- if method or path:
170
- fqn = f"{method} {path}".strip()
171
- elif topic:
172
- fqn = f"topic:{topic}"
173
- else:
174
- fqn = ""
175
- return NodeRef(
176
- id=nid, kind="route", fqn=fqn, name=(path or topic),
177
- method=method or None, path=path or None, topic=topic,
178
- framework=str(row.get("framework") or "") or None,
179
- microservice=microservice, module=module,
180
- filename=filename, start_line=start_line, resolved=resolved,
181
- )
182
-
183
- if kind == "client":
184
- mfqn = str(row.get("member_fqn") or "")
185
- tgt = str(row.get("target_service") or "")
186
- method = str(row.get("method") or "")
187
- path = str(row.get("path_template") or row.get("path") or "")
188
- member_fqn = mfqn or None
189
- target_service = tgt or None
190
- member_simple = (mfqn.rsplit(".", 1)[-1] if mfqn else "") or None
191
- # Build the contract id ``member_fqn->target_service`` from the RAW
192
- # strings: ``member_fqn`` was normalized to None above, so interpolating
193
- # it would emit ``"None-><target>"`` for member-less (brownfield/meta)
194
- # clients. Fall back to whichever half is present; never a dangling arrow.
195
- fqn = f"{mfqn}->{tgt}" if (mfqn and tgt) else (mfqn or tgt)
196
- return NodeRef(
197
- id=nid, kind="client",
198
- fqn=fqn,
199
- name=member_simple,
200
- member_fqn=member_fqn, target_service=target_service,
201
- method=method or None, path=path or None,
202
- client_kind=str(row.get("client_kind") or "") or None,
203
- microservice=microservice, module=module,
204
- filename=filename, start_line=start_line, resolved=resolved,
205
- )
206
-
207
- # producer
208
- topic = str(row.get("topic") or "") or None
209
- member_fqn = str(row.get("member_fqn") or "") or None
210
- member_simple = (member_fqn.rsplit(".", 1)[-1] if member_fqn else "") or None
211
- return NodeRef(
212
- id=nid, kind="producer",
213
- fqn=(f"topic:{topic}" if topic else ""),
214
- name=(topic or member_simple),
215
- topic=topic, broker=str(row.get("broker") or "") or None,
216
- producer_kind=str(row.get("producer_kind") or "") or None,
217
- member_fqn=member_fqn,
218
- microservice=microservice, module=module,
219
- filename=filename, start_line=start_line, resolved=resolved,
220
- )
221
-
222
-
223
- def _to_structured_hints(raw: list[Any]) -> list[StructuredHint]:
224
- return [StructuredHint(label=h.label, tool=h.tool, args=h.args, actionable=h.actionable, reason=h.reason) for h in raw]
@@ -1,465 +0,0 @@
1
- """Shared valid role and capability label sets for Java indexers and MCP.
2
-
3
- Used by `ast_java` inference, brownfield config validation in `graph_enrich`,
4
- and resolver steps for `@CodebaseRole` / `@CodebaseCapability`."""
5
- from __future__ import annotations
6
-
7
- from dataclasses import dataclass
8
- from typing import Literal
9
-
10
- from java_codebase_rag.ast.ast_java import (
11
- ROLE_ANNOTATIONS,
12
- _INJECTED_TYPES_TO_CAPABILITY,
13
- _METHOD_ANN_TO_CAPABILITY,
14
- _SUPERTYPE_TO_CAPABILITY,
15
- _TYPE_ANN_TO_CAPABILITY,
16
- )
17
-
18
- # Roles assignable by indexing: Spring stereotype values plus DTO. ``OTHER`` is the
19
- # built-in inference fallback (ast_java.infer_role when nothing matches) and is
20
- # deliberately excluded here — it is a read-side value (the mcp_v2 ``Role`` enum
21
- # includes it) but not a role a user may set via @CodebaseRole / role_overrides.
22
- VALID_ROLES: frozenset[str] = frozenset((*ROLE_ANNOTATIONS.values(), "DTO"))
23
-
24
- VALID_CAPABILITIES: frozenset[str] = frozenset(
25
- {
26
- *_METHOD_ANN_TO_CAPABILITY.values(),
27
- *_TYPE_ANN_TO_CAPABILITY.values(),
28
- *_INJECTED_TYPES_TO_CAPABILITY.values(),
29
- *_SUPERTYPE_TO_CAPABILITY.values(),
30
- }
31
- )
32
-
33
- VALID_ROUTE_FRAMEWORKS: frozenset[str] = frozenset((
34
- "spring_mvc",
35
- "webflux",
36
- ))
37
-
38
- VALID_ROUTE_KINDS: frozenset[str] = frozenset((
39
- "http_endpoint",
40
- "http_consumer",
41
- "kafka_topic",
42
- "rabbit_queue",
43
- "jms_destination",
44
- "stream_binding",
45
- ))
46
-
47
- VALID_CLIENT_KINDS: frozenset[str] = frozenset((
48
- "feign_method",
49
- "rest_template",
50
- "web_client",
51
- ))
52
- # Named members of VALID_CLIENT_KINDS — reference these at emit/match sites so a
53
- # rename in the set above cannot silently desync callers (issue #359).
54
- CLIENT_KIND_FEIGN_METHOD = "feign_method"
55
- CLIENT_KIND_REST_TEMPLATE = "rest_template"
56
- CLIENT_KIND_WEB_CLIENT = "web_client"
57
-
58
- VALID_PRODUCER_KINDS: frozenset[str] = frozenset((
59
- "kafka_send",
60
- "stream_bridge_send",
61
- ))
62
-
63
- VALID_HTTP_CALL_STRATEGIES: frozenset[str] = frozenset((
64
- "feign_method",
65
- "rest_template",
66
- "web_client",
67
- "unresolved",
68
- ))
69
-
70
- VALID_ASYNC_CALL_STRATEGIES: frozenset[str] = frozenset((
71
- "kafka_template",
72
- "stream_bridge",
73
- "rabbit_template",
74
- "jms_template",
75
- "unresolved",
76
- ))
77
-
78
- VALID_HTTP_CALL_MATCHES: frozenset[str] = frozenset((
79
- "cross_service",
80
- "intra_service",
81
- "ambiguous",
82
- "phantom",
83
- "unresolved",
84
- ))
85
-
86
- VALID_RESOLVE_REASONS: frozenset[str] = frozenset((
87
- "exact_id",
88
- "exact_fqn",
89
- "fqn_suffix",
90
- "short_name",
91
- "route_template",
92
- "route_method_path",
93
- "route_topic",
94
- "route_topic_prefix",
95
- "client_target",
96
- "client_target_path",
97
- "client_name",
98
- "client_fqn",
99
- "producer_topic",
100
- "producer_topic_prefix",
101
- ))
102
-
103
- # Brownfield / fallback edge resolution strategies (hints v2 neighbors fuzzy signal).
104
- # ``phantom`` / ``chained_receiver`` are not CALLS edge strategies after PR-3 (receiver
105
- # failures live on ``UnresolvedCallSite``); they remain on HTTP/ASYNC match literals only.
106
- FUZZY_STRATEGY_SET: frozenset[str] = frozenset({
107
- "layer_c_source",
108
- "layer_b_fqn",
109
- "overload_ambiguous",
110
- "implicit_super",
111
- })
112
-
113
- VALID_UNRESOLVED_CALL_REASONS: frozenset[str] = frozenset({
114
- "phantom_unresolved_receiver",
115
- "chained_receiver",
116
- })
117
-
118
- # Union of fuzzy + non-fuzzy resolver strategies that may appear on graph edges
119
- # carrying a `strategy` column (brownfield layers, codebase stubs, call-graph tiers,
120
- # HTTP/async dispatch literals). Used by `EdgeSpec.brownfield_resolver_sourced`.
121
- BROWNFIELD_RESOLVER_STRATEGY_SET: frozenset[str] = frozenset({
122
- *FUZZY_STRATEGY_SET,
123
- # Receiver-tier / HTTP match literals — not CALLS edge strategies after PR-3 UCS facet.
124
- "phantom",
125
- "chained_receiver",
126
- "layer_b_ann",
127
- "layer_a_meta",
128
- "codebase_route",
129
- "codebase_client",
130
- "codebase_producer",
131
- "annotation",
132
- "spel",
133
- "constant_ref",
134
- *VALID_HTTP_CALL_STRATEGIES,
135
- *VALID_ASYNC_CALL_STRATEGIES,
136
- *VALID_CLIENT_KINDS,
137
- *VALID_PRODUCER_KINDS,
138
- "import_map",
139
- "static_import",
140
- "static_import_wildcard",
141
- "constructor",
142
- "method_reference",
143
- "this_super",
144
- "unique_type_name",
145
- "suffix",
146
- "same_module",
147
- })
148
-
149
- NodeKind = Literal["Symbol", "Route", "Client", "Producer"]
150
- Cardinality = Literal["many_to_many", "many_to_one", "one_to_many", "one_to_one"]
151
-
152
-
153
- @dataclass(frozen=True)
154
- class EdgeAttr:
155
- name: str
156
- graph_type: str
157
- purpose: str
158
-
159
-
160
- @dataclass(frozen=True)
161
- class EdgeSpec:
162
- name: str
163
- src: NodeKind
164
- dst: NodeKind
165
- cardinality: Cardinality
166
- brownfield_resolver_sourced: bool
167
- attrs: tuple[EdgeAttr, ...]
168
- purpose: str
169
- typical_traversals: dict[str, str]
170
- member_only: bool = False
171
-
172
-
173
- _SYMBOL_TYPE_TRAVERSAL = (
174
- "neighbors(['{id}'],'out',['DECLARES']) "
175
- "then neighbors(member_ids,'{direction}',['{edge}'])"
176
- )
177
-
178
- _COMPOSED_MEMBER_TYPE_TRAVERSAL = (
179
- "neighbors(['{id}'],'out',['DECLARES.{edge}']) — or "
180
- "neighbors(['{id}'],'out',['DECLARES']) then neighbors(member_ids,'{direction}',['{edge}'])"
181
- )
182
-
183
- EDGE_SCHEMA: dict[str, EdgeSpec] = {
184
- "EXTENDS": EdgeSpec(
185
- name="EXTENDS",
186
- src="Symbol",
187
- dst="Symbol",
188
- cardinality="many_to_one",
189
- brownfield_resolver_sourced=False,
190
- attrs=(
191
- EdgeAttr("dst_name", "STRING", "raw supertype name as written in source"),
192
- EdgeAttr("dst_fqn", "STRING", "best-effort resolved FQN of the supertype"),
193
- EdgeAttr("resolved", "BOOLEAN", "True iff dst_fqn was resolved to an in-graph Symbol"),
194
- ),
195
- purpose="class or interface direct supertype relation",
196
- typical_traversals={
197
- "type_subject": _SYMBOL_TYPE_TRAVERSAL.format(id="{id}", direction="{direction}", edge="EXTENDS"),
198
- "member_subject": "neighbors(['{id}'],'out',['EXTENDS'])",
199
- "alien_subject": "EXTENDS connects Symbol → Symbol; use a type or member Symbol id",
200
- },
201
- ),
202
- "IMPLEMENTS": EdgeSpec(
203
- name="IMPLEMENTS",
204
- src="Symbol",
205
- dst="Symbol",
206
- cardinality="many_to_many",
207
- brownfield_resolver_sourced=False,
208
- attrs=(
209
- EdgeAttr("dst_name", "STRING", "raw interface name as written in source"),
210
- EdgeAttr("dst_fqn", "STRING", "best-effort resolved FQN of the interface"),
211
- EdgeAttr("resolved", "BOOLEAN", "True iff dst_fqn was resolved to an in-graph Symbol"),
212
- ),
213
- purpose="class implements interface relation",
214
- typical_traversals={
215
- "type_subject": _SYMBOL_TYPE_TRAVERSAL.format(id="{id}", direction="{direction}", edge="IMPLEMENTS"),
216
- "member_subject": "neighbors(['{id}'],'out',['IMPLEMENTS'])",
217
- "alien_subject": "IMPLEMENTS connects Symbol → Symbol; use a type or member Symbol id",
218
- },
219
- ),
220
- "INJECTS": EdgeSpec(
221
- name="INJECTS",
222
- src="Symbol",
223
- dst="Symbol",
224
- cardinality="many_to_many",
225
- brownfield_resolver_sourced=False,
226
- attrs=(
227
- EdgeAttr("dst_name", "STRING", "raw injected type name as written in source"),
228
- EdgeAttr("dst_fqn", "STRING", "best-effort resolved FQN of the injected type"),
229
- EdgeAttr("resolved", "BOOLEAN", "True iff dst_fqn was resolved to an in-graph Symbol"),
230
- EdgeAttr("mechanism", "STRING", "injection mechanism literal (constructor, field, setter, …)"),
231
- EdgeAttr("annotation", "STRING", "injection annotation simple name when present"),
232
- EdgeAttr("field_or_param", "STRING", "field or parameter name for the injection site"),
233
- ),
234
- purpose="dependency injection edge from declaring type to injected type",
235
- typical_traversals={
236
- "type_subject": _SYMBOL_TYPE_TRAVERSAL.format(id="{id}", direction="{direction}", edge="INJECTS"),
237
- "member_subject": "neighbors(['{id}'],'in',['INJECTS'])",
238
- "alien_subject": "INJECTS connects Symbol → Symbol; use a type Symbol id",
239
- },
240
- ),
241
- "DECLARES": EdgeSpec(
242
- name="DECLARES",
243
- src="Symbol",
244
- dst="Symbol",
245
- cardinality="one_to_many",
246
- brownfield_resolver_sourced=False,
247
- attrs=(),
248
- purpose="type declares member Symbol (method, constructor, nested type)",
249
- typical_traversals={
250
- "type_subject": "neighbors(['{id}'],'out',['DECLARES'])",
251
- "member_subject": "neighbors(['{id}'],'in',['DECLARES'])",
252
- "alien_subject": "DECLARES connects Symbol → Symbol; use a type Symbol id for outbound members",
253
- },
254
- ),
255
- "OVERRIDES": EdgeSpec(
256
- name="OVERRIDES",
257
- src="Symbol",
258
- dst="Symbol",
259
- cardinality="many_to_one",
260
- brownfield_resolver_sourced=False,
261
- attrs=(),
262
- purpose="subtype method overrides supertype declared method with matching signature",
263
- member_only=True,
264
- typical_traversals={
265
- "type_subject": _SYMBOL_TYPE_TRAVERSAL.format(id="{id}", direction="{direction}", edge="OVERRIDES"),
266
- "member_subject": "neighbors(['{id}'],'out',['OVERRIDES'])",
267
- "alien_subject": "OVERRIDES connects method Symbol → method Symbol",
268
- },
269
- ),
270
- "CALLS": EdgeSpec(
271
- name="CALLS",
272
- src="Symbol",
273
- dst="Symbol",
274
- cardinality="many_to_many",
275
- brownfield_resolver_sourced=True,
276
- attrs=(
277
- EdgeAttr("call_site_line", "INT64", "source line of the call site"),
278
- EdgeAttr("call_site_byte", "INT64", "source byte offset of the call site"),
279
- EdgeAttr("arg_count", "INT64", "argument count at the call site (-1 for method references)"),
280
- EdgeAttr("confidence", "DOUBLE", "resolver confidence in [0.0, 1.0]"),
281
- EdgeAttr("strategy", "STRING", "call-graph resolution strategy literal"),
282
- EdgeAttr("source", "STRING", "call-graph source tag"),
283
- EdgeAttr("resolved", "BOOLEAN", "True iff callee Symbol was resolved in-graph"),
284
- EdgeAttr(
285
- "callee_declaring_role",
286
- "STRING",
287
- "role of the Symbol that declares the callee method",
288
- ),
289
- ),
290
- purpose="intra-codebase method call from caller method to callee method",
291
- member_only=True,
292
- typical_traversals={
293
- "type_subject": _SYMBOL_TYPE_TRAVERSAL.format(id="{id}", direction="{direction}", edge="CALLS"),
294
- "member_subject": "neighbors(['{id}'],'out',['CALLS'])",
295
- "alien_subject": "CALLS connects method Symbol → method Symbol",
296
- },
297
- ),
298
- "EXPOSES": EdgeSpec(
299
- name="EXPOSES",
300
- src="Symbol",
301
- dst="Route",
302
- cardinality="one_to_one",
303
- brownfield_resolver_sourced=True,
304
- attrs=(
305
- EdgeAttr("confidence", "DOUBLE", "route extraction confidence in [0.0, 1.0]"),
306
- EdgeAttr("strategy", "STRING", "route resolution strategy literal"),
307
- ),
308
- purpose="declaring method exposes an inbound HTTP or messaging Route",
309
- member_only=True,
310
- typical_traversals={
311
- "type_subject": _SYMBOL_TYPE_TRAVERSAL.format(id="{id}", direction="{direction}", edge="EXPOSES"),
312
- "member_subject": "neighbors(['{id}'],'out',['EXPOSES'])",
313
- "alien_subject": "EXPOSES connects method Symbol → Route; use a method Symbol id",
314
- },
315
- ),
316
- "DECLARES_CLIENT": EdgeSpec(
317
- name="DECLARES_CLIENT",
318
- src="Symbol",
319
- dst="Client",
320
- cardinality="one_to_many",
321
- brownfield_resolver_sourced=True,
322
- attrs=(
323
- EdgeAttr("confidence", "DOUBLE", "client declaration confidence in [0.0, 1.0]"),
324
- EdgeAttr("strategy", "STRING", "client resolution strategy literal"),
325
- ),
326
- purpose="method declares an outbound HTTP client call site",
327
- member_only=True,
328
- typical_traversals={
329
- "type_subject": _SYMBOL_TYPE_TRAVERSAL.format(
330
- id="{id}", direction="{direction}", edge="DECLARES_CLIENT",
331
- ),
332
- "member_subject": "neighbors(['{id}'],'out',['DECLARES_CLIENT'])",
333
- "alien_subject": "DECLARES_CLIENT connects method Symbol → Client",
334
- },
335
- ),
336
- "DECLARES_PRODUCER": EdgeSpec(
337
- name="DECLARES_PRODUCER",
338
- src="Symbol",
339
- dst="Producer",
340
- cardinality="one_to_many",
341
- brownfield_resolver_sourced=True,
342
- attrs=(
343
- EdgeAttr("confidence", "DOUBLE", "producer declaration confidence in [0.0, 1.0]"),
344
- EdgeAttr("strategy", "STRING", "producer resolution strategy literal"),
345
- ),
346
- purpose="method declares an outbound async producer call site",
347
- member_only=True,
348
- typical_traversals={
349
- "type_subject": _SYMBOL_TYPE_TRAVERSAL.format(
350
- id="{id}", direction="{direction}", edge="DECLARES_PRODUCER",
351
- ),
352
- "member_subject": "neighbors(['{id}'],'out',['DECLARES_PRODUCER'])",
353
- "alien_subject": "DECLARES_PRODUCER connects method Symbol → Producer",
354
- },
355
- ),
356
- "HTTP_CALLS": EdgeSpec(
357
- name="HTTP_CALLS",
358
- src="Client",
359
- dst="Route",
360
- cardinality="many_to_many",
361
- brownfield_resolver_sourced=True,
362
- attrs=(
363
- EdgeAttr("confidence", "DOUBLE", "pass6 match confidence in [0.0, 1.0]"),
364
- EdgeAttr("strategy", "STRING", "HTTP call resolution strategy literal"),
365
- EdgeAttr("method_call", "STRING", "HTTP method of the call site"),
366
- EdgeAttr("raw_uri", "STRING", "uninterpolated URI template from the call site"),
367
- EdgeAttr("match", "STRING", "cross_service|intra_service|ambiguous|phantom|unresolved"),
368
- ),
369
- purpose="resolved HTTP call from a declared Client to a target route",
370
- typical_traversals={
371
- "type_subject": (
372
- "neighbors(['{id}'],'out',['DECLARES']) "
373
- "then neighbors(member_ids,'out',['DECLARES_CLIENT']) "
374
- "then neighbors(client_ids,'out',['HTTP_CALLS'])"
375
- ),
376
- "member_subject": (
377
- "neighbors(['{id}'],'out',['DECLARES_CLIENT']) "
378
- "then neighbors(client_ids,'out',['HTTP_CALLS'])"
379
- ),
380
- "route_subject": (
381
- "neighbors(['{id}'],'in',['HTTP_CALLS']) "
382
- "then neighbors(client_ids,'in',['DECLARES_CLIENT']) for declaring method"
383
- ),
384
- "alien_subject": (
385
- "HTTP_CALLS connects Client→Route; use DECLARES_CLIENT from a method Symbol, "
386
- "or neighbors(client_id,'out',['HTTP_CALLS']) from a Client id"
387
- ),
388
- },
389
- ),
390
- "ASYNC_CALLS": EdgeSpec(
391
- name="ASYNC_CALLS",
392
- src="Producer",
393
- dst="Route",
394
- cardinality="many_to_many",
395
- brownfield_resolver_sourced=True,
396
- attrs=(
397
- EdgeAttr("confidence", "DOUBLE", "pass6 match confidence in [0.0, 1.0]"),
398
- EdgeAttr("strategy", "STRING", "async call resolution strategy literal"),
399
- EdgeAttr("direction", "STRING", "produce|consume async direction literal"),
400
- EdgeAttr("raw_topic", "STRING", "uninterpolated topic template from the call site"),
401
- EdgeAttr("match", "STRING", "cross_service|intra_service|ambiguous|phantom|unresolved"),
402
- ),
403
- purpose="resolved async call from a declared Producer to a topic route",
404
- typical_traversals={
405
- "type_subject": (
406
- "neighbors(['{id}'],'out',['DECLARES']) "
407
- "then neighbors(member_ids,'out',['DECLARES_PRODUCER']) "
408
- "then neighbors(producer_ids,'out',['ASYNC_CALLS'])"
409
- ),
410
- "member_subject": (
411
- "neighbors(['{id}'],'out',['DECLARES_PRODUCER']) "
412
- "then neighbors(producer_ids,'out',['ASYNC_CALLS'])"
413
- ),
414
- "route_subject": (
415
- "neighbors(['{id}'],'in',['ASYNC_CALLS']) "
416
- "then neighbors(producer_ids,'in',['DECLARES_PRODUCER']) for declaring method"
417
- ),
418
- "alien_subject": (
419
- "ASYNC_CALLS connects Producer→Route; use DECLARES_PRODUCER from a method Symbol, "
420
- "or neighbors(producer_id,'out',['ASYNC_CALLS']) from a Producer id"
421
- ),
422
- },
423
- ),
424
- }
425
-
426
- ResolveReason = Literal[
427
- "exact_id",
428
- "exact_fqn",
429
- "fqn_suffix",
430
- "short_name",
431
- "route_template",
432
- "route_method_path",
433
- "route_topic",
434
- "route_topic_prefix",
435
- "client_target",
436
- "client_target_path",
437
- "client_name",
438
- "client_fqn",
439
- "producer_topic",
440
- "producer_topic_prefix",
441
- ]
442
-
443
- __all__ = [
444
- "VALID_ROLES",
445
- "VALID_CAPABILITIES",
446
- "VALID_ROUTE_FRAMEWORKS",
447
- "VALID_ROUTE_KINDS",
448
- "VALID_CLIENT_KINDS",
449
- "CLIENT_KIND_FEIGN_METHOD",
450
- "CLIENT_KIND_REST_TEMPLATE",
451
- "CLIENT_KIND_WEB_CLIENT",
452
- "VALID_PRODUCER_KINDS",
453
- "VALID_HTTP_CALL_STRATEGIES",
454
- "VALID_ASYNC_CALL_STRATEGIES",
455
- "VALID_HTTP_CALL_MATCHES",
456
- "VALID_RESOLVE_REASONS",
457
- "FUZZY_STRATEGY_SET",
458
- "BROWNFIELD_RESOLVER_STRATEGY_SET",
459
- "NodeKind",
460
- "Cardinality",
461
- "EdgeAttr",
462
- "EdgeSpec",
463
- "EDGE_SCHEMA",
464
- "ResolveReason",
465
- ]