sourcecode 2.4.0__py3-none-any.whl → 2.5.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.
- sourcecode/__init__.py +1 -1
- sourcecode/archetype.py +46 -0
- sourcecode/cli.py +429 -3
- sourcecode/context_graph.py +32 -24
- sourcecode/repository_ir.py +116 -2
- sourcecode/retrieval/__init__.py +192 -0
- sourcecode/retrieval/context.py +241 -0
- sourcecode/retrieval/errors.py +41 -0
- sourcecode/retrieval/executor.py +51 -0
- sourcecode/retrieval/planner.py +297 -0
- sourcecode/retrieval/query.py +484 -0
- sourcecode/retrieval/request.py +94 -0
- sourcecode/retrieval/resolution.py +135 -0
- sourcecode/retrieval/result.py +144 -0
- sourcecode/retrieval/retriever.py +62 -0
- sourcecode/retrieval/runtime.py +259 -0
- sourcecode/retrieval/steps.py +242 -0
- sourcecode/retrieval/steps_endpoint.py +311 -0
- sourcecode/retrieval/steps_graph.py +248 -0
- sourcecode/retrieval/steps_impact.py +293 -0
- sourcecode/retrieval/steps_intf.py +247 -0
- sourcecode/retrieval/steps_struct.py +338 -0
- sourcecode/retrieval/steps_txsec.py +351 -0
- sourcecode/security_config.py +4 -4
- sourcecode/spring_impact.py +52 -10
- {sourcecode-2.4.0.dist-info → sourcecode-2.5.1.dist-info}/METADATA +4 -4
- {sourcecode-2.4.0.dist-info → sourcecode-2.5.1.dist-info}/RECORD +30 -12
- {sourcecode-2.4.0.dist-info → sourcecode-2.5.1.dist-info}/WHEEL +0 -0
- {sourcecode-2.4.0.dist-info → sourcecode-2.5.1.dist-info}/entry_points.txt +0 -0
- {sourcecode-2.4.0.dist-info → sourcecode-2.5.1.dist-info}/licenses/LICENSE +0 -0
sourcecode/__init__.py
CHANGED
sourcecode/archetype.py
CHANGED
|
@@ -80,6 +80,17 @@ _MIN_PRIMARY_SCORE = 0.05
|
|
|
80
80
|
# A winner must clear this absolute score (not just the top-2 margin) to earn
|
|
81
81
|
# medium/high confidence — a near-floor lone candidate stays "low".
|
|
82
82
|
_MIN_CONFIDENT_SCORE = 0.5
|
|
83
|
+
# Fraction of engine's positive contribution discounted for a non-runnable artifact
|
|
84
|
+
# (P0 library de-bias): an engine-like internal core is expected of a library, so it is not
|
|
85
|
+
# discriminating. Tuned so a clear library (no app/server/servlet entry) is not confidently
|
|
86
|
+
# labeled an engine, while runnable systems (which never trigger the gate) are untouched.
|
|
87
|
+
_LIBRARY_ENGINE_DISCOUNT = 0.55
|
|
88
|
+
# Entry kinds that make a repo a runnable system (an app/server/servlet/daemon) rather
|
|
89
|
+
# than a consumable library. Used to gate the library de-bias (P0).
|
|
90
|
+
_RUNNABLE_ENTRY_KINDS = frozenset({
|
|
91
|
+
"application", "bootstrap", "main", "server", "daemon", "worker",
|
|
92
|
+
"mvc_controller", "jax_rs_controller", "servlet", "security_filter", "filter",
|
|
93
|
+
})
|
|
83
94
|
|
|
84
95
|
|
|
85
96
|
@dataclass
|
|
@@ -389,6 +400,41 @@ class ArchetypeClassifier:
|
|
|
389
400
|
f"{f.module_count} modules; distributed mass ≈ {cm['distributed']:.0%}",
|
|
390
401
|
1.5, multi, max(cm["distributed"], 0.1))
|
|
391
402
|
self._apply_graph_evidence("software_archetype", cands, f)
|
|
403
|
+
# ── Library de-bias (P0) ────────────────────────────────────────────────
|
|
404
|
+
# A consumable JVM artifact — `jar` packaging with no server/bootstrap/application
|
|
405
|
+
# entry — is a library, not a runnable system. But a library naturally exhibits
|
|
406
|
+
# engine-like topology: a few core API types with high fan-in, tightly-coupled
|
|
407
|
+
# internals (SCCs), hub concentration. Those graph metrics (`graph_*`) otherwise
|
|
408
|
+
# label every library an "engine" (observed: jobrunr → engine(high), library 0.3).
|
|
409
|
+
# Correct it transparently: (1) add a packaging-grounded library signal that does
|
|
410
|
+
# not depend on an `api/` package existing; (2) append a NAMED negative evidence row
|
|
411
|
+
# that discounts most of engine's graph-derived score, since topological hubness in
|
|
412
|
+
# a library is expected and therefore not discriminating for "engine".
|
|
413
|
+
# A runnable/web entry of ANY kind (an app bootstrap, an HTTP controller, a
|
|
414
|
+
# servlet, a daemon) means the repo is a system you run, not a library you depend
|
|
415
|
+
# on. Packaging is unreliable here (gradle libs report no packaging; maven
|
|
416
|
+
# aggregators report `pom`), so the entry-kind surface is the robust signal.
|
|
417
|
+
is_runnable = any(k in f.entry_kinds for k in _RUNNABLE_ENTRY_KINDS)
|
|
418
|
+
is_library_shaped = not is_runnable
|
|
419
|
+
if is_library_shaped:
|
|
420
|
+
add("library", "no_runnable_entry",
|
|
421
|
+
f"entry kinds {sorted(f.entry_kinds) or 'none'} — no app/server/servlet "
|
|
422
|
+
"bootstrap; a consumable artifact, not a runnable system",
|
|
423
|
+
3.0, 1.0, 0.7)
|
|
424
|
+
# A library legitimately owns an engine-like core (storage/kernel mass, hub
|
|
425
|
+
# topology, SCCs) — that is what a library *is*. Discount most of engine's
|
|
426
|
+
# positive evidence for a non-runnable artifact so its internal machinery does
|
|
427
|
+
# not, alone, promote it to "engine". Transparent: a named negative row.
|
|
428
|
+
engine_positive = sum(max(0.0, e.contribution) for e in cands["engine"])
|
|
429
|
+
if engine_positive > 0:
|
|
430
|
+
discount = engine_positive * _LIBRARY_ENGINE_DISCOUNT
|
|
431
|
+
cands["engine"].append(Evidence(
|
|
432
|
+
"library_core_discount",
|
|
433
|
+
"non-runnable artifact: an engine-like internal core (storage/kernel "
|
|
434
|
+
"mass, hubs, SCCs) is expected of a library and is not, alone, evidence "
|
|
435
|
+
"of an engine product",
|
|
436
|
+
1.0, 1.0, 1.0, -discount,
|
|
437
|
+
))
|
|
392
438
|
return self._resolve("software_archetype", cands, f)
|
|
393
439
|
|
|
394
440
|
def _architectural_style(self, f: _Features) -> DimensionResult:
|
sourcecode/cli.py
CHANGED
|
@@ -248,6 +248,8 @@ _SUBCOMMANDS: frozenset[str] = frozenset(
|
|
|
248
248
|
"chunk-file",
|
|
249
249
|
# Experimental evidence-based archetype (parallel to legacy)
|
|
250
250
|
"archetype",
|
|
251
|
+
# Experimental Semantic Retrieval Engine (Layer 3.5)
|
|
252
|
+
"retrieve",
|
|
251
253
|
}
|
|
252
254
|
)
|
|
253
255
|
|
|
@@ -600,6 +602,12 @@ app.add_typer(cache_app, name="cache")
|
|
|
600
602
|
auth_app = typer.Typer(help="Authentication: status, logout.", rich_markup_mode="rich")
|
|
601
603
|
app.add_typer(auth_app, name="auth")
|
|
602
604
|
|
|
605
|
+
retrieve_app = typer.Typer(
|
|
606
|
+
help="[EXPERIMENTAL] Semantic Retrieval Engine — typed knowledge queries.",
|
|
607
|
+
rich_markup_mode="rich",
|
|
608
|
+
)
|
|
609
|
+
app.add_typer(retrieve_app, name="retrieve")
|
|
610
|
+
|
|
603
611
|
|
|
604
612
|
def _maybe_show_telemetry_notice() -> None:
|
|
605
613
|
"""Show first-run telemetry notice once, on interactive TTYs only.
|
|
@@ -3887,7 +3895,7 @@ def endpoints_cmd(
|
|
|
3887
3895
|
as policy "none_detected"):
|
|
3888
3896
|
{
|
|
3889
3897
|
"customSecurityAnnotations": [
|
|
3890
|
-
{"shortName": "
|
|
3898
|
+
{"shortName": "CustomSecurityAnnotation",
|
|
3891
3899
|
"resourceParam": "nombreRecurso", "levelParam": "nivelRequerido"}
|
|
3892
3900
|
]
|
|
3893
3901
|
}
|
|
@@ -5558,7 +5566,12 @@ def fix_bug_cmd(
|
|
|
5558
5566
|
ctx: typer.Context,
|
|
5559
5567
|
path: Path = typer.Argument(
|
|
5560
5568
|
Path("."),
|
|
5561
|
-
help="Repository root (default: current directory)",
|
|
5569
|
+
help="Repository root (default: current directory), OR the bug symptom when a second path argument follows (sibling-consistent `fix-bug <symptom> <path>`).",
|
|
5570
|
+
),
|
|
5571
|
+
path2: Optional[Path] = typer.Argument(
|
|
5572
|
+
None,
|
|
5573
|
+
help="Repository root when the first argument is the bug symptom.",
|
|
5574
|
+
show_default=False,
|
|
5562
5575
|
),
|
|
5563
5576
|
symptom: Optional[str] = typer.Option(
|
|
5564
5577
|
None, "--symptom", "-s",
|
|
@@ -5596,7 +5609,16 @@ def fix_bug_cmd(
|
|
|
5596
5609
|
ask impact <target> — Propagate impact from a specific class
|
|
5597
5610
|
ask onboard . — Full architecture context first
|
|
5598
5611
|
"""
|
|
5599
|
-
#
|
|
5612
|
+
# Sibling-consistent positional form: `fix-bug <symptom> <path>` (mirrors
|
|
5613
|
+
# `impact <target> <path>` / `explain <symbol> <path>`). When a second positional is
|
|
5614
|
+
# supplied, the first positional is the symptom and the second is the repository path.
|
|
5615
|
+
if path2 is not None:
|
|
5616
|
+
if not symptom:
|
|
5617
|
+
symptom = str(path)
|
|
5618
|
+
path = path2
|
|
5619
|
+
|
|
5620
|
+
# Detect misuse: `fix-bug "symptom text"` alone — the single positional looks like a
|
|
5621
|
+
# symptom, not a path.
|
|
5600
5622
|
_path_str = str(path)
|
|
5601
5623
|
_path_looks_like_symptom = (
|
|
5602
5624
|
not Path(_path_str).exists()
|
|
@@ -6509,6 +6531,410 @@ def archetype_cmd(
|
|
|
6509
6531
|
typer.echo(out)
|
|
6510
6532
|
|
|
6511
6533
|
|
|
6534
|
+
def _run_retrieval_intent(
|
|
6535
|
+
intent_name: str,
|
|
6536
|
+
path: Path,
|
|
6537
|
+
output_path: Optional[Path],
|
|
6538
|
+
trace: bool,
|
|
6539
|
+
anchors: tuple = (),
|
|
6540
|
+
) -> None:
|
|
6541
|
+
"""Shared adapter for the experimental Semantic Retrieval commands. The CLI is one
|
|
6542
|
+
thin surface over the CLI-independent engine: it submits a typed RetrievalRequest and
|
|
6543
|
+
prints the structured JSON result (optionally with the runtime trace/profiling)."""
|
|
6544
|
+
import json as _json
|
|
6545
|
+
from sourcecode.retrieval import (
|
|
6546
|
+
RetrievalAnchor,
|
|
6547
|
+
RetrievalIntent,
|
|
6548
|
+
RetrievalRequest,
|
|
6549
|
+
SemanticRetriever,
|
|
6550
|
+
)
|
|
6551
|
+
|
|
6552
|
+
target = Path(path).resolve()
|
|
6553
|
+
retriever = SemanticRetriever.for_repo(target)
|
|
6554
|
+
request = RetrievalRequest(
|
|
6555
|
+
intent=RetrievalIntent(intent_name),
|
|
6556
|
+
anchors=tuple(RetrievalAnchor(kind=k, raw=v) for k, v in anchors),
|
|
6557
|
+
)
|
|
6558
|
+
run = retriever.run(request)
|
|
6559
|
+
payload: dict = run.result.to_dict()
|
|
6560
|
+
if trace:
|
|
6561
|
+
payload = {"result": payload, "runtime": run.report.to_dict()}
|
|
6562
|
+
out = _json.dumps(payload, indent=2, ensure_ascii=False)
|
|
6563
|
+
if output_path:
|
|
6564
|
+
_safe_write_file(output_path, out)
|
|
6565
|
+
typer.echo(f"Retrieval result written to {output_path}")
|
|
6566
|
+
else:
|
|
6567
|
+
typer.echo(out)
|
|
6568
|
+
|
|
6569
|
+
|
|
6570
|
+
@retrieve_app.command("architectural-core")
|
|
6571
|
+
def retrieve_architectural_core_cmd(
|
|
6572
|
+
path: Path = typer.Argument(Path("."), help="Repository path (default: current directory)"),
|
|
6573
|
+
output_path: Optional[Path] = typer.Option(
|
|
6574
|
+
None, "--output", "-o", help="Write output to a file instead of stdout."
|
|
6575
|
+
),
|
|
6576
|
+
trace: bool = typer.Option(
|
|
6577
|
+
False, "--trace", help="Include the Query Plan Runtime trace + per-step profiling."
|
|
6578
|
+
),
|
|
6579
|
+
) -> None:
|
|
6580
|
+
"""[EXPERIMENTAL] Retrieve the ARCHITECTURAL_CORE characterization as structured JSON.
|
|
6581
|
+
|
|
6582
|
+
A Semantic Retrieval query (Layer 3.5): it consults ONLY existing Knowledge-Layer
|
|
6583
|
+
capabilities (ArchetypeClassifier + GraphEvidenceProvider) — no extraction, no new
|
|
6584
|
+
heuristics, no natural language. Output is fully typed/structured JSON.
|
|
6585
|
+
"""
|
|
6586
|
+
_run_retrieval_intent("architectural-core", path, output_path, trace)
|
|
6587
|
+
|
|
6588
|
+
|
|
6589
|
+
@retrieve_app.command("architectural-style")
|
|
6590
|
+
def retrieve_architectural_style_cmd(
|
|
6591
|
+
path: Path = typer.Argument(Path("."), help="Repository path (default: current directory)"),
|
|
6592
|
+
output_path: Optional[Path] = typer.Option(
|
|
6593
|
+
None, "--output", "-o", help="Write output to a file instead of stdout."
|
|
6594
|
+
),
|
|
6595
|
+
trace: bool = typer.Option(
|
|
6596
|
+
False, "--trace", help="Include the Query Plan Runtime trace + per-step profiling."
|
|
6597
|
+
),
|
|
6598
|
+
) -> None:
|
|
6599
|
+
"""[EXPERIMENTAL] Retrieve the ARCHITECTURAL_STYLE characterization as structured JSON.
|
|
6600
|
+
|
|
6601
|
+
Same Query Plan Runtime as architectural-core — this intent differs only in its
|
|
6602
|
+
declarative plan (the archetype dimension). No runtime code changes to add it.
|
|
6603
|
+
"""
|
|
6604
|
+
_run_retrieval_intent("architectural-style", path, output_path, trace)
|
|
6605
|
+
|
|
6606
|
+
|
|
6607
|
+
@retrieve_app.command("deployment-shape")
|
|
6608
|
+
def retrieve_deployment_shape_cmd(
|
|
6609
|
+
path: Path = typer.Argument(Path("."), help="Repository path (default: current directory)"),
|
|
6610
|
+
output_path: Optional[Path] = typer.Option(None, "--output", "-o", help="Write output to a file."),
|
|
6611
|
+
trace: bool = typer.Option(False, "--trace", help="Include the Query Plan Runtime trace."),
|
|
6612
|
+
) -> None:
|
|
6613
|
+
"""[EXPERIMENTAL] DEPLOYMENT_SHAPE — the deployment-shape archetype dimension.
|
|
6614
|
+
Same plan as architectural-core, different ArchetypeClassifier dimension."""
|
|
6615
|
+
_run_retrieval_intent("deployment-shape", path, output_path, trace)
|
|
6616
|
+
|
|
6617
|
+
|
|
6618
|
+
@retrieve_app.command("primary-interface")
|
|
6619
|
+
def retrieve_primary_interface_cmd(
|
|
6620
|
+
path: Path = typer.Argument(Path("."), help="Repository path (default: current directory)"),
|
|
6621
|
+
output_path: Optional[Path] = typer.Option(None, "--output", "-o", help="Write output to a file."),
|
|
6622
|
+
trace: bool = typer.Option(False, "--trace", help="Include the Query Plan Runtime trace."),
|
|
6623
|
+
) -> None:
|
|
6624
|
+
"""[EXPERIMENTAL] PRIMARY_INTERFACE — the primary-interface archetype dimension.
|
|
6625
|
+
Same plan as architectural-core, different ArchetypeClassifier dimension."""
|
|
6626
|
+
_run_retrieval_intent("primary-interface", path, output_path, trace)
|
|
6627
|
+
|
|
6628
|
+
|
|
6629
|
+
@retrieve_app.command("blast-radius")
|
|
6630
|
+
def retrieve_blast_radius_cmd(
|
|
6631
|
+
target: str = typer.Option(..., "--target", "-t", help="Symbol (class/FQN) or file to analyze."),
|
|
6632
|
+
path: Path = typer.Argument(Path("."), help="Repository path (default: current directory)"),
|
|
6633
|
+
output_path: Optional[Path] = typer.Option(None, "--output", "-o", help="Write output to a file."),
|
|
6634
|
+
trace: bool = typer.Option(False, "--trace", help="Include the Query Plan Runtime trace."),
|
|
6635
|
+
) -> None:
|
|
6636
|
+
"""[EXPERIMENTAL] BLAST_RADIUS — structural change impact (dependents + risk) for a
|
|
6637
|
+
target, via the Semantic Retrieval Engine. Reuses `compute_blast_radius`."""
|
|
6638
|
+
_run_retrieval_intent("blast-radius", path, output_path, trace, anchors=(("symbol", target),))
|
|
6639
|
+
|
|
6640
|
+
|
|
6641
|
+
@retrieve_app.command("affected-endpoints")
|
|
6642
|
+
def retrieve_affected_endpoints_cmd(
|
|
6643
|
+
target: str = typer.Option(..., "--target", "-t", help="Symbol (class/FQN) or file to analyze."),
|
|
6644
|
+
path: Path = typer.Argument(Path("."), help="Repository path (default: current directory)"),
|
|
6645
|
+
output_path: Optional[Path] = typer.Option(None, "--output", "-o", help="Write output to a file."),
|
|
6646
|
+
trace: bool = typer.Option(False, "--trace", help="Include the Query Plan Runtime trace."),
|
|
6647
|
+
) -> None:
|
|
6648
|
+
"""[EXPERIMENTAL] AFFECTED_ENDPOINTS — HTTP endpoints in the blast cone of a target."""
|
|
6649
|
+
_run_retrieval_intent("affected-endpoints", path, output_path, trace, anchors=(("symbol", target),))
|
|
6650
|
+
|
|
6651
|
+
|
|
6652
|
+
@retrieve_app.command("affected-integrations")
|
|
6653
|
+
def retrieve_affected_integrations_cmd(
|
|
6654
|
+
target: str = typer.Option(..., "--target", "-t", help="Symbol (class/FQN) or file to analyze."),
|
|
6655
|
+
path: Path = typer.Argument(Path("."), help="Repository path (default: current directory)"),
|
|
6656
|
+
output_path: Optional[Path] = typer.Option(None, "--output", "-o", help="Write output to a file."),
|
|
6657
|
+
trace: bool = typer.Option(False, "--trace", help="Include the Query Plan Runtime trace."),
|
|
6658
|
+
) -> None:
|
|
6659
|
+
"""[EXPERIMENTAL] AFFECTED_INTEGRATIONS — external integrations in the blast cone of a
|
|
6660
|
+
target. Reuses `SemanticIntegrationEngine`."""
|
|
6661
|
+
_run_retrieval_intent(
|
|
6662
|
+
"affected-integrations", path, output_path, trace, anchors=(("symbol", target),)
|
|
6663
|
+
)
|
|
6664
|
+
|
|
6665
|
+
|
|
6666
|
+
@retrieve_app.command("transaction-boundaries")
|
|
6667
|
+
def retrieve_transaction_boundaries_cmd(
|
|
6668
|
+
target: str = typer.Option(..., "--target", "-t", help="Symbol (class/FQN) or file to analyze."),
|
|
6669
|
+
path: Path = typer.Argument(Path("."), help="Repository path (default: current directory)"),
|
|
6670
|
+
output_path: Optional[Path] = typer.Option(None, "--output", "-o", help="Write output to a file."),
|
|
6671
|
+
trace: bool = typer.Option(False, "--trace", help="Include the Query Plan Runtime trace."),
|
|
6672
|
+
) -> None:
|
|
6673
|
+
"""[EXPERIMENTAL] TRANSACTION_BOUNDARIES — transactional boundaries touched by a
|
|
6674
|
+
target's blast cone."""
|
|
6675
|
+
_run_retrieval_intent(
|
|
6676
|
+
"transaction-boundaries", path, output_path, trace, anchors=(("symbol", target),)
|
|
6677
|
+
)
|
|
6678
|
+
|
|
6679
|
+
|
|
6680
|
+
@retrieve_app.command("cross-module-impact")
|
|
6681
|
+
def retrieve_cross_module_impact_cmd(
|
|
6682
|
+
target: str = typer.Option(..., "--target", "-t", help="Symbol (class/FQN) or file to analyze."),
|
|
6683
|
+
path: Path = typer.Argument(Path("."), help="Repository path (default: current directory)"),
|
|
6684
|
+
output_path: Optional[Path] = typer.Option(None, "--output", "-o", help="Write output to a file."),
|
|
6685
|
+
trace: bool = typer.Option(False, "--trace", help="Include the Query Plan Runtime trace."),
|
|
6686
|
+
) -> None:
|
|
6687
|
+
"""[EXPERIMENTAL] CROSS_MODULE_IMPACT — subsystems/modules hit by a target's change."""
|
|
6688
|
+
_run_retrieval_intent(
|
|
6689
|
+
"cross-module-impact", path, output_path, trace, anchors=(("symbol", target),)
|
|
6690
|
+
)
|
|
6691
|
+
|
|
6692
|
+
|
|
6693
|
+
@retrieve_app.command("transaction-flow")
|
|
6694
|
+
def retrieve_transaction_flow_cmd(
|
|
6695
|
+
path: Path = typer.Argument(Path("."), help="Repository path (default: current directory)"),
|
|
6696
|
+
output_path: Optional[Path] = typer.Option(None, "--output", "-o", help="Write output to a file."),
|
|
6697
|
+
trace: bool = typer.Option(False, "--trace", help="Include the Query Plan Runtime trace."),
|
|
6698
|
+
) -> None:
|
|
6699
|
+
"""[EXPERIMENTAL] TRANSACTION_FLOW — the @Transactional boundary map. Reuses
|
|
6700
|
+
SpringSemanticModel's transaction index."""
|
|
6701
|
+
_run_retrieval_intent("transaction-flow", path, output_path, trace)
|
|
6702
|
+
|
|
6703
|
+
|
|
6704
|
+
@retrieve_app.command("transaction-entrypoints")
|
|
6705
|
+
def retrieve_transaction_entrypoints_cmd(
|
|
6706
|
+
path: Path = typer.Argument(Path("."), help="Repository path (default: current directory)"),
|
|
6707
|
+
output_path: Optional[Path] = typer.Option(None, "--output", "-o", help="Write output to a file."),
|
|
6708
|
+
trace: bool = typer.Option(False, "--trace", help="Include the Query Plan Runtime trace."),
|
|
6709
|
+
) -> None:
|
|
6710
|
+
"""[EXPERIMENTAL] TRANSACTION_ENTRYPOINTS — transactional boundaries at the API surface."""
|
|
6711
|
+
_run_retrieval_intent("transaction-entrypoints", path, output_path, trace)
|
|
6712
|
+
|
|
6713
|
+
|
|
6714
|
+
@retrieve_app.command("transaction-propagation")
|
|
6715
|
+
def retrieve_transaction_propagation_cmd(
|
|
6716
|
+
path: Path = typer.Argument(Path("."), help="Repository path (default: current directory)"),
|
|
6717
|
+
output_path: Optional[Path] = typer.Option(None, "--output", "-o", help="Write output to a file."),
|
|
6718
|
+
trace: bool = typer.Option(False, "--trace", help="Include the Query Plan Runtime trace."),
|
|
6719
|
+
) -> None:
|
|
6720
|
+
"""[EXPERIMENTAL] TRANSACTION_PROPAGATION — non-default propagation points + propagation
|
|
6721
|
+
risks. Reuses the Spring transaction engine."""
|
|
6722
|
+
_run_retrieval_intent("transaction-propagation", path, output_path, trace)
|
|
6723
|
+
|
|
6724
|
+
|
|
6725
|
+
@retrieve_app.command("security-surface")
|
|
6726
|
+
def retrieve_security_surface_cmd(
|
|
6727
|
+
path: Path = typer.Argument(Path("."), help="Repository path (default: current directory)"),
|
|
6728
|
+
output_path: Optional[Path] = typer.Option(None, "--output", "-o", help="Write output to a file."),
|
|
6729
|
+
trace: bool = typer.Option(False, "--trace", help="Include the Query Plan Runtime trace."),
|
|
6730
|
+
) -> None:
|
|
6731
|
+
"""[EXPERIMENTAL] SECURITY_SURFACE — the security audit surface. Reuses run_security_audit."""
|
|
6732
|
+
_run_retrieval_intent("security-surface", path, output_path, trace)
|
|
6733
|
+
|
|
6734
|
+
|
|
6735
|
+
@retrieve_app.command("security-chain")
|
|
6736
|
+
def retrieve_security_chain_cmd(
|
|
6737
|
+
target: str = typer.Option(..., "--target", "-t", help="Symbol (class/FQN) to scope the chain to."),
|
|
6738
|
+
path: Path = typer.Argument(Path("."), help="Repository path (default: current directory)"),
|
|
6739
|
+
output_path: Optional[Path] = typer.Option(None, "--output", "-o", help="Write output to a file."),
|
|
6740
|
+
trace: bool = typer.Option(False, "--trace", help="Include the Query Plan Runtime trace."),
|
|
6741
|
+
) -> None:
|
|
6742
|
+
"""[EXPERIMENTAL] SECURITY_CHAIN — security findings scoped to a target symbol."""
|
|
6743
|
+
_run_retrieval_intent("security-chain", path, output_path, trace, anchors=(("symbol", target),))
|
|
6744
|
+
|
|
6745
|
+
|
|
6746
|
+
@retrieve_app.command("validation-points")
|
|
6747
|
+
def retrieve_validation_points_cmd(
|
|
6748
|
+
path: Path = typer.Argument(Path("."), help="Repository path (default: current directory)"),
|
|
6749
|
+
output_path: Optional[Path] = typer.Option(None, "--output", "-o", help="Write output to a file."),
|
|
6750
|
+
trace: bool = typer.Option(False, "--trace", help="Include the Query Plan Runtime trace."),
|
|
6751
|
+
) -> None:
|
|
6752
|
+
"""[EXPERIMENTAL] VALIDATION_POINTS — request-body validation constraints + gaps.
|
|
6753
|
+
Reuses build_validation_surface."""
|
|
6754
|
+
_run_retrieval_intent("validation-points", path, output_path, trace)
|
|
6755
|
+
|
|
6756
|
+
|
|
6757
|
+
@retrieve_app.command("endpoint-inventory")
|
|
6758
|
+
def retrieve_endpoint_inventory_cmd(
|
|
6759
|
+
path: Path = typer.Argument(Path("."), help="Repository path (default: current directory)"),
|
|
6760
|
+
output_path: Optional[Path] = typer.Option(None, "--output", "-o", help="Write output to a file."),
|
|
6761
|
+
trace: bool = typer.Option(False, "--trace", help="Include the Query Plan Runtime trace."),
|
|
6762
|
+
) -> None:
|
|
6763
|
+
"""[EXPERIMENTAL] ENDPOINT_INVENTORY — the repository's HTTP surface.
|
|
6764
|
+
Reuses SpringSemanticModel.endpoint_index."""
|
|
6765
|
+
_run_retrieval_intent("endpoint-inventory", path, output_path, trace)
|
|
6766
|
+
|
|
6767
|
+
|
|
6768
|
+
@retrieve_app.command("integration-inventory")
|
|
6769
|
+
def retrieve_integration_inventory_cmd(
|
|
6770
|
+
path: Path = typer.Argument(Path("."), help="Repository path (default: current directory)"),
|
|
6771
|
+
output_path: Optional[Path] = typer.Option(None, "--output", "-o", help="Write output to a file."),
|
|
6772
|
+
trace: bool = typer.Option(False, "--trace", help="Include the Query Plan Runtime trace."),
|
|
6773
|
+
) -> None:
|
|
6774
|
+
"""[EXPERIMENTAL] INTEGRATION_INVENTORY — every detected external integration.
|
|
6775
|
+
Reuses SemanticIntegrationEngine (whole repo, no cone filter)."""
|
|
6776
|
+
_run_retrieval_intent("integration-inventory", path, output_path, trace)
|
|
6777
|
+
|
|
6778
|
+
|
|
6779
|
+
@retrieve_app.command("event-topology")
|
|
6780
|
+
def retrieve_event_topology_cmd(
|
|
6781
|
+
path: Path = typer.Argument(Path("."), help="Repository path (default: current directory)"),
|
|
6782
|
+
output_path: Optional[Path] = typer.Option(None, "--output", "-o", help="Write output to a file."),
|
|
6783
|
+
trace: bool = typer.Option(False, "--trace", help="Include the Query Plan Runtime trace."),
|
|
6784
|
+
) -> None:
|
|
6785
|
+
"""[EXPERIMENTAL] EVENT_TOPOLOGY — Spring event publishers/listeners per event type.
|
|
6786
|
+
Reuses SpringSemanticModel.event_graph."""
|
|
6787
|
+
_run_retrieval_intent("event-topology", path, output_path, trace)
|
|
6788
|
+
|
|
6789
|
+
|
|
6790
|
+
@retrieve_app.command("subsystem-inventory")
|
|
6791
|
+
def retrieve_subsystem_inventory_cmd(
|
|
6792
|
+
path: Path = typer.Argument(Path("."), help="Repository path (default: current directory)"),
|
|
6793
|
+
output_path: Optional[Path] = typer.Option(None, "--output", "-o", help="Write output to a file."),
|
|
6794
|
+
trace: bool = typer.Option(False, "--trace", help="Include the Query Plan Runtime trace."),
|
|
6795
|
+
) -> None:
|
|
6796
|
+
"""[EXPERIMENTAL] SUBSYSTEM_INVENTORY — the repository's subsystem partition.
|
|
6797
|
+
Reuses the repo IR subsystem model."""
|
|
6798
|
+
_run_retrieval_intent("subsystem-inventory", path, output_path, trace)
|
|
6799
|
+
|
|
6800
|
+
|
|
6801
|
+
@retrieve_app.command("subsystem-members")
|
|
6802
|
+
def retrieve_subsystem_members_cmd(
|
|
6803
|
+
subsystem: str = typer.Option(..., "--subsystem", "-s", help="Subsystem label or package prefix."),
|
|
6804
|
+
path: Path = typer.Argument(Path("."), help="Repository path (default: current directory)"),
|
|
6805
|
+
output_path: Optional[Path] = typer.Option(None, "--output", "-o", help="Write output to a file."),
|
|
6806
|
+
trace: bool = typer.Option(False, "--trace", help="Include the Query Plan Runtime trace."),
|
|
6807
|
+
) -> None:
|
|
6808
|
+
"""[EXPERIMENTAL] SUBSYSTEM_MEMBERS — the member symbols of a subsystem.
|
|
6809
|
+
Reuses the repo IR subsystem model."""
|
|
6810
|
+
_run_retrieval_intent(
|
|
6811
|
+
"subsystem-members", path, output_path, trace, anchors=(("subsystem", subsystem),)
|
|
6812
|
+
)
|
|
6813
|
+
|
|
6814
|
+
|
|
6815
|
+
@retrieve_app.command("module-dependents")
|
|
6816
|
+
def retrieve_module_dependents_cmd(
|
|
6817
|
+
module: str = typer.Option(..., "--module", "-m", help="Module path or package prefix."),
|
|
6818
|
+
path: Path = typer.Argument(Path("."), help="Repository path (default: current directory)"),
|
|
6819
|
+
output_path: Optional[Path] = typer.Option(None, "--output", "-o", help="Write output to a file."),
|
|
6820
|
+
trace: bool = typer.Option(False, "--trace", help="Include the Query Plan Runtime trace."),
|
|
6821
|
+
) -> None:
|
|
6822
|
+
"""[EXPERIMENTAL] MODULE_DEPENDENTS — modules that depend on the scope.
|
|
6823
|
+
Reuses the module graph (GraphAnalyzer)."""
|
|
6824
|
+
_run_retrieval_intent(
|
|
6825
|
+
"module-dependents", path, output_path, trace, anchors=(("module", module),)
|
|
6826
|
+
)
|
|
6827
|
+
|
|
6828
|
+
|
|
6829
|
+
@retrieve_app.command("module-dependencies")
|
|
6830
|
+
def retrieve_module_dependencies_cmd(
|
|
6831
|
+
module: str = typer.Option(..., "--module", "-m", help="Module path or package prefix."),
|
|
6832
|
+
path: Path = typer.Argument(Path("."), help="Repository path (default: current directory)"),
|
|
6833
|
+
output_path: Optional[Path] = typer.Option(None, "--output", "-o", help="Write output to a file."),
|
|
6834
|
+
trace: bool = typer.Option(False, "--trace", help="Include the Query Plan Runtime trace."),
|
|
6835
|
+
) -> None:
|
|
6836
|
+
"""[EXPERIMENTAL] MODULE_DEPENDENCIES — modules the scope depends on.
|
|
6837
|
+
Reuses the module graph (GraphAnalyzer)."""
|
|
6838
|
+
_run_retrieval_intent(
|
|
6839
|
+
"module-dependencies", path, output_path, trace, anchors=(("module", module),)
|
|
6840
|
+
)
|
|
6841
|
+
|
|
6842
|
+
|
|
6843
|
+
@retrieve_app.command("type-dependents")
|
|
6844
|
+
def retrieve_type_dependents_cmd(
|
|
6845
|
+
target: str = typer.Option(..., "--target", "-t", help="Type/symbol (simple name or FQN)."),
|
|
6846
|
+
path: Path = typer.Argument(Path("."), help="Repository path (default: current directory)"),
|
|
6847
|
+
output_path: Optional[Path] = typer.Option(None, "--output", "-o", help="Write output to a file."),
|
|
6848
|
+
trace: bool = typer.Option(False, "--trace", help="Include the Query Plan Runtime trace."),
|
|
6849
|
+
) -> None:
|
|
6850
|
+
"""[EXPERIMENTAL] TYPE_DEPENDENTS — types that import/implement/inject the target.
|
|
6851
|
+
Reuses the repo IR reverse graph."""
|
|
6852
|
+
_run_retrieval_intent(
|
|
6853
|
+
"type-dependents", path, output_path, trace, anchors=(("symbol", target),)
|
|
6854
|
+
)
|
|
6855
|
+
|
|
6856
|
+
|
|
6857
|
+
@retrieve_app.command("endpoint-contract")
|
|
6858
|
+
def retrieve_endpoint_contract_cmd(
|
|
6859
|
+
ref: str = typer.Option(..., "--endpoint", "-e", help="Endpoint path or handler symbol."),
|
|
6860
|
+
path: Path = typer.Argument(Path("."), help="Repository path (default: current directory)"),
|
|
6861
|
+
output_path: Optional[Path] = typer.Option(None, "--output", "-o", help="Write output to a file."),
|
|
6862
|
+
trace: bool = typer.Option(False, "--trace", help="Include the Query Plan Runtime trace."),
|
|
6863
|
+
) -> None:
|
|
6864
|
+
"""[EXPERIMENTAL] ENDPOINT_CONTRACT — the request/validation contract of an endpoint.
|
|
6865
|
+
Reuses build_validation_surface, scoped to one endpoint."""
|
|
6866
|
+
_run_retrieval_intent(
|
|
6867
|
+
"endpoint-contract", path, output_path, trace, anchors=(("endpoint", ref),)
|
|
6868
|
+
)
|
|
6869
|
+
|
|
6870
|
+
|
|
6871
|
+
@retrieve_app.command("endpoint-security")
|
|
6872
|
+
def retrieve_endpoint_security_cmd(
|
|
6873
|
+
ref: str = typer.Option(..., "--endpoint", "-e", help="Endpoint path or handler symbol."),
|
|
6874
|
+
path: Path = typer.Argument(Path("."), help="Repository path (default: current directory)"),
|
|
6875
|
+
output_path: Optional[Path] = typer.Option(None, "--output", "-o", help="Write output to a file."),
|
|
6876
|
+
trace: bool = typer.Option(False, "--trace", help="Include the Query Plan Runtime trace."),
|
|
6877
|
+
) -> None:
|
|
6878
|
+
"""[EXPERIMENTAL] ENDPOINT_SECURITY — effective security of an endpoint handler.
|
|
6879
|
+
Reuses the endpoint model's CanonicalSecurity + run_security_audit."""
|
|
6880
|
+
_run_retrieval_intent(
|
|
6881
|
+
"endpoint-security", path, output_path, trace, anchors=(("endpoint", ref),)
|
|
6882
|
+
)
|
|
6883
|
+
|
|
6884
|
+
|
|
6885
|
+
@retrieve_app.command("call-neighborhood")
|
|
6886
|
+
def retrieve_call_neighborhood_cmd(
|
|
6887
|
+
target: str = typer.Option(..., "--target", "-t", help="Symbol (class/FQN/method)."),
|
|
6888
|
+
path: Path = typer.Argument(Path("."), help="Repository path (default: current directory)"),
|
|
6889
|
+
output_path: Optional[Path] = typer.Option(None, "--output", "-o", help="Write output to a file."),
|
|
6890
|
+
trace: bool = typer.Option(False, "--trace", help="Include the Query Plan Runtime trace."),
|
|
6891
|
+
) -> None:
|
|
6892
|
+
"""[EXPERIMENTAL] CALL_NEIGHBORHOOD — forward callees + reverse callers of a symbol.
|
|
6893
|
+
Reuses SpringSemanticModel.call_adj."""
|
|
6894
|
+
_run_retrieval_intent(
|
|
6895
|
+
"call-neighborhood", path, output_path, trace, anchors=(("symbol", target),)
|
|
6896
|
+
)
|
|
6897
|
+
|
|
6898
|
+
|
|
6899
|
+
@retrieve_app.command("execution-paths-through")
|
|
6900
|
+
def retrieve_execution_paths_cmd(
|
|
6901
|
+
target: str = typer.Option(..., "--target", "-t", help="Symbol (class/FQN/method)."),
|
|
6902
|
+
path: Path = typer.Argument(Path("."), help="Repository path (default: current directory)"),
|
|
6903
|
+
output_path: Optional[Path] = typer.Option(None, "--output", "-o", help="Write output to a file."),
|
|
6904
|
+
trace: bool = typer.Option(False, "--trace", help="Include the Query Plan Runtime trace."),
|
|
6905
|
+
) -> None:
|
|
6906
|
+
"""[EXPERIMENTAL] EXECUTION_PATHS_THROUGH — multi-hop caller reachability of a symbol.
|
|
6907
|
+
Reuses spring_impact.run_impact_chain."""
|
|
6908
|
+
_run_retrieval_intent(
|
|
6909
|
+
"execution-paths-through", path, output_path, trace, anchors=(("symbol", target),)
|
|
6910
|
+
)
|
|
6911
|
+
|
|
6912
|
+
|
|
6913
|
+
@retrieve_app.command("transactions-reaching")
|
|
6914
|
+
def retrieve_transactions_reaching_cmd(
|
|
6915
|
+
target: str = typer.Option(..., "--target", "-t", help="Symbol (class/FQN/method)."),
|
|
6916
|
+
path: Path = typer.Argument(Path("."), help="Repository path (default: current directory)"),
|
|
6917
|
+
output_path: Optional[Path] = typer.Option(None, "--output", "-o", help="Write output to a file."),
|
|
6918
|
+
trace: bool = typer.Option(False, "--trace", help="Include the Query Plan Runtime trace."),
|
|
6919
|
+
) -> None:
|
|
6920
|
+
"""[EXPERIMENTAL] TRANSACTIONS_REACHING — @Transactional boundaries that reach a symbol.
|
|
6921
|
+
Reuses run_impact_chain + the tx boundary index."""
|
|
6922
|
+
_run_retrieval_intent(
|
|
6923
|
+
"transactions-reaching", path, output_path, trace, anchors=(("symbol", target),)
|
|
6924
|
+
)
|
|
6925
|
+
|
|
6926
|
+
|
|
6927
|
+
@retrieve_app.command("subsystem-coupling")
|
|
6928
|
+
def retrieve_subsystem_coupling_cmd(
|
|
6929
|
+
path: Path = typer.Argument(Path("."), help="Repository path (default: current directory)"),
|
|
6930
|
+
output_path: Optional[Path] = typer.Option(None, "--output", "-o", help="Write output to a file."),
|
|
6931
|
+
trace: bool = typer.Option(False, "--trace", help="Include the Query Plan Runtime trace."),
|
|
6932
|
+
) -> None:
|
|
6933
|
+
"""[EXPERIMENTAL] SUBSYSTEM_COUPLING — module-graph hubs/cycles/orphans + subsystems.
|
|
6934
|
+
Reuses the module graph summary + the repo IR subsystem partition."""
|
|
6935
|
+
_run_retrieval_intent("subsystem-coupling", path, output_path, trace)
|
|
6936
|
+
|
|
6937
|
+
|
|
6512
6938
|
@app.command("cold-start")
|
|
6513
6939
|
def cold_start_cmd(
|
|
6514
6940
|
path: Path = typer.Argument(Path("."), help="Repository path (default: current directory)"),
|
sourcecode/context_graph.py
CHANGED
|
@@ -407,7 +407,7 @@ class ContextGraph:
|
|
|
407
407
|
__slots__ = (
|
|
408
408
|
"_cir", "_nodes_by_fqn", "_nodes", "_build_ms",
|
|
409
409
|
"_body_index", "_literal_index", "_guard_index", "_span_index",
|
|
410
|
-
"_class_type_index",
|
|
410
|
+
"_class_type_index", "_relations_all", "_symbols_sorted",
|
|
411
411
|
)
|
|
412
412
|
|
|
413
413
|
def __init__(self, cir: CanonicalRepositoryIR, *, build_ms: float = 0.0) -> None:
|
|
@@ -431,6 +431,14 @@ class ContextGraph:
|
|
|
431
431
|
_node_to_symbol(n) for n in raw_nodes
|
|
432
432
|
)
|
|
433
433
|
self._nodes_by_fqn: dict[str, Symbol] = {s.fqn: s for s in self._nodes}
|
|
434
|
+
# Memoized full projections (the CIR is immutable for this graph's lifetime).
|
|
435
|
+
# `relations()`/`symbols()` are called once PER FILE by per-file consumers such as
|
|
436
|
+
# `_java_contract_from_graph`; without these caches each call re-converted every
|
|
437
|
+
# edge (`_edge_to_relation`) and re-sorted every node — an O(files × edges) blow-up
|
|
438
|
+
# that made cold `ask` / `ask --agent` take minutes on large repos. Built once,
|
|
439
|
+
# filtered cheaply thereafter.
|
|
440
|
+
self._relations_all: Optional[tuple[Relation, ...]] = None
|
|
441
|
+
self._symbols_sorted: Optional[tuple[Symbol, ...]] = None
|
|
434
442
|
|
|
435
443
|
# -- construction -------------------------------------------------------
|
|
436
444
|
|
|
@@ -497,19 +505,18 @@ class ContextGraph:
|
|
|
497
505
|
set. Results are sorted by FQN for determinism. This is the primitive
|
|
498
506
|
the role-convenience methods below are thin sugar over.
|
|
499
507
|
"""
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
return out
|
|
508
|
+
if self._symbols_sorted is None:
|
|
509
|
+
self._symbols_sorted = tuple(sorted(self._nodes, key=lambda s: s.fqn))
|
|
510
|
+
# Filter over the memoized fqn-sorted set (filtering preserves that order, so the
|
|
511
|
+
# result is identical to sorting after filtering — but the sort happens once).
|
|
512
|
+
return [
|
|
513
|
+
s
|
|
514
|
+
for s in self._symbols_sorted
|
|
515
|
+
if (kind is None or s.kind == kind)
|
|
516
|
+
and (role is None or s.role == role)
|
|
517
|
+
and (annotated_with is None or s.has_annotation(annotated_with))
|
|
518
|
+
and (name_contains is None or name_contains in s.fqn)
|
|
519
|
+
]
|
|
513
520
|
|
|
514
521
|
def types(self) -> list[Symbol]:
|
|
515
522
|
"""All class/interface/enum/annotation symbols, sorted by FQN."""
|
|
@@ -575,16 +582,17 @@ class ContextGraph:
|
|
|
575
582
|
) -> list[Relation]:
|
|
576
583
|
"""All relations matching the given filters (AND-combined), in the IR's
|
|
577
584
|
stable edge order (already sorted from → type → to)."""
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
585
|
+
if self._relations_all is None:
|
|
586
|
+
# Convert every edge ONCE; filtered calls then scan the cached Relation
|
|
587
|
+
# objects without re-running `_edge_to_relation` (the cold-path hotspot).
|
|
588
|
+
self._relations_all = tuple(_edge_to_relation(e) for e in self._cir.call_graph)
|
|
589
|
+
return [
|
|
590
|
+
r
|
|
591
|
+
for r in self._relations_all
|
|
592
|
+
if (kind is None or r.kind == kind)
|
|
593
|
+
and (source is None or r.source == source)
|
|
594
|
+
and (target is None or r.target == target)
|
|
595
|
+
]
|
|
588
596
|
|
|
589
597
|
# -- inheritance / implementation (reuses cir.implementation_graph) ------
|
|
590
598
|
|