java-codebase-rag 0.12.0__py3-none-any.whl → 0.12.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.
Files changed (77) hide show
  1. java_codebase_rag-0.12.2.dist-info/METADATA +35 -0
  2. java_codebase_rag-0.12.2.dist-info/RECORD +4 -0
  3. {java_codebase_rag-0.12.0.dist-info → java_codebase_rag-0.12.2.dist-info}/WHEEL +1 -1
  4. java_codebase_rag/_deprecation.py +0 -103
  5. java_codebase_rag/_fdlimit.py +0 -56
  6. java_codebase_rag/_stdio.py +0 -32
  7. java_codebase_rag/_version.py +0 -35
  8. java_codebase_rag/absence/__init__.py +0 -0
  9. java_codebase_rag/absence/absence_diagnosis.py +0 -700
  10. java_codebase_rag/absence/absence_types.py +0 -124
  11. java_codebase_rag/absence/absence_vocab.py +0 -460
  12. java_codebase_rag/analysis/__init__.py +0 -0
  13. java_codebase_rag/analysis/pr_analysis.py +0 -563
  14. java_codebase_rag/analysis/resolve_service.py +0 -740
  15. java_codebase_rag/ast/__init__.py +0 -0
  16. java_codebase_rag/ast/ast_java.py +0 -2847
  17. java_codebase_rag/ast/ast_kotlin.py +0 -1794
  18. java_codebase_rag/ast/brownfield_events.py +0 -58
  19. java_codebase_rag/ast/chunk_heuristics.py +0 -83
  20. java_codebase_rag/ast/language.py +0 -117
  21. java_codebase_rag/cli.py +0 -1215
  22. java_codebase_rag/cli_dispatch.py +0 -251
  23. java_codebase_rag/cli_format.py +0 -85
  24. java_codebase_rag/cli_progress.py +0 -94
  25. java_codebase_rag/config.py +0 -833
  26. java_codebase_rag/eval/__init__.py +0 -1
  27. java_codebase_rag/eval/ground_truth.py +0 -100
  28. java_codebase_rag/eval/metrics.py +0 -107
  29. java_codebase_rag/eval/runner.py +0 -556
  30. java_codebase_rag/graph/__init__.py +0 -0
  31. java_codebase_rag/graph/build_ast_graph.py +0 -4593
  32. java_codebase_rag/graph/graph_enrich.py +0 -1940
  33. java_codebase_rag/graph/graph_types.py +0 -224
  34. java_codebase_rag/graph/java_ontology.py +0 -465
  35. java_codebase_rag/graph/ladybug_queries.py +0 -2213
  36. java_codebase_rag/graph/path_filtering.py +0 -509
  37. java_codebase_rag/index/__init__.py +0 -0
  38. java_codebase_rag/index/java_index_flow_lancedb.py +0 -879
  39. java_codebase_rag/index/java_index_v1_common.py +0 -33
  40. java_codebase_rag/install_data/__init__.py +0 -0
  41. java_codebase_rag/install_data/agents/explorer-rag-cli.md +0 -110
  42. java_codebase_rag/install_data/agents/explorer-rag-enhanced.md +0 -152
  43. java_codebase_rag/install_data/skills/explore-codebase/SKILL.md +0 -165
  44. java_codebase_rag/install_data/skills/explore-codebase-cli/SKILL.md +0 -107
  45. java_codebase_rag/installer.py +0 -2188
  46. java_codebase_rag/jrag.py +0 -4545
  47. java_codebase_rag/jrag_envelope.py +0 -1107
  48. java_codebase_rag/jrag_hints.py +0 -204
  49. java_codebase_rag/jrag_render.py +0 -926
  50. java_codebase_rag/lance_optimize.py +0 -264
  51. java_codebase_rag/mcp/__init__.py +0 -0
  52. java_codebase_rag/mcp/mcp_hints.py +0 -932
  53. java_codebase_rag/mcp/mcp_v2.py +0 -1916
  54. java_codebase_rag/mcp/server.py +0 -886
  55. java_codebase_rag/pipeline.py +0 -531
  56. java_codebase_rag/progress.py +0 -570
  57. java_codebase_rag/read_payloads.py +0 -781
  58. java_codebase_rag/search/__init__.py +0 -0
  59. java_codebase_rag/search/index_common.py +0 -10
  60. java_codebase_rag/search/search_lancedb.py +0 -1296
  61. java_codebase_rag/search/search_lexical.py +0 -449
  62. java_codebase_rag/search/search_scoring.py +0 -537
  63. java_codebase_rag/watch/__init__.py +0 -0
  64. java_codebase_rag/watch/client.py +0 -230
  65. java_codebase_rag/watch/daemon.py +0 -396
  66. java_codebase_rag/watch/lock.py +0 -201
  67. java_codebase_rag/watch/paths.py +0 -76
  68. java_codebase_rag/watch/protocol.py +0 -122
  69. java_codebase_rag/watch/server.py +0 -273
  70. java_codebase_rag/watch/warm.py +0 -105
  71. java_codebase_rag/watch/watcher.py +0 -394
  72. java_codebase_rag-0.12.0.dist-info/METADATA +0 -340
  73. java_codebase_rag-0.12.0.dist-info/RECORD +0 -75
  74. java_codebase_rag-0.12.0.dist-info/entry_points.txt +0 -5
  75. java_codebase_rag-0.12.0.dist-info/licenses/LICENSE +0 -21
  76. java_codebase_rag-0.12.0.dist-info/top_level.txt +0 -1
  77. /java_codebase_rag/__init__.py → /java_codebase_rag-0.12.2.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
- ]