sourcecode 1.30.12__py3-none-any.whl → 1.30.14__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/cli.py +12 -5
- sourcecode/flow_analyzer.py +11 -11
- sourcecode/prepare_context.py +53 -60
- sourcecode/repository_ir.py +879 -120
- {sourcecode-1.30.12.dist-info → sourcecode-1.30.14.dist-info}/METADATA +3 -3
- {sourcecode-1.30.12.dist-info → sourcecode-1.30.14.dist-info}/RECORD +10 -10
- {sourcecode-1.30.12.dist-info → sourcecode-1.30.14.dist-info}/WHEEL +0 -0
- {sourcecode-1.30.12.dist-info → sourcecode-1.30.14.dist-info}/entry_points.txt +0 -0
- {sourcecode-1.30.12.dist-info → sourcecode-1.30.14.dist-info}/licenses/LICENSE +0 -0
sourcecode/__init__.py
CHANGED
sourcecode/cli.py
CHANGED
|
@@ -2015,11 +2015,18 @@ def repo_ir_cmd(
|
|
|
2015
2015
|
if not file_list:
|
|
2016
2016
|
typer.echo(
|
|
2017
2017
|
_json.dumps({
|
|
2018
|
-
"
|
|
2019
|
-
"
|
|
2020
|
-
"
|
|
2021
|
-
|
|
2022
|
-
|
|
2018
|
+
"schema_version": "final-v1",
|
|
2019
|
+
"graph": {"nodes": [], "edges": []},
|
|
2020
|
+
"analysis": {
|
|
2021
|
+
"changed_entities": [],
|
|
2022
|
+
"impacted_entities": [],
|
|
2023
|
+
"isolated_changes": [],
|
|
2024
|
+
"validated_changes": [],
|
|
2025
|
+
},
|
|
2026
|
+
"impact": {"global_score": 0, "ranked_nodes": []},
|
|
2027
|
+
"subsystems": [],
|
|
2028
|
+
"change_set": [],
|
|
2029
|
+
"audit": {"dropped_fields": []},
|
|
2023
2030
|
}, indent=2)
|
|
2024
2031
|
)
|
|
2025
2032
|
return
|
sourcecode/flow_analyzer.py
CHANGED
|
@@ -381,27 +381,27 @@ def _impact_descriptions(
|
|
|
381
381
|
|
|
382
382
|
if changed_type in _REPO_ARTIFACT_TYPES:
|
|
383
383
|
items.append(_impact_item(
|
|
384
|
-
f"{domain} persistence
|
|
385
|
-
f"{changed_class} classified as
|
|
384
|
+
f"{domain} persistence layer modified" if domain else "persistence layer modified",
|
|
385
|
+
f"{changed_class} classified as {changed_type} (artifact_type evidence)",
|
|
386
386
|
certainty,
|
|
387
387
|
))
|
|
388
388
|
elif changed_type in _SERVICE_ARTIFACT_TYPES:
|
|
389
389
|
if end_state == "DB write":
|
|
390
390
|
items.append(_impact_item(
|
|
391
|
-
f"{domain}
|
|
392
|
-
f"{changed_class} delegates to repository with DB write",
|
|
391
|
+
f"{domain} service layer: DB write in call path" if domain else "service layer: DB write in call path",
|
|
392
|
+
f"{changed_class} delegates to repository with DB write (code evidence)",
|
|
393
393
|
certainty,
|
|
394
394
|
))
|
|
395
395
|
else:
|
|
396
396
|
items.append(_impact_item(
|
|
397
|
-
f"{domain}
|
|
398
|
-
f"{changed_class} is a service
|
|
397
|
+
f"{domain} service layer modified" if domain else "service layer modified",
|
|
398
|
+
f"{changed_class} is a service (artifact_type={changed_type})",
|
|
399
399
|
certainty,
|
|
400
400
|
))
|
|
401
401
|
else:
|
|
402
402
|
items.append(_impact_item(
|
|
403
|
-
f"{domain}
|
|
404
|
-
f"{changed_class}
|
|
403
|
+
f"{domain} component modified" if domain else "component modified",
|
|
404
|
+
f"{changed_class} found in traced call path (artifact_type={changed_type})",
|
|
405
405
|
certainty,
|
|
406
406
|
))
|
|
407
407
|
|
|
@@ -440,14 +440,14 @@ def _impact_descriptions_for_controller(
|
|
|
440
440
|
domain = d
|
|
441
441
|
break
|
|
442
442
|
items.append(_impact_item(
|
|
443
|
-
f"{domain} persistence
|
|
444
|
-
"repository with DB write detected in path",
|
|
443
|
+
f"{domain} persistence layer: repository with DB write in call path" if domain else "persistence layer: repository with DB write in call path",
|
|
444
|
+
"repository with DB write detected in traced call path (code evidence)",
|
|
445
445
|
certainty,
|
|
446
446
|
))
|
|
447
447
|
else:
|
|
448
448
|
items.append(_impact_item(
|
|
449
|
-
"request handler behavior may change",
|
|
450
449
|
"controller entry point modified",
|
|
450
|
+
"controller entry point is in changed files (direct diff evidence)",
|
|
451
451
|
certainty,
|
|
452
452
|
))
|
|
453
453
|
|
sourcecode/prepare_context.py
CHANGED
|
@@ -539,23 +539,23 @@ def _read_code_signal_evidence(root: Path, file_path: str, artifact_type: str) -
|
|
|
539
539
|
|
|
540
540
|
|
|
541
541
|
_ARTIFACT_CHANGE_EFFECT: dict[str, str] = {
|
|
542
|
-
"entrypoint": "
|
|
543
|
-
"controller": "
|
|
544
|
-
"service": "
|
|
545
|
-
"repository": "
|
|
546
|
-
"mapper": "
|
|
547
|
-
"security": "
|
|
548
|
-
"spring_config": "
|
|
549
|
-
"spring_profile": "
|
|
550
|
-
"config": "
|
|
551
|
-
"build_manifest": "
|
|
552
|
-
"db_migration": "
|
|
553
|
-
"domain_model": "
|
|
554
|
-
"dto": "
|
|
555
|
-
"test": "
|
|
556
|
-
"documentation": "
|
|
557
|
-
"ide_noise": "IDE/tooling artifact
|
|
558
|
-
"source": "
|
|
542
|
+
"entrypoint": "application entrypoint (framework bootstrap / CLI handler)",
|
|
543
|
+
"controller": "HTTP routing layer (request-to-handler mapping)",
|
|
544
|
+
"service": "business logic layer (@Service component)",
|
|
545
|
+
"repository": "data access layer (persistence queries / ORM)",
|
|
546
|
+
"mapper": "SQL-object mapping layer (MyBatis mapper / query template)",
|
|
547
|
+
"security": "security component (authentication / access control configuration)",
|
|
548
|
+
"spring_config": "Spring @Configuration class (bean definitions / datasource wiring)",
|
|
549
|
+
"spring_profile": "Spring profile override (environment-specific configuration)",
|
|
550
|
+
"config": "configuration file (application properties / environment values)",
|
|
551
|
+
"build_manifest": "build manifest (dependency and plugin configuration)",
|
|
552
|
+
"db_migration": "database schema migration (DDL change pending execution)",
|
|
553
|
+
"domain_model": "domain entity (@Entity / value object)",
|
|
554
|
+
"dto": "data transfer object (serialization contract)",
|
|
555
|
+
"test": "test file (no production code modified)",
|
|
556
|
+
"documentation": "documentation file (no runtime impact)",
|
|
557
|
+
"ide_noise": "IDE/tooling artifact (no application impact)",
|
|
558
|
+
"source": "application source (artifact role requires annotation inspection)",
|
|
559
559
|
}
|
|
560
560
|
|
|
561
561
|
# Maps frontend symptom keywords → backend terms likely to contain the root cause.
|
|
@@ -1037,7 +1037,7 @@ class TaskContextBuilder:
|
|
|
1037
1037
|
_pr_review_hotspots = sorted(
|
|
1038
1038
|
[f for f, cls in _pr_changed_cls.items()
|
|
1039
1039
|
if not cls["is_noise"] and cls["artifact_type"] != "build_manifest"],
|
|
1040
|
-
key=lambda f: (_delta_impact_score_per_file.get(f) or {}).get("
|
|
1040
|
+
key=lambda f: (_delta_impact_score_per_file.get(f) or {}).get("_rank_score", 0.0),
|
|
1041
1041
|
reverse=True,
|
|
1042
1042
|
)[:8]
|
|
1043
1043
|
|
|
@@ -1123,33 +1123,29 @@ class TaskContextBuilder:
|
|
|
1123
1123
|
_has_code_ev = any(e["type"] in ("annotation", "import") for e in _evidence)
|
|
1124
1124
|
_has_symbol_ev = any(e["type"] == "symbol" for e in _evidence)
|
|
1125
1125
|
_role_basis = "annotation" if _has_code_ev else ("symbol" if _has_symbol_ev else "git_diff_only")
|
|
1126
|
-
_cls_conf = _f_cls["confidence"]
|
|
1127
1126
|
_role_obj = {
|
|
1128
|
-
"type": "inferred",
|
|
1129
|
-
"confidence": "medium" if (_has_code_ev or (_has_symbol_ev and _cls_conf == "high")) else "low",
|
|
1130
1127
|
"basis": _role_basis,
|
|
1128
|
+
"has_annotation_signal": _has_code_ev,
|
|
1129
|
+
"has_symbol_signal": _has_symbol_ev,
|
|
1131
1130
|
}
|
|
1132
1131
|
|
|
1133
|
-
# File confidence: from structured impact entry
|
|
1134
|
-
_impact_entry = _delta_impact_score_per_file.get(_f) or {}
|
|
1135
|
-
_f_conf = _impact_entry.get("confidence", "low")
|
|
1136
1132
|
_diff_source = (
|
|
1137
1133
|
DiffSourceType.GIT_RANGE.value if _f in _committed_set
|
|
1138
1134
|
else DiffSourceType.WORKTREE_UNSTAGED.value if _f in _uncommitted_set
|
|
1139
1135
|
else "unknown"
|
|
1140
1136
|
)
|
|
1137
|
+
_impact_entry = _delta_impact_score_per_file.get(_f) or {}
|
|
1141
1138
|
_entry = {
|
|
1142
1139
|
"path": _f,
|
|
1143
1140
|
"diff_source": _diff_source,
|
|
1144
1141
|
"role": _role_obj,
|
|
1145
|
-
"confidence": _f_conf,
|
|
1146
1142
|
"artifact_type": _f_atype,
|
|
1147
1143
|
"evidence": _evidence,
|
|
1148
1144
|
"change_effect": {
|
|
1149
|
-
"statement": _ARTIFACT_CHANGE_EFFECT.get(_f_atype, "
|
|
1150
|
-
"
|
|
1151
|
-
"confidence": _role_obj["confidence"],
|
|
1145
|
+
"statement": _ARTIFACT_CHANGE_EFFECT.get(_f_atype, "application source (artifact role requires annotation inspection)"),
|
|
1146
|
+
"classification_method": _f_cls.get("confidence", "low"),
|
|
1152
1147
|
},
|
|
1148
|
+
"evidence_completeness": _impact_entry.get("evidence", {}),
|
|
1153
1149
|
}
|
|
1154
1150
|
_pr_runtime_changes.append(_entry)
|
|
1155
1151
|
# Split committed vs uncommitted — never merged
|
|
@@ -2336,17 +2332,10 @@ class TaskContextBuilder:
|
|
|
2336
2332
|
return "service" # annotation-confirmed — not "core_service" (overclaim)
|
|
2337
2333
|
return "unclassified" # no role claim without evidence
|
|
2338
2334
|
|
|
2339
|
-
def _score_to_confidence(score: float) -> str:
|
|
2340
|
-
if score >= 0.60:
|
|
2341
|
-
return "high"
|
|
2342
|
-
if score >= 0.40:
|
|
2343
|
-
return "medium"
|
|
2344
|
-
return "low"
|
|
2345
|
-
|
|
2346
2335
|
def _structured_why(path: str, atype: str, module: str, role: str, risk_areas: list[str], cls_confidence: str = "low") -> str:
|
|
2347
2336
|
area = _classify_impact_area(path, risk_areas, atype)
|
|
2348
2337
|
prop = _PROPAGATION_RISK.get(atype, "low") if atype != "source" else "unknown"
|
|
2349
|
-
effect = _CHANGE_EFFECT.get(atype, "
|
|
2338
|
+
effect = _CHANGE_EFFECT.get(atype, "application source (artifact role requires annotation inspection)")
|
|
2350
2339
|
parts = [f"artifact_type: {atype}", f"classification_confidence: {cls_confidence}"]
|
|
2351
2340
|
# Only emit role/area/propagation when there is confirmed evidence (not source/unclassified)
|
|
2352
2341
|
if role not in ("unclassified",):
|
|
@@ -2431,8 +2420,7 @@ class TaskContextBuilder:
|
|
|
2431
2420
|
role = _role_in_system(path, atype, in_ep)
|
|
2432
2421
|
cls_conf = cls.get("confidence", "low")
|
|
2433
2422
|
why_str = _structured_why(path, atype, module, role, cls["risk_areas"], cls_conf)
|
|
2434
|
-
|
|
2435
|
-
reason = f"changed since {ref_label} | artifact: {atype} | confidence: {confidence}"
|
|
2423
|
+
reason = f"changed since {ref_label} | artifact: {atype}"
|
|
2436
2424
|
|
|
2437
2425
|
relevant.append(RelevantFile(path=path, role=role, score=round(score, 2), reason=reason, why=why_str))
|
|
2438
2426
|
why[path] = why_str
|
|
@@ -2485,7 +2473,7 @@ class TaskContextBuilder:
|
|
|
2485
2473
|
why_str = _structured_why(path, rel_atype, _extract_ddd_domain(path), role, rel_cls["risk_areas"], rel_conf)
|
|
2486
2474
|
why_str += f" | pulled_by: type-aware expansion from {ctx_type} '{ctx_val}'"
|
|
2487
2475
|
why_str += f" | triggered_by: {', '.join(triggers[:3])}"
|
|
2488
|
-
reason = f"expansion: {ctx_type} '{ctx_val}' | artifact: {rel_atype}
|
|
2476
|
+
reason = f"expansion: {ctx_type} '{ctx_val}' | artifact: {rel_atype}"
|
|
2489
2477
|
related.append((rel_score, path, RelevantFile(
|
|
2490
2478
|
path=path, role=role, score=rel_score, reason=reason, why=why_str
|
|
2491
2479
|
)))
|
|
@@ -2595,7 +2583,7 @@ class TaskContextBuilder:
|
|
|
2595
2583
|
_why_str += f" | pulled_by: hop-{_hop_num} import from {Path(_seed_path).name}"
|
|
2596
2584
|
_reason = (
|
|
2597
2585
|
f"hop-{_hop_num} import-dependent of {Path(_seed_path).name}"
|
|
2598
|
-
f" ({_seed_atype})
|
|
2586
|
+
f" ({_seed_atype})"
|
|
2599
2587
|
)
|
|
2600
2588
|
why[_dep_path] = _why_str
|
|
2601
2589
|
# Tests import production code but are not structural dependencies —
|
|
@@ -2670,18 +2658,18 @@ class TaskContextBuilder:
|
|
|
2670
2658
|
0.02
|
|
2671
2659
|
)
|
|
2672
2660
|
_raw_score = round(min(1.0, _base * 0.50 + _sec_w + _fw + _fanout + _ctw), 3)
|
|
2661
|
+
_caller_count = _downstream_count.get(_path, 0)
|
|
2673
2662
|
impact_score_per_file[_path] = {
|
|
2674
|
-
"
|
|
2675
|
-
"confidence": _score_to_confidence(_raw_score),
|
|
2676
|
-
"score_breakdown": {
|
|
2677
|
-
"artifact_base": round(_base * 0.50, 3),
|
|
2678
|
-
"security_weight": _sec_w,
|
|
2679
|
-
"framework_weight": _fw,
|
|
2680
|
-
"fanout_weight": round(_fanout, 3),
|
|
2681
|
-
"change_type_weight": _ctw,
|
|
2682
|
-
},
|
|
2663
|
+
"_rank_score": _raw_score, # internal ranking only — not a confidence claim
|
|
2683
2664
|
"change_types": sorted(_file_ctypes),
|
|
2684
2665
|
"diff_severity": _diff_sev,
|
|
2666
|
+
"evidence": {
|
|
2667
|
+
"has_reverse_edges": _caller_count > 0,
|
|
2668
|
+
"reverse_edge_count": _caller_count,
|
|
2669
|
+
"has_route_diff": _diff_sev == "api_change",
|
|
2670
|
+
"has_security_diff": _diff_sev == "security_change",
|
|
2671
|
+
"has_wiring_evidence": _atype in {"spring_config", "security"} and _cls.get("confidence") == "high",
|
|
2672
|
+
},
|
|
2685
2673
|
}
|
|
2686
2674
|
|
|
2687
2675
|
_CT_ORDER = ["security_change", "behavioral_change", "structural_change",
|
|
@@ -2714,24 +2702,29 @@ class TaskContextBuilder:
|
|
|
2714
2702
|
changed_subsystems.append(_subsys)
|
|
2715
2703
|
_seen_subsys.add(_subsys)
|
|
2716
2704
|
|
|
2717
|
-
# behavioral_changes:
|
|
2718
|
-
#
|
|
2719
|
-
|
|
2720
|
-
|
|
2721
|
-
|
|
2722
|
-
|
|
2723
|
-
|
|
2724
|
-
|
|
2705
|
+
# behavioral_changes: only emitted when graph evidence exists (import edges found).
|
|
2706
|
+
# Without reverse dependency graph, we cannot make traceable structural claims.
|
|
2707
|
+
# Also gated on semantic diff evidence (api_change/security_change) per file.
|
|
2708
|
+
_has_graph_ev = bool(graph_edges)
|
|
2709
|
+
behavioral_changes: list[str] = (
|
|
2710
|
+
[
|
|
2711
|
+
f"{Path(_p).name}: {_CHANGE_EFFECT.get(_cls['artifact_type'], 'application source (artifact role requires annotation inspection)')} [diff_severity={diff_severities.get(_p)}]"
|
|
2712
|
+
for _p, _cls in classifications.items()
|
|
2713
|
+
if not _cls["is_noise"]
|
|
2714
|
+
and diff_severities.get(_p, "unknown") in ("api_change", "security_change")
|
|
2715
|
+
]
|
|
2716
|
+
if _has_graph_ev else []
|
|
2717
|
+
)
|
|
2725
2718
|
|
|
2726
2719
|
def _runtime_impact(tc: dict[str, int]) -> list[str]:
|
|
2727
2720
|
_ri: list[str] = []
|
|
2728
2721
|
# Only emit claims that are evidence-backed (annotation-confirmed roles)
|
|
2729
2722
|
if "entrypoint" in tc:
|
|
2730
|
-
_ri.append("Entrypoint-classified file modified —
|
|
2723
|
+
_ri.append("Entrypoint-classified file modified — restart required before deploying to production")
|
|
2731
2724
|
if "spring_config" in tc:
|
|
2732
|
-
_ri.append("Spring
|
|
2725
|
+
_ri.append("Spring @Configuration-classified file modified — bean context rebuild required on restart")
|
|
2733
2726
|
if "security" in tc:
|
|
2734
|
-
_ri.append("Security-classified file modified —
|
|
2727
|
+
_ri.append("Security-classified file modified — inspect authentication and access control wiring")
|
|
2735
2728
|
if "db_migration" in tc:
|
|
2736
2729
|
_ri.append("Database schema migration pending — execute before deploying application")
|
|
2737
2730
|
# service transactional claim: only if @Service annotation confirmed (not source/unclassified)
|