sourcecode 1.30.21__py3-none-any.whl → 1.30.22__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 +30 -2
- sourcecode/prepare_context.py +68 -40
- {sourcecode-1.30.21.dist-info → sourcecode-1.30.22.dist-info}/METADATA +3 -3
- {sourcecode-1.30.21.dist-info → sourcecode-1.30.22.dist-info}/RECORD +8 -8
- {sourcecode-1.30.21.dist-info → sourcecode-1.30.22.dist-info}/WHEEL +0 -0
- {sourcecode-1.30.21.dist-info → sourcecode-1.30.22.dist-info}/entry_points.txt +0 -0
- {sourcecode-1.30.21.dist-info → sourcecode-1.30.22.dist-info}/licenses/LICENSE +0 -0
sourcecode/__init__.py
CHANGED
sourcecode/cli.py
CHANGED
|
@@ -1610,11 +1610,10 @@ def _serialize_relevant_file(f: Any) -> dict:
|
|
|
1610
1610
|
d = {k: v for k, v in _asdict(f).items() if v != "" and v is not None}
|
|
1611
1611
|
reason = d.pop("reason", "") or ""
|
|
1612
1612
|
why = d.pop("why", "") or ""
|
|
1613
|
+
d.pop("score", None) # score removed from public output (internal ranking only)
|
|
1613
1614
|
explanation = _make_explanation(reason, why)
|
|
1614
1615
|
if explanation:
|
|
1615
1616
|
d["explanation"] = explanation
|
|
1616
|
-
if reason:
|
|
1617
|
-
d["reason"] = reason
|
|
1618
1617
|
return d
|
|
1619
1618
|
|
|
1620
1619
|
|
|
@@ -1882,9 +1881,14 @@ def prepare_context_cmd(
|
|
|
1882
1881
|
def _task_include(field: str) -> bool:
|
|
1883
1882
|
return _content_filter.get(field, True)
|
|
1884
1883
|
|
|
1884
|
+
_run_id = hashlib.sha256(
|
|
1885
|
+
f"{task}:{target}:{since or ''}:{format or ''}:{symptom or ''}".encode()
|
|
1886
|
+
).hexdigest()[:16]
|
|
1887
|
+
|
|
1885
1888
|
out: dict[str, Any] = {
|
|
1886
1889
|
"task": output.task,
|
|
1887
1890
|
"goal": output.goal,
|
|
1891
|
+
"run_id": _run_id,
|
|
1888
1892
|
}
|
|
1889
1893
|
if _task_include("project_summary"):
|
|
1890
1894
|
out["project_summary"] = output.project_summary
|
|
@@ -1935,6 +1939,30 @@ def prepare_context_cmd(
|
|
|
1935
1939
|
_sys.stdout.buffer.write(b"\n")
|
|
1936
1940
|
_sys.stdout.buffer.flush()
|
|
1937
1941
|
raise typer.Exit(code=1)
|
|
1942
|
+
if output.ci_decision == "no_changes":
|
|
1943
|
+
# Early exit: no diff — emit minimal JSON without any analysis fields.
|
|
1944
|
+
# Prevents no_changes from ever being serialized alongside relevant_files > 0.
|
|
1945
|
+
_nc_out: dict[str, Any] = {
|
|
1946
|
+
"task": output.task,
|
|
1947
|
+
"ci_decision": "no_changes",
|
|
1948
|
+
"summary": "No changes detected",
|
|
1949
|
+
}
|
|
1950
|
+
if output.since:
|
|
1951
|
+
_nc_out["since"] = output.since
|
|
1952
|
+
if output.analysis_scope:
|
|
1953
|
+
_nc_out["analysis_scope"] = output.analysis_scope
|
|
1954
|
+
_nc_json = json.dumps(_nc_out, indent=2, ensure_ascii=False)
|
|
1955
|
+
if output_path is not None:
|
|
1956
|
+
output_path.write_text(_nc_json, encoding="utf-8")
|
|
1957
|
+
else:
|
|
1958
|
+
import sys as _sys
|
|
1959
|
+
_sys.stdout.buffer.write(_nc_json.encode("utf-8"))
|
|
1960
|
+
_sys.stdout.buffer.write(b"\n")
|
|
1961
|
+
_sys.stdout.buffer.flush()
|
|
1962
|
+
if copy:
|
|
1963
|
+
_copy_to_clipboard(_nc_json)
|
|
1964
|
+
typer.echo("✓ copied to clipboard", err=True)
|
|
1965
|
+
raise typer.Exit()
|
|
1938
1966
|
if output.ci_decision:
|
|
1939
1967
|
out["ci_decision"] = output.ci_decision
|
|
1940
1968
|
if output.since:
|
sourcecode/prepare_context.py
CHANGED
|
@@ -377,6 +377,25 @@ class TaskOutput:
|
|
|
377
377
|
analysis_scope: dict = field(default_factory=dict)
|
|
378
378
|
|
|
379
379
|
|
|
380
|
+
@dataclass
|
|
381
|
+
class CanonicalAnalysisIR:
|
|
382
|
+
"""Shared intermediate representation produced by _build_delta_impact.
|
|
383
|
+
|
|
384
|
+
Both delta and review-pr derive their task-specific output from this IR.
|
|
385
|
+
Never recalculate logic per command — render views from this single object.
|
|
386
|
+
"""
|
|
387
|
+
relevant_files: list[RelevantFile]
|
|
388
|
+
impact_summary: str
|
|
389
|
+
affected_modules: list[str]
|
|
390
|
+
risk_areas: list[dict]
|
|
391
|
+
why_these_files: dict[str, str]
|
|
392
|
+
analysis_gaps: list[str]
|
|
393
|
+
system_impact: dict
|
|
394
|
+
change_type: list[str]
|
|
395
|
+
dependency_graph_summary: dict
|
|
396
|
+
impact_score_per_file: dict
|
|
397
|
+
|
|
398
|
+
|
|
380
399
|
# ─────────────────────────────────────────────────────────────────────────────
|
|
381
400
|
# Builder
|
|
382
401
|
# ─────────────────────────────────────────────────────────────────────────────
|
|
@@ -934,7 +953,8 @@ class TaskContextBuilder:
|
|
|
934
953
|
test_set = {p for p in all_paths if self._is_test(p)}
|
|
935
954
|
source_set = {p for p in all_paths if not self._is_test(p) and self._is_source(p)}
|
|
936
955
|
|
|
937
|
-
# Delta
|
|
956
|
+
# Delta and review-pr share CanonicalAnalysisIR — computed once, rendered per task.
|
|
957
|
+
_ir: Optional[CanonicalAnalysisIR] = None
|
|
938
958
|
_delta_impact_summary: Optional[str] = None
|
|
939
959
|
_delta_affected_modules: list[str] = []
|
|
940
960
|
_delta_risk_areas: list[dict] = []
|
|
@@ -947,23 +967,22 @@ class TaskContextBuilder:
|
|
|
947
967
|
|
|
948
968
|
if task_name in ("delta", "review-pr"):
|
|
949
969
|
_delta_changed_list: list[str] = sorted(_delta_files) if _delta_files else []
|
|
950
|
-
(
|
|
951
|
-
relevant_files,
|
|
952
|
-
_delta_impact_summary,
|
|
953
|
-
_delta_affected_modules,
|
|
954
|
-
_delta_risk_areas,
|
|
955
|
-
_delta_why,
|
|
956
|
-
_delta_analysis_gaps,
|
|
957
|
-
_delta_system_impact,
|
|
958
|
-
_delta_change_type,
|
|
959
|
-
_delta_dep_graph_summary,
|
|
960
|
-
_delta_impact_score_per_file,
|
|
961
|
-
) = self._build_delta_impact(
|
|
970
|
+
_ir = self._build_delta_impact(
|
|
962
971
|
changed_files=_delta_changed_list,
|
|
963
972
|
all_paths=all_paths,
|
|
964
973
|
entry_points=entry_points,
|
|
965
974
|
since=since,
|
|
966
975
|
)
|
|
976
|
+
relevant_files = _ir.relevant_files
|
|
977
|
+
_delta_impact_summary = _ir.impact_summary
|
|
978
|
+
_delta_affected_modules = _ir.affected_modules
|
|
979
|
+
_delta_risk_areas = _ir.risk_areas
|
|
980
|
+
_delta_why = _ir.why_these_files
|
|
981
|
+
_delta_analysis_gaps = _ir.analysis_gaps
|
|
982
|
+
_delta_system_impact = _ir.system_impact
|
|
983
|
+
_delta_change_type = _ir.change_type
|
|
984
|
+
_delta_dep_graph_summary = _ir.dependency_graph_summary
|
|
985
|
+
_delta_impact_score_per_file = _ir.impact_score_per_file
|
|
967
986
|
else:
|
|
968
987
|
relevant_files = self._rank_files(
|
|
969
988
|
task_name, spec, all_paths, entry_set, test_set,
|
|
@@ -2297,13 +2316,10 @@ class TaskContextBuilder:
|
|
|
2297
2316
|
all_paths: list[str],
|
|
2298
2317
|
entry_points: list,
|
|
2299
2318
|
since: Optional[str],
|
|
2300
|
-
) ->
|
|
2319
|
+
) -> "CanonicalAnalysisIR":
|
|
2301
2320
|
"""Build incremental impact analysis for changed files.
|
|
2302
2321
|
|
|
2303
|
-
Returns
|
|
2304
|
-
(relevant_files, impact_summary, affected_modules, risk_areas,
|
|
2305
|
-
why_these_files, analysis_gaps)
|
|
2306
|
-
|
|
2322
|
+
Returns CanonicalAnalysisIR — the shared IR consumed by delta and review-pr views.
|
|
2307
2323
|
Changed files are always included in relevant_files (never dropped by score).
|
|
2308
2324
|
Related files are expanded type-aware: controller→service→repository→mapper chain.
|
|
2309
2325
|
Scoring is hierarchical by artifact_type, not by heuristic impact_level.
|
|
@@ -2471,6 +2487,18 @@ class TaskContextBuilder:
|
|
|
2471
2487
|
return "data_access"
|
|
2472
2488
|
if atype == "service":
|
|
2473
2489
|
return "service" # annotation-confirmed — not "core_service" (overclaim)
|
|
2490
|
+
# Name-pattern heuristics — only when atype alone gave no verdict.
|
|
2491
|
+
# These are INFERRED (LOW CONFIDENCE) — stem match, not annotation evidence.
|
|
2492
|
+
if any(kw in stem_lower for kw in ("validator", "validation")):
|
|
2493
|
+
return "validation_component"
|
|
2494
|
+
if any(kw in stem_lower for kw in ("controller", "resource", "endpoint", "rest")):
|
|
2495
|
+
return "external_interface"
|
|
2496
|
+
if any(kw in stem_lower for kw in ("service", "svc", "usecase", "facade")):
|
|
2497
|
+
return "service"
|
|
2498
|
+
if any(kw in stem_lower for kw in ("repository", "repo", "dao", "store")):
|
|
2499
|
+
return "data_access"
|
|
2500
|
+
if any(kw in stem_lower for kw in ("config", "configuration", "settings", "properties")):
|
|
2501
|
+
return "configuration"
|
|
2474
2502
|
return "unclassified" # no role claim without evidence
|
|
2475
2503
|
|
|
2476
2504
|
def _structured_why(path: str, atype: str, module: str, role: str, risk_areas: list[str], cls_confidence: str = "low") -> str:
|
|
@@ -2491,17 +2519,17 @@ class TaskContextBuilder:
|
|
|
2491
2519
|
return " | ".join(parts)
|
|
2492
2520
|
|
|
2493
2521
|
if not changed_files:
|
|
2494
|
-
return (
|
|
2495
|
-
[],
|
|
2496
|
-
"No changes detected — verify the git ref passed to --since",
|
|
2497
|
-
[],
|
|
2498
|
-
[],
|
|
2499
|
-
{},
|
|
2500
|
-
["No changed files found. Check that --since ref exists and the diff is non-empty."],
|
|
2501
|
-
{},
|
|
2502
|
-
[],
|
|
2503
|
-
{"edges": [], "propagation_depth": 0},
|
|
2504
|
-
{},
|
|
2522
|
+
return CanonicalAnalysisIR(
|
|
2523
|
+
relevant_files=[],
|
|
2524
|
+
impact_summary="No changes detected — verify the git ref passed to --since",
|
|
2525
|
+
affected_modules=[],
|
|
2526
|
+
risk_areas=[],
|
|
2527
|
+
why_these_files={},
|
|
2528
|
+
analysis_gaps=["No changed files found. Check that --since ref exists and the diff is non-empty."],
|
|
2529
|
+
system_impact={},
|
|
2530
|
+
change_type=[],
|
|
2531
|
+
dependency_graph_summary={"edges": [], "propagation_depth": 0},
|
|
2532
|
+
impact_score_per_file={},
|
|
2505
2533
|
)
|
|
2506
2534
|
|
|
2507
2535
|
ep_paths = {ep.path for ep in entry_points}
|
|
@@ -3026,17 +3054,17 @@ class TaskContextBuilder:
|
|
|
3026
3054
|
" — related file expansion uses directory proximity only"
|
|
3027
3055
|
)
|
|
3028
3056
|
|
|
3029
|
-
return (
|
|
3030
|
-
relevant,
|
|
3031
|
-
impact_summary,
|
|
3032
|
-
sorted(affected_modules_set),
|
|
3033
|
-
risk_areas_out,
|
|
3034
|
-
why,
|
|
3035
|
-
analysis_gaps,
|
|
3036
|
-
system_impact,
|
|
3037
|
-
aggregate_change_type,
|
|
3038
|
-
dependency_graph_summary,
|
|
3039
|
-
impact_score_per_file,
|
|
3057
|
+
return CanonicalAnalysisIR(
|
|
3058
|
+
relevant_files=relevant,
|
|
3059
|
+
impact_summary=impact_summary,
|
|
3060
|
+
affected_modules=sorted(affected_modules_set),
|
|
3061
|
+
risk_areas=risk_areas_out,
|
|
3062
|
+
why_these_files=why,
|
|
3063
|
+
analysis_gaps=analysis_gaps,
|
|
3064
|
+
system_impact=system_impact,
|
|
3065
|
+
change_type=aggregate_change_type,
|
|
3066
|
+
dependency_graph_summary=dependency_graph_summary,
|
|
3067
|
+
impact_score_per_file=impact_score_per_file,
|
|
3040
3068
|
)
|
|
3041
3069
|
|
|
3042
3070
|
def _resolve_git_baseline(self, since: Optional[str]) -> dict[str, Any]:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: sourcecode
|
|
3
|
-
Version: 1.30.
|
|
3
|
+
Version: 1.30.22
|
|
4
4
|
Summary: Deterministic codebase context for AI coding agents
|
|
5
5
|
License: Apache License
|
|
6
6
|
Version 2.0, January 2004
|
|
@@ -221,7 +221,7 @@ Description-Content-Type: text/markdown
|
|
|
221
221
|
|
|
222
222
|
**Deterministic, behavior-aware codebase context for AI agents and PR review.**
|
|
223
223
|
|
|
224
|
-

|
|
225
225
|

|
|
226
226
|
|
|
227
227
|
---
|
|
@@ -257,7 +257,7 @@ pipx install sourcecode
|
|
|
257
257
|
|
|
258
258
|
```bash
|
|
259
259
|
sourcecode version
|
|
260
|
-
# sourcecode 1.30.
|
|
260
|
+
# sourcecode 1.30.22
|
|
261
261
|
```
|
|
262
262
|
|
|
263
263
|
---
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
sourcecode/__init__.py,sha256=
|
|
1
|
+
sourcecode/__init__.py,sha256=d5lEITIIf1zIOm689tAJlsrD77TynMzXXXt1H2tvxjk,104
|
|
2
2
|
sourcecode/adaptive_scanner.py,sha256=RTNExwWPXzjgLaRueT7UuxkPj5ZEToWjGbx1j0LSZ9E,10250
|
|
3
3
|
sourcecode/architecture_analyzer.py,sha256=MyBa0Hf5HmkudZQDLKrjcWDKETXETXl0mQX1swtTwAA,39091
|
|
4
4
|
sourcecode/architecture_summary.py,sha256=z34_6v7cSwy98cof2UVciGho7SCrZ93tiqMmq5WNzRQ,20405
|
|
5
5
|
sourcecode/ast_extractor.py,sha256=XgrZg2DcWcUm9r87cRG3KGO7IK2TIL_N-CvhSbUmmh4,49901
|
|
6
6
|
sourcecode/classifier.py,sha256=pYve2J1LqtYssU3lYLMDz18PT-CjN5c18QYE7R_IG1Q,7507
|
|
7
|
-
sourcecode/cli.py,sha256=
|
|
7
|
+
sourcecode/cli.py,sha256=MhXLytfQdGp4L25c6gbhfJyeL5R11ox-wGo-wrO5Ph8,93201
|
|
8
8
|
sourcecode/code_notes_analyzer.py,sha256=y1MJBnPZHYp4i6cQCXUb9ATIyifS_qMQWjw_8lPkpsU,9215
|
|
9
9
|
sourcecode/confidence_analyzer.py,sha256=xw_Jv8pAd0wd8t2vvQlorw8Ih0rSF3YCoFS8K-_4aXg,15762
|
|
10
10
|
sourcecode/context_scorer.py,sha256=QpChSpsmaAYz91rXA4Ue5xzQmNz_ZboZN09YOHScq1U,14679
|
|
@@ -22,7 +22,7 @@ sourcecode/git_analyzer.py,sha256=0Gyj-vMpIIN4nfriKXVRouNYBeJ59s6pQDX2Xu9Pq-U,13
|
|
|
22
22
|
sourcecode/graph_analyzer.py,sha256=iUK-7pSV-cvGqqD2hENdYmhnm0wcXFEyK-xnu5ul8OU,62515
|
|
23
23
|
sourcecode/metrics_analyzer.py,sha256=m0ENgtqKeBL17kUIK3fmGkgo7UfXBNHxCMj0H_Y5K7c,22750
|
|
24
24
|
sourcecode/pr_comment_renderer.py,sha256=k5pCIP6iBNwy5UYPxu47CAq-62j4E9QZZOPyL3trH80,14799
|
|
25
|
-
sourcecode/prepare_context.py,sha256=
|
|
25
|
+
sourcecode/prepare_context.py,sha256=g36iiJ_7XnDR1-M68vp0Pyb9v_n387G8JdcxXYj0TSI,160472
|
|
26
26
|
sourcecode/progress.py,sha256=qn30sWaHOkjTgXsSBmiPkz7Rsbwc5oSlIe6JNEMYp_k,3149
|
|
27
27
|
sourcecode/ranking_engine.py,sha256=virVglafZufioHpZpwktjMvUiL0TZELWQCQnQNV8dFo,9360
|
|
28
28
|
sourcecode/redactor.py,sha256=xuGcadGEHaPw4qZXlMDvzMCsr4VOkdp3oBQptHyJk8c,2884
|
|
@@ -64,8 +64,8 @@ sourcecode/telemetry/consent.py,sha256=wLMvGNJeSSyZoNkQXpoUioY6mMv4Qdvuw7S9jAEWn
|
|
|
64
64
|
sourcecode/telemetry/events.py,sha256=oEvvulfsv5GIDWG2174gSS6tNB95w38AIYiYeifGKlE,2294
|
|
65
65
|
sourcecode/telemetry/filters.py,sha256=Asa71oRl7q3Wt_FMwuufIZJFzSYdgRNKS8LHCIyFeYE,4805
|
|
66
66
|
sourcecode/telemetry/transport.py,sha256=KJeIPCPWMdmbCP3ySGs2iUlia34U6vWne2dZsUezesw,1560
|
|
67
|
-
sourcecode-1.30.
|
|
68
|
-
sourcecode-1.30.
|
|
69
|
-
sourcecode-1.30.
|
|
70
|
-
sourcecode-1.30.
|
|
71
|
-
sourcecode-1.30.
|
|
67
|
+
sourcecode-1.30.22.dist-info/METADATA,sha256=01gxhfG0_4V4qosEA-V3HnFungaPYvRLR2wTs3aVsz0,28956
|
|
68
|
+
sourcecode-1.30.22.dist-info/WHEEL,sha256=QccIxa26bgl1E6uMy58deGWi-0aeIkkangHcxk2kWfw,87
|
|
69
|
+
sourcecode-1.30.22.dist-info/entry_points.txt,sha256=ex3F9rmbXeyDIoFQHtkEqTsKSaJow8F0LrVu8XfIktQ,57
|
|
70
|
+
sourcecode-1.30.22.dist-info/licenses/LICENSE,sha256=7DdHrU9Z_3e7dSvq4ISijZNjnuHo5NIHNiHDouMQ9JU,10491
|
|
71
|
+
sourcecode-1.30.22.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|