sourcecode 1.33.3__py3-none-any.whl → 1.33.4__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 +26 -11
- sourcecode/prepare_context.py +4 -0
- sourcecode/ris.py +31 -2
- {sourcecode-1.33.3.dist-info → sourcecode-1.33.4.dist-info}/METADATA +3 -3
- {sourcecode-1.33.3.dist-info → sourcecode-1.33.4.dist-info}/RECORD +9 -9
- {sourcecode-1.33.3.dist-info → sourcecode-1.33.4.dist-info}/WHEEL +0 -0
- {sourcecode-1.33.3.dist-info → sourcecode-1.33.4.dist-info}/entry_points.txt +0 -0
- {sourcecode-1.33.3.dist-info → sourcecode-1.33.4.dist-info}/licenses/LICENSE +0 -0
sourcecode/__init__.py
CHANGED
sourcecode/cli.py
CHANGED
|
@@ -658,7 +658,6 @@ def main(
|
|
|
658
658
|
env_map: bool = typer.Option(
|
|
659
659
|
False,
|
|
660
660
|
"--env-map",
|
|
661
|
-
hidden=True,
|
|
662
661
|
help="Map environment variables referenced across the codebase.",
|
|
663
662
|
),
|
|
664
663
|
code_notes: bool = typer.Option(
|
|
@@ -1880,8 +1879,9 @@ def main(
|
|
|
1880
1879
|
if _gc_early and not (_bad_gc & set(_gc_early.limitations)):
|
|
1881
1880
|
_uc = _gc_early.uncommitted_changes
|
|
1882
1881
|
if _uc:
|
|
1883
|
-
#
|
|
1884
|
-
|
|
1882
|
+
# Include untracked (new files not yet staged) so new source files
|
|
1883
|
+
# are analyzed under --changed-only, not silently treated as "clean".
|
|
1884
|
+
_allowed_changed_files = set(_uc.staged) | set(_uc.unstaged) | set(_uc.untracked)
|
|
1885
1885
|
if not _allowed_changed_files:
|
|
1886
1886
|
# Git is available and confirms no uncommitted changes.
|
|
1887
1887
|
# Do NOT fall back to a full scan — that would silently produce
|
|
@@ -1900,10 +1900,10 @@ def main(
|
|
|
1900
1900
|
changed_only = False
|
|
1901
1901
|
if _git_confirmed_clean:
|
|
1902
1902
|
_nc_payload = json.dumps({
|
|
1903
|
-
"status": "working_tree_clean",
|
|
1904
|
-
"no_changes": True,
|
|
1905
1903
|
"changed_files": [],
|
|
1906
|
-
"message": "
|
|
1904
|
+
"message": "no uncommitted changes detected",
|
|
1905
|
+
"analysis_scope": "empty",
|
|
1906
|
+
"_meta": {"changed_only": True},
|
|
1907
1907
|
}, ensure_ascii=False)
|
|
1908
1908
|
write_output(_nc_payload, output=output)
|
|
1909
1909
|
raise typer.Exit()
|
|
@@ -2626,7 +2626,14 @@ def prepare_context_cmd(
|
|
|
2626
2626
|
if _task_include("improvement_opportunities") and output.improvement_opportunities:
|
|
2627
2627
|
out["improvement_opportunities"] = output.improvement_opportunities
|
|
2628
2628
|
if _task_include("test_gaps") and output.test_gaps:
|
|
2629
|
-
|
|
2629
|
+
# Emit both the canonical name (untested_sources) and the compat alias (test_gaps)
|
|
2630
|
+
# so agents can use either. untested_sources is the correct semantic name.
|
|
2631
|
+
out["untested_sources"] = output.test_gaps
|
|
2632
|
+
out["test_gaps"] = output.test_gaps # backward compat alias
|
|
2633
|
+
if task == "generate-tests":
|
|
2634
|
+
_et_count = getattr(output, "existing_test_count", None)
|
|
2635
|
+
if _et_count is not None:
|
|
2636
|
+
out["existing_test_count"] = _et_count
|
|
2630
2637
|
# P0-2: fast-mode truncation transparency — always emit when truncated, even if test_gaps is []
|
|
2631
2638
|
# Use `is True` (strict) so MagicMock objects in tests don't trigger this branch.
|
|
2632
2639
|
if getattr(output, "truncated", False) is True:
|
|
@@ -3543,6 +3550,12 @@ def fix_bug_cmd(
|
|
|
3543
3550
|
sourcecode impact <target> — Propagate impact from a specific class
|
|
3544
3551
|
sourcecode onboard . — Full architecture context first
|
|
3545
3552
|
"""
|
|
3553
|
+
if not symptom:
|
|
3554
|
+
typer.echo(
|
|
3555
|
+
"[fix-bug] Results are significantly better with --symptom. "
|
|
3556
|
+
"Example: --symptom 'NullPointerException in PaymentService'",
|
|
3557
|
+
err=True,
|
|
3558
|
+
)
|
|
3546
3559
|
ctx.invoke(
|
|
3547
3560
|
prepare_context_cmd,
|
|
3548
3561
|
task="fix-bug",
|
|
@@ -4298,19 +4311,21 @@ def cache_status_cmd(
|
|
|
4298
4311
|
def cache_clear_cmd(
|
|
4299
4312
|
path: Path = typer.Argument(Path("."), help="Repository path (default: current directory)"),
|
|
4300
4313
|
yes: bool = typer.Option(False, "--yes", "-y", help="Skip confirmation prompt."),
|
|
4301
|
-
include_ris: bool = typer.Option(False, "--include-ris", help="
|
|
4314
|
+
include_ris: bool = typer.Option(False, "--include-ris", hidden=True, help="Alias for --all. Preserved for backward compatibility."),
|
|
4315
|
+
all_: bool = typer.Option(False, "--all", help="Also delete the RIS snapshot (ris.json.gz). By default, RIS is preserved across clears."),
|
|
4302
4316
|
) -> None:
|
|
4303
4317
|
"""Delete cached snapshots for a repository.
|
|
4304
4318
|
|
|
4305
4319
|
By default, RIS (ris.json.gz) is preserved — it is the persistent structural
|
|
4306
|
-
index used for cold-start bootstrapping. Use --
|
|
4320
|
+
index used for cold-start bootstrapping. Use --all to also clear it.
|
|
4307
4321
|
"""
|
|
4308
4322
|
from sourcecode import cache as _cm
|
|
4309
4323
|
target = Path(path).resolve()
|
|
4324
|
+
_clear_ris = include_ris or all_
|
|
4310
4325
|
if not yes:
|
|
4311
|
-
_ris_note = " (including RIS)" if
|
|
4326
|
+
_ris_note = " (including RIS)" if _clear_ris else " (RIS preserved — use --all to also clear it)"
|
|
4312
4327
|
typer.confirm(f"Delete all cache files for {target}{_ris_note}?", abort=True)
|
|
4313
|
-
removed = _cm.clear(target, clear_ris=
|
|
4328
|
+
removed = _cm.clear(target, clear_ris=_clear_ris)
|
|
4314
4329
|
typer.echo(f"Removed {removed} file(s).")
|
|
4315
4330
|
|
|
4316
4331
|
|
sourcecode/prepare_context.py
CHANGED
|
@@ -391,6 +391,8 @@ class TaskOutput:
|
|
|
391
391
|
# P0-2: fast-mode truncation transparency
|
|
392
392
|
truncated: bool = False
|
|
393
393
|
truncated_reason: Optional[str] = None
|
|
394
|
+
# generate-tests: count of existing test files found (complements untested_sources)
|
|
395
|
+
existing_test_count: Optional[int] = None
|
|
394
396
|
|
|
395
397
|
|
|
396
398
|
@dataclass
|
|
@@ -2237,6 +2239,8 @@ class TaskContextBuilder:
|
|
|
2237
2239
|
# P0-2: fast-mode truncation transparency
|
|
2238
2240
|
truncated=_fast_truncated,
|
|
2239
2241
|
truncated_reason=_fast_truncated_reason,
|
|
2242
|
+
# generate-tests: count of test files found alongside untested_sources
|
|
2243
|
+
existing_test_count=len(test_set) if task_name == "generate-tests" else None,
|
|
2240
2244
|
)
|
|
2241
2245
|
|
|
2242
2246
|
def render_prompt(self, output: TaskOutput) -> str:
|
sourcecode/ris.py
CHANGED
|
@@ -393,12 +393,40 @@ def get_cold_start_context(repo_root: Path) -> dict:
|
|
|
393
393
|
# An empty list does NOT mean "no endpoints exist" — it means the endpoint
|
|
394
394
|
# index has not been built yet. Agents must call get_endpoints to populate.
|
|
395
395
|
_api_complete = not _is_java or bool(endpoints)
|
|
396
|
+
|
|
397
|
+
# Build structural validation for Java/Spring repos.
|
|
398
|
+
# Detects when the RIS snapshot is structurally incomplete (controllers found
|
|
399
|
+
# but endpoint index was never built), so agents can decide whether to rebuild.
|
|
400
|
+
_controllers_in_map = ris.structural_map.get("controllers", [])
|
|
401
|
+
_controllers_in_api = ris.api_surface.get("controllers_index", [])
|
|
402
|
+
_controllers_found = len(_controllers_in_map) or len(_controllers_in_api)
|
|
403
|
+
_endpoints_found = len(endpoints)
|
|
404
|
+
# Spring is detected when controllers exist in structural map or api surface.
|
|
405
|
+
_spring_detected = bool(_controllers_found) or bool(_controllers_in_api)
|
|
406
|
+
_validation_status = (
|
|
407
|
+
"incomplete_snapshot"
|
|
408
|
+
if _is_java and _spring_detected and _endpoints_found == 0
|
|
409
|
+
else "valid"
|
|
410
|
+
)
|
|
411
|
+
_validation: dict = {
|
|
412
|
+
"spring_detected": _spring_detected,
|
|
413
|
+
"controllers_found": _controllers_found,
|
|
414
|
+
"endpoints_found": _endpoints_found,
|
|
415
|
+
"status": _validation_status,
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
# When the snapshot is structurally incomplete, downgrade status so agents
|
|
419
|
+
# don't assume cold_start_ready when critical sections are missing.
|
|
420
|
+
_status_base = "cold_start_stale" if stale else "cold_start_ready"
|
|
421
|
+
if _validation_status == "incomplete_snapshot" and not stale:
|
|
422
|
+
_status_base = "cold_start_incomplete"
|
|
423
|
+
|
|
396
424
|
result: dict = {
|
|
397
|
-
"status":
|
|
425
|
+
"status": _status_base,
|
|
398
426
|
"repo_id": ris.repo_id,
|
|
399
427
|
"git_head": ris.git_head,
|
|
400
428
|
"current_git_head": current_head,
|
|
401
|
-
"stale": stale,
|
|
429
|
+
"stale": stale or (_validation_status == "incomplete_snapshot"),
|
|
402
430
|
"has_uncommitted_changes": uncommitted,
|
|
403
431
|
"last_updated_at": ris.last_updated_at,
|
|
404
432
|
"cache_source": "RIS",
|
|
@@ -408,6 +436,7 @@ def get_cold_start_context(repo_root: Path) -> dict:
|
|
|
408
436
|
"entrypoints": ris.structural_map.get("entrypoints", []),
|
|
409
437
|
"endpoints": endpoints,
|
|
410
438
|
"hotspots": ris.git_context_snapshot.get("hotspots", []),
|
|
439
|
+
"validation": _validation,
|
|
411
440
|
}
|
|
412
441
|
if not endpoints and _is_java:
|
|
413
442
|
result["endpoints_hint"] = (
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: sourcecode
|
|
3
|
-
Version: 1.33.
|
|
3
|
+
Version: 1.33.4
|
|
4
4
|
Summary: Persistent structural context and ultra-fast repeated analysis for AI coding agents
|
|
5
5
|
License-File: LICENSE
|
|
6
6
|
Keywords: agents,ai,codebase,context,developer-tools,llm
|
|
@@ -39,7 +39,7 @@ Description-Content-Type: text/markdown
|
|
|
39
39
|
|
|
40
40
|
**Persistent structural context and ultra-fast repeated analysis for AI coding agents.**
|
|
41
41
|
|
|
42
|
-

|
|
43
43
|

|
|
44
44
|
|
|
45
45
|
---
|
|
@@ -113,7 +113,7 @@ pipx install sourcecode
|
|
|
113
113
|
|
|
114
114
|
```bash
|
|
115
115
|
sourcecode version
|
|
116
|
-
# sourcecode 1.33.
|
|
116
|
+
# sourcecode 1.33.4
|
|
117
117
|
```
|
|
118
118
|
|
|
119
119
|
---
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
sourcecode/__init__.py,sha256=
|
|
1
|
+
sourcecode/__init__.py,sha256=oG8RdsJRmrxoLhAnBA3rq7bWu7SPvQTfWedYeipB42k,103
|
|
2
2
|
sourcecode/adaptive_scanner.py,sha256=XffluXKzJUXrMtjEiAOnSNPZnztdIcts17T9ouHeID0,10521
|
|
3
3
|
sourcecode/architecture_analyzer.py,sha256=qh749a7ykPtGmQI1MR9y6j8TtL_jBdVYFx9YRsLqOMw,44121
|
|
4
4
|
sourcecode/architecture_summary.py,sha256=z34_6v7cSwy98cof2UVciGho7SCrZ93tiqMmq5WNzRQ,20405
|
|
@@ -7,7 +7,7 @@ sourcecode/cache.py,sha256=wAyPrXN5DqiGivnMpeEuun2xHDKfBer2_oBsh6kj_vc,30447
|
|
|
7
7
|
sourcecode/cache.tmp_new,sha256=-IvV7CojiZjqeKMln1m-lqI0QVA2uFGWmYir4XRFOUk,27970
|
|
8
8
|
sourcecode/canonical_ir.py,sha256=_HM3AUmKSdna9u4dCoU6rpgSA6HdF8gzOKZykIUCNGY,23277
|
|
9
9
|
sourcecode/classifier.py,sha256=2lYoSH3vOTkXZYPU7Go2WIet1-IuNzTWVhc-ULnXtgw,8024
|
|
10
|
-
sourcecode/cli.py,sha256=
|
|
10
|
+
sourcecode/cli.py,sha256=K2FT1wLNZuG_-9nKSOGdYbk-5GQkn4u7C2NR6IxdePY,180950
|
|
11
11
|
sourcecode/code_notes_analyzer.py,sha256=EJemNCNc9Dn-1RZYu-aNbK0ELzmsyC4s6FdHi3XyNEI,9392
|
|
12
12
|
sourcecode/confidence_analyzer.py,sha256=_jckZSxksV-OU38vbkxfVNBnWCtlCq8Vwfg23x1uspA,19054
|
|
13
13
|
sourcecode/context_scorer.py,sha256=QpChSpsmaAYz91rXA4Ue5xzQmNz_ZboZN09YOHScq1U,14679
|
|
@@ -29,14 +29,14 @@ sourcecode/metrics_analyzer.py,sha256=m0ENgtqKeBL17kUIK3fmGkgo7UfXBNHxCMj0H_Y5K7
|
|
|
29
29
|
sourcecode/output_budget.py,sha256=43307mJEyUPU3MI-QEQoVxrcAvNyUzdzF_SAPgisBQE,6603
|
|
30
30
|
sourcecode/path_filters.py,sha256=ROFRQ8eSLBEMiixK9f45-RO7um4VEEcjoD5AA4I427I,3739
|
|
31
31
|
sourcecode/pr_comment_renderer.py,sha256=smHslxiG14lrytCkq5nFrFu-qTHgA-t-LFYfdrfjz2o,14423
|
|
32
|
-
sourcecode/prepare_context.py,sha256=
|
|
32
|
+
sourcecode/prepare_context.py,sha256=aL4WS62wozw9iG_v3UrU00Qc7lGgckUB5RY5ApPblo8,205618
|
|
33
33
|
sourcecode/progress.py,sha256=qn30sWaHOkjTgXsSBmiPkz7Rsbwc5oSlIe6JNEMYp_k,3149
|
|
34
34
|
sourcecode/ranking_engine.py,sha256=ZAucq_YX2KkWUuAZf4P0lhtQ_38vEFnUhuGtSZd1S0E,12970
|
|
35
35
|
sourcecode/redactor.py,sha256=SB4hwIvg8h-hvcqKcDWaZvA-aSyn-at-BIRwa0tUv5E,3227
|
|
36
36
|
sourcecode/relevance_scorer.py,sha256=MYF4FFkveAQps9SmTeTlh6ODiBz2F--_hWNeHMLtUHQ,8405
|
|
37
37
|
sourcecode/repo_classifier.py,sha256=FG1vaWKdWXsWdl-S8hjVMiTqcwgaRXkDyvK4rPcOGtQ,22681
|
|
38
38
|
sourcecode/repository_ir.py,sha256=-NjBQUT7zyya4ng8Hq0-ChoiHZkUif9lr-Q878gmj8M,153163
|
|
39
|
-
sourcecode/ris.py,sha256=
|
|
39
|
+
sourcecode/ris.py,sha256=vkIe_v-jjceeb0Adhn-Kw5eFXE_nIkGHflOnQYPycTk,17411
|
|
40
40
|
sourcecode/runtime_classifier.py,sha256=uTAD6BDCiBLUZEDRfqk718kM4RTT_vAbfkcOI2_Xx58,18432
|
|
41
41
|
sourcecode/scanner.py,sha256=WdOQ78mMzjR1NjmKTlbxdgwinnCTfAhxCVLBEFQiFHU,8899
|
|
42
42
|
sourcecode/schema.py,sha256=aHNXDf8LGyUC8ZDE_VS9kiskC2-Oswhi_WnpdGy6HDw,24897
|
|
@@ -80,8 +80,8 @@ sourcecode/telemetry/consent.py,sha256=wLMvGNJeSSyZoNkQXpoUioY6mMv4Qdvuw7S9jAEWn
|
|
|
80
80
|
sourcecode/telemetry/events.py,sha256=oEvvulfsv5GIDWG2174gSS6tNB95w38AIYiYeifGKlE,2294
|
|
81
81
|
sourcecode/telemetry/filters.py,sha256=Asa71oRl7q3Wt_FMwuufIZJFzSYdgRNKS8LHCIyFeYE,4805
|
|
82
82
|
sourcecode/telemetry/transport.py,sha256=KJeIPCPWMdmbCP3ySGs2iUlia34U6vWne2dZsUezesw,1560
|
|
83
|
-
sourcecode-1.33.
|
|
84
|
-
sourcecode-1.33.
|
|
85
|
-
sourcecode-1.33.
|
|
86
|
-
sourcecode-1.33.
|
|
87
|
-
sourcecode-1.33.
|
|
83
|
+
sourcecode-1.33.4.dist-info/METADATA,sha256=Q9XlsPNiuahPxhrDZUU8OqtH1U_DH77rv22bnvblazA,16440
|
|
84
|
+
sourcecode-1.33.4.dist-info/WHEEL,sha256=QccIxa26bgl1E6uMy58deGWi-0aeIkkangHcxk2kWfw,87
|
|
85
|
+
sourcecode-1.33.4.dist-info/entry_points.txt,sha256=ex3F9rmbXeyDIoFQHtkEqTsKSaJow8F0LrVu8XfIktQ,57
|
|
86
|
+
sourcecode-1.33.4.dist-info/licenses/LICENSE,sha256=7DdHrU9Z_3e7dSvq4ISijZNjnuHo5NIHNiHDouMQ9JU,10491
|
|
87
|
+
sourcecode-1.33.4.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|