sourcecode 1.33.2__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 CHANGED
@@ -1,3 +1,3 @@
1
1
  """sourcecode — Deterministic codebase context maps for AI coding agents."""
2
2
 
3
- __version__ = "1.33.2"
3
+ __version__ = "1.33.4"
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
- # WORKTREE_UNSTAGED + WORKTREE_STAGED only; untracked excluded
1884
- _allowed_changed_files = set(_uc.staged) | set(_uc.unstaged)
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": "No uncommitted changes detected — working tree is clean.",
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
- out["test_gaps"] = output.test_gaps
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="Also delete the RIS snapshot (ris.json.gz). By default, RIS is preserved across clears."),
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 --include-ris to also clear it.
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 include_ris else " (RIS preserved — use --include-ris to also clear it)"
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=include_ris)
4328
+ removed = _cm.clear(target, clear_ris=_clear_ris)
4314
4329
  typer.echo(f"Removed {removed} file(s).")
4315
4330
 
4316
4331
 
@@ -4320,7 +4335,11 @@ def cache_warm_cmd(
4320
4335
  compact: bool = typer.Option(True, "--compact/--no-compact", help="Warm compact view (default: on)."),
4321
4336
  agent: bool = typer.Option(False, "--agent", help="Also warm agent view."),
4322
4337
  ) -> None:
4323
- """Pre-populate the cache by running a fresh analysis."""
4338
+ """Pre-populate the cache by running a fresh analysis.
4339
+
4340
+ Runs a full analysis to populate L1/L2 caches and rebuild the RIS
4341
+ (Repository Intelligence Snapshot). Useful after a merge/pull in CI.
4342
+ """
4324
4343
  import shutil as _shutil
4325
4344
  import subprocess as _sub
4326
4345
  import sys as _sys
@@ -4334,7 +4353,7 @@ def cache_warm_cmd(
4334
4353
  cmd.append("--agent")
4335
4354
  result = _sub.run(cmd, capture_output=True, text=True)
4336
4355
  if result.returncode == 0:
4337
- typer.echo("Cache warmed.", err=True)
4356
+ typer.echo("Cache warmed (L1/L2 + RIS rebuilt).", err=True)
4338
4357
  else:
4339
4358
  typer.echo(f"Warm failed (exit {result.returncode}).", err=True)
4340
4359
  if result.stderr:
@@ -4342,6 +4361,88 @@ def cache_warm_cmd(
4342
4361
  raise typer.Exit(code=result.returncode)
4343
4362
 
4344
4363
 
4364
+ @cache_app.command("freshness")
4365
+ def cache_freshness_cmd(
4366
+ path: Path = typer.Argument(Path("."), help="Repository path (default: current directory)"),
4367
+ json_output: bool = typer.Option(False, "--json", help="Output as JSON."),
4368
+ ) -> None:
4369
+ """Report RIS freshness relative to the current git HEAD.
4370
+
4371
+ Answers: is the cached snapshot current? How many commits behind is it?
4372
+
4373
+ \b
4374
+ Output fields:
4375
+ fresh — True when RIS HEAD matches current HEAD and no uncommitted changes
4376
+ current_git_head — Current repo HEAD (short SHA)
4377
+ ris_git_head — HEAD stored in RIS when it was last built
4378
+ delta_commits — Number of commits between ris_git_head and HEAD (0 = in sync)
4379
+ has_uncommitted_changes — Working tree has staged/unstaged changes
4380
+ ris_exists — False when no RIS has been built yet
4381
+ ris_last_updated_at — ISO-8601 timestamp of last RIS write
4382
+ """
4383
+ import json as _json
4384
+ import subprocess as _sub
4385
+ from sourcecode import cache as _cm
4386
+ from sourcecode.ris import _has_uncommitted_changes as _huc
4387
+ from sourcecode.ris import load_ris as _lris
4388
+
4389
+ target = Path(path).resolve()
4390
+ current_head = _cm._get_git_head(target)
4391
+ ris = _lris(target)
4392
+
4393
+ if ris is None:
4394
+ result: dict = {
4395
+ "fresh": False,
4396
+ "ris_exists": False,
4397
+ "current_git_head": current_head,
4398
+ "ris_git_head": None,
4399
+ "delta_commits": None,
4400
+ "has_uncommitted_changes": _huc(target),
4401
+ "ris_last_updated_at": None,
4402
+ }
4403
+ else:
4404
+ ris_head = ris.git_head
4405
+ head_matches = bool(current_head and ris_head and current_head == ris_head)
4406
+ uncommitted = _huc(target)
4407
+
4408
+ # Count commits between ris_head and current HEAD
4409
+ delta = None
4410
+ if ris_head and current_head and ris_head != current_head:
4411
+ try:
4412
+ _r = _sub.run(
4413
+ ["git", "-C", str(target), "rev-list", "--count", f"{ris_head}..HEAD"],
4414
+ capture_output=True, text=True, timeout=5,
4415
+ )
4416
+ if _r.returncode == 0:
4417
+ delta = int(_r.stdout.strip())
4418
+ except Exception:
4419
+ pass
4420
+ elif head_matches:
4421
+ delta = 0
4422
+
4423
+ result = {
4424
+ "fresh": head_matches and not uncommitted,
4425
+ "ris_exists": True,
4426
+ "current_git_head": current_head,
4427
+ "ris_git_head": ris_head,
4428
+ "delta_commits": delta,
4429
+ "has_uncommitted_changes": uncommitted,
4430
+ "ris_last_updated_at": ris.last_updated_at,
4431
+ }
4432
+
4433
+ if json_output:
4434
+ typer.echo(_json.dumps(result, indent=2, ensure_ascii=False))
4435
+ else:
4436
+ _fresh_tag = "FRESH" if result["fresh"] else "STALE"
4437
+ typer.echo(f"Status: {_fresh_tag}")
4438
+ typer.echo(f"Current HEAD: {result['current_git_head'] or '(unknown)'}")
4439
+ typer.echo(f"RIS HEAD: {result.get('ris_git_head') or '(none)'}")
4440
+ if result.get("delta_commits") is not None:
4441
+ typer.echo(f"Delta: {result['delta_commits']} commit(s) behind")
4442
+ typer.echo(f"Uncommitted: {result['has_uncommitted_changes']}")
4443
+ typer.echo(f"RIS updated: {result.get('ris_last_updated_at') or 'never'}")
4444
+
4445
+
4345
4446
  # ── Entry point ───────────────────────────────────────────────────────────────
4346
4447
 
4347
4448
  def main_entry() -> None:
sourcecode/mcp/server.py CHANGED
@@ -215,7 +215,10 @@ def get_agent_context(repo_path: str = ".", git_context: bool = False) -> dict:
215
215
 
216
216
  @mcp.tool()
217
217
  def get_endpoints(repo_path: str = ".") -> dict:
218
- """REST API endpoint surface extraction from Java source files.
218
+ """REST API endpoint surface extraction from Java source files. JAVA ONLY.
219
+
220
+ Do NOT call this on non-Java repositories — it will return empty results.
221
+ Use get_compact_context or get_agent_context for non-Java repos.
219
222
 
220
223
  Maps to: sourcecode endpoints <repo_path>
221
224
  Returns: endpoints list with method, path, controller, handler fields;
@@ -230,7 +233,7 @@ def get_endpoints(repo_path: str = ".") -> dict:
230
233
  Supports Spring MVC (@GetMapping etc.) and JAX-RS (@GET/@POST etc.).
231
234
  Security annotations detected: @RolesAllowed, @PermitAll, @DenyAll,
232
235
  @Authenticated, @PreAuthorize, @Secured, @SecurityRequirement, @M3FiltroSeguridad.
233
- repo_path: absolute path to the repository (default: current working directory).
236
+ repo_path: absolute path to the Java repository (default: current working directory).
234
237
  """
235
238
  _raw = repo_path
236
239
  try:
@@ -275,25 +278,43 @@ def get_module_context(repo_path: str = ".", module: str = "") -> dict:
275
278
  )
276
279
 
277
280
 
281
+ def _auto_since(repo_path: str) -> str:
282
+ """Detect best merge-base for delta: origin/main > origin/master > HEAD~1."""
283
+ import subprocess as _sp
284
+ for base in ("origin/main", "origin/master"):
285
+ try:
286
+ r = _sp.run(
287
+ ["git", "-C", repo_path, "merge-base", "HEAD", base],
288
+ capture_output=True, text=True, timeout=5,
289
+ )
290
+ if r.returncode == 0 and r.stdout.strip():
291
+ return r.stdout.strip()
292
+ except Exception:
293
+ pass
294
+ return "HEAD~1"
295
+
296
+
278
297
  @mcp.tool()
279
- def get_delta(repo_path: str = ".", since: str = "HEAD~1") -> dict:
298
+ def get_delta(repo_path: str = ".", since: str = "") -> dict:
280
299
  """Incremental context: git-changed files since a reference commit.
281
300
 
282
301
  Maps to: sourcecode prepare-context delta <repo_path> --since <since>
283
302
  repo_path: absolute path to the repository (default: current working directory).
284
303
  since: git ref to diff against (e.g. HEAD~3, main, origin/main).
304
+ If empty or omitted, auto-detects merge-base with origin/main (or
305
+ origin/master). Falls back to HEAD~1 if no remote branch found.
306
+ Pass "HEAD~1" explicitly to force single-commit diff.
285
307
  """
286
308
  _raw = repo_path
287
309
  try:
288
310
  if not isinstance(repo_path, str):
289
311
  return _err("repo_path must be a string", "INVALID_ARGUMENT")
290
- if not isinstance(since, str) or not since.strip():
291
- return _err("since must be a non-empty git ref", "INVALID_ARGUMENT")
292
312
  repo_path = _normalize_repo_path(repo_path)
293
313
  _path_err = _check_repo_path(repo_path)
294
314
  if _path_err is not None:
295
315
  return _path_err
296
- return _execute(["prepare-context", "delta", repo_path, "--since", since])
316
+ _since = since.strip() if isinstance(since, str) and since.strip() else _auto_since(repo_path)
317
+ return _execute(["prepare-context", "delta", repo_path, "--since", _since])
297
318
  except Exception as exc:
298
319
  return _err(
299
320
  f"Internal error: {type(exc).__name__}: {exc} — repo_path recibido: {_raw}",
@@ -301,6 +322,40 @@ def get_delta(repo_path: str = ".", since: str = "HEAD~1") -> dict:
301
322
  )
302
323
 
303
324
 
325
+ @mcp.tool()
326
+ def check_freshness(repo_path: str = ".") -> dict:
327
+ """Report RIS freshness relative to the current git HEAD.
328
+
329
+ Answers instantly: is the cached snapshot current? How many commits behind?
330
+ Use before deciding whether to call get_compact_context for a refresh.
331
+
332
+ Returns:
333
+ fresh (bool) — True when RIS HEAD == current HEAD and no uncommitted changes
334
+ current_git_head (str) — Current repo HEAD (short SHA)
335
+ ris_git_head (str|null) — HEAD stored in RIS at last build
336
+ delta_commits (int|null) — Commits between ris_git_head and HEAD (0 = in sync)
337
+ has_uncommitted_changes — Working tree has staged or unstaged changes
338
+ ris_exists (bool) — False when no RIS built yet
339
+ ris_last_updated_at (str) — ISO-8601 timestamp of last RIS write
340
+
341
+ repo_path: absolute path to the repository (default: current working directory).
342
+ """
343
+ _raw = repo_path
344
+ try:
345
+ if not isinstance(repo_path, str):
346
+ return _err("repo_path must be a string", "INVALID_ARGUMENT")
347
+ repo_path = _normalize_repo_path(repo_path)
348
+ _path_err = _check_repo_path(repo_path)
349
+ if _path_err is not None:
350
+ return _path_err
351
+ return _execute(["cache", "freshness", repo_path, "--json"])
352
+ except Exception as exc:
353
+ return _err(
354
+ f"Internal error: {type(exc).__name__}: {exc} — repo_path: {_raw}",
355
+ "INTERNAL_ERROR",
356
+ )
357
+
358
+
304
359
  @mcp.tool()
305
360
  def get_ir_summary(repo_path: str = ".") -> dict:
306
361
  """Deterministic symbol-level IR summary for Java repositories. Java only.
@@ -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
@@ -384,30 +384,65 @@ def get_cold_start_context(repo_root: Path) -> dict:
384
384
  uncommitted = _has_uncommitted_changes(repo_root)
385
385
 
386
386
  endpoints = ris.api_surface.get("endpoints", [])
387
+ _is_java = (
388
+ (repo_root / "pom.xml").exists()
389
+ or (repo_root / "build.gradle").exists()
390
+ or (repo_root / "build.gradle.kts").exists()
391
+ )
392
+ # api_surface_complete: False when this is a Java repo but endpoints are absent.
393
+ # An empty list does NOT mean "no endpoints exist" — it means the endpoint
394
+ # index has not been built yet. Agents must call get_endpoints to populate.
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
+
387
424
  result: dict = {
388
- "status": "cold_start_stale" if stale else "cold_start_ready",
425
+ "status": _status_base,
389
426
  "repo_id": ris.repo_id,
390
427
  "git_head": ris.git_head,
391
428
  "current_git_head": current_head,
392
- "stale": stale,
429
+ "stale": stale or (_validation_status == "incomplete_snapshot"),
393
430
  "has_uncommitted_changes": uncommitted,
394
431
  "last_updated_at": ris.last_updated_at,
395
432
  "cache_source": "RIS",
396
433
  "data_scope": "RIS_BOOTSTRAP",
434
+ "api_surface_complete": _api_complete,
397
435
  "summary": ris.compact_summary,
398
436
  "entrypoints": ris.structural_map.get("entrypoints", []),
399
437
  "endpoints": endpoints,
400
438
  "hotspots": ris.git_context_snapshot.get("hotspots", []),
439
+ "validation": _validation,
401
440
  }
402
- if not endpoints:
403
- _is_java = (repo_root / "pom.xml").exists() or \
404
- (repo_root / "build.gradle").exists() or \
405
- (repo_root / "build.gradle.kts").exists()
406
- if _is_java:
407
- result["endpoints_hint"] = (
408
- "Java repo detected but no endpoint index found. "
409
- "Call get_endpoints (or: sourcecode endpoints <path>) to populate."
410
- )
441
+ if not endpoints and _is_java:
442
+ result["endpoints_hint"] = (
443
+ "Java repo detected but no endpoint index found. "
444
+ "Call get_endpoints (or: sourcecode endpoints <path>) to populate."
445
+ )
411
446
  return result
412
447
  except Exception:
413
448
  return {"status": "no_ris"}
sourcecode/serializer.py CHANGED
@@ -631,9 +631,12 @@ def _bootstrap_structured(eps: list) -> "Optional[dict[str, Any]]":
631
631
  if security:
632
632
  result["security"] = security
633
633
  if controllers:
634
- # Count unique files (classes) vs total entries (methods/endpoints)
634
+ # Each controller file generates one EntryPoint regardless of how many
635
+ # handler methods it contains. controller_classes == len(controllers)
636
+ # always (deduplicated by path in _scan_java_file_for_entry_points).
637
+ # "methods" is therefore removed from the note — use `sourcecode endpoints`
638
+ # for per-method HTTP surface.
635
639
  controller_classes = len({c["path"] for c in controllers})
636
- controller_methods = len(controllers)
637
640
 
638
641
  # Extract all DDD module names from controller paths and group by domain area.
639
642
  # Path pattern: .../ddd/{module}/infrastructure/rest/*Controller.java
@@ -655,9 +658,8 @@ def _bootstrap_structured(eps: list) -> "Optional[dict[str, Any]]":
655
658
  module_names.append(module)
656
659
 
657
660
  _ctrl_note = (
658
- f"{controller_methods} detected entry-point methods across "
659
- f"{controller_classes} controller classes"
660
- f" (use 'sourcecode endpoints' for full surface)"
661
+ f"{controller_classes} controller classes detected"
662
+ f" (use 'sourcecode endpoints' for per-method HTTP surface)"
661
663
  )
662
664
  if len(module_names) > 30:
663
665
  # Group by first path segment under ddd/ (inferred domain area)
@@ -678,14 +680,12 @@ def _bootstrap_structured(eps: list) -> "Optional[dict[str, Any]]":
678
680
  domain_groups[domain_prefix or "other"].append(module)
679
681
  result["controllers"] = {
680
682
  "classes": controller_classes,
681
- "methods": controller_methods,
682
683
  "note": _ctrl_note,
683
684
  "modules": {k: sorted(v) for k, v in sorted(domain_groups.items())},
684
685
  }
685
686
  else:
686
687
  result["controllers"] = {
687
688
  "classes": controller_classes,
688
- "methods": controller_methods,
689
689
  "note": _ctrl_note,
690
690
  "modules": sorted(module_names),
691
691
  }
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: sourcecode
3
- Version: 1.33.2
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
- ![Version](https://img.shields.io/badge/version-1.33.2-blue)
42
+ ![Version](https://img.shields.io/badge/version-1.33.4-blue)
43
43
  ![Python](https://img.shields.io/badge/python-3.10%2B-green)
44
44
 
45
45
  ---
@@ -113,7 +113,7 @@ pipx install sourcecode
113
113
 
114
114
  ```bash
115
115
  sourcecode version
116
- # sourcecode 1.33.2
116
+ # sourcecode 1.33.4
117
117
  ```
118
118
 
119
119
  ---
@@ -1,4 +1,4 @@
1
- sourcecode/__init__.py,sha256=tN8Xe7UyyVpCOi0lC9IYgThLHlUY6kso5Yf2r_0OwA0,103
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=rtQ4Bx4L82G0vuSPz1Iabu1azPwF3vuNiAZVxQSvXrQ,176581
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,19 +29,19 @@ 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=uZo0r7QBXUmQdfTp3w_A1XI-OzFAlcoH7F76_p7IQjo,205311
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=dAzD8suyQyq_gixQbgzFiIzeFBfONJ6A54qd44vOwMc,15595
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
43
43
  sourcecode/semantic_analyzer.py,sha256=TDuC3wzZR2DPm1mgrAg1YSLk2QzJoueS3TZAmyGGpCU,89417
44
- sourcecode/serializer.py,sha256=3JBvsMDj5pt1RXpi1zJpk5DGWUKbeb2Jl622-kmYWD4,123312
44
+ sourcecode/serializer.py,sha256=ooNZW2_fqx__BXII25eAWq-BomodvqQ6opUT_niQYCA,123403
45
45
  sourcecode/summarizer.py,sha256=YspHEVeYJVmltq0FMtGZF8kIP3qiR2KLcanGL6Y7uTI,20747
46
46
  sourcecode/tree_utils.py,sha256=8GAkIfQAsvtEudIeW1l4ooH_oRtrWR8cpJQJsEa_Pfw,2093
47
47
  sourcecode/workspace.py,sha256=X_6NmNnitvT3_38V-JDChydo_sR68s249hLFlrQskU0,8271
@@ -68,7 +68,7 @@ sourcecode/detectors/terraform.py,sha256=cxORPR_zVLOJpHlh4e9JnFpkQsn_UnqMMom5yG6
68
68
  sourcecode/detectors/tooling.py,sha256=8CKbtxwQoABP-WyBRNmdAmHDOvAH57AR1cF4UKuWEdQ,2074
69
69
  sourcecode/mcp/__init__.py,sha256=XU4HfRGbdid8wdUA0x_4f7uKZD1z3mv_XUY_WU_T9Mw,179
70
70
  sourcecode/mcp/runner.py,sha256=YSw2DXEICau6mCBr3Gfia3D_tKxMbRvIIXEh4cHC1SY,1390
71
- sourcecode/mcp/server.py,sha256=jUCDNjJKUIhse52M8-Lp63CDxlm21xOYUOVlv3z6_uk,25556
71
+ sourcecode/mcp/server.py,sha256=dAmoUbnu4kPPWeRH2tcOn9WJPG8Zfzvlu0nRmyiok70,27925
72
72
  sourcecode/mcp/onboarding/__init__.py,sha256=sj2PWqEBmMc4zBNkomg89WtL0M6S7A9yb7_wAuSWNP4,66
73
73
  sourcecode/mcp/onboarding/applier.py,sha256=B9CneieWTpaDSDIyW3S5nrlRlBpvfqUcgi93-mm_ApQ,2135
74
74
  sourcecode/mcp/onboarding/backup.py,sha256=ihqGOR8QTX8HASRSEDyfFyXr5bkXrygPHamv4p9KTmk,1452
@@ -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.2.dist-info/METADATA,sha256=5ow3o68xzE1c77dH1MfolgnmPKRepCxBGOtZco3luV8,16440
84
- sourcecode-1.33.2.dist-info/WHEEL,sha256=QccIxa26bgl1E6uMy58deGWi-0aeIkkangHcxk2kWfw,87
85
- sourcecode-1.33.2.dist-info/entry_points.txt,sha256=ex3F9rmbXeyDIoFQHtkEqTsKSaJow8F0LrVu8XfIktQ,57
86
- sourcecode-1.33.2.dist-info/licenses/LICENSE,sha256=7DdHrU9Z_3e7dSvq4ISijZNjnuHo5NIHNiHDouMQ9JU,10491
87
- sourcecode-1.33.2.dist-info/RECORD,,
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,,