sourcecode 1.32.6__tar.gz → 1.32.7__tar.gz

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.
Files changed (93) hide show
  1. {sourcecode-1.32.6 → sourcecode-1.32.7}/PKG-INFO +1 -1
  2. {sourcecode-1.32.6 → sourcecode-1.32.7}/pyproject.toml +1 -1
  3. {sourcecode-1.32.6 → sourcecode-1.32.7}/src/sourcecode/__init__.py +1 -1
  4. {sourcecode-1.32.6 → sourcecode-1.32.7}/src/sourcecode/cli.py +21 -1
  5. {sourcecode-1.32.6 → sourcecode-1.32.7}/src/sourcecode/prepare_context.py +77 -0
  6. {sourcecode-1.32.6 → sourcecode-1.32.7}/src/sourcecode/ris.py +13 -2
  7. {sourcecode-1.32.6 → sourcecode-1.32.7}/.github/workflows/build-windows.yml +0 -0
  8. {sourcecode-1.32.6 → sourcecode-1.32.7}/.gitignore +0 -0
  9. {sourcecode-1.32.6 → sourcecode-1.32.7}/.ruff.toml +0 -0
  10. {sourcecode-1.32.6 → sourcecode-1.32.7}/CHANGELOG.md +0 -0
  11. {sourcecode-1.32.6 → sourcecode-1.32.7}/CONTRIBUTING.md +0 -0
  12. {sourcecode-1.32.6 → sourcecode-1.32.7}/LICENSE +0 -0
  13. {sourcecode-1.32.6 → sourcecode-1.32.7}/README.md +0 -0
  14. {sourcecode-1.32.6 → sourcecode-1.32.7}/SECURITY.md +0 -0
  15. {sourcecode-1.32.6 → sourcecode-1.32.7}/raw +0 -0
  16. {sourcecode-1.32.6 → sourcecode-1.32.7}/src/sourcecode/adaptive_scanner.py +0 -0
  17. {sourcecode-1.32.6 → sourcecode-1.32.7}/src/sourcecode/architecture_analyzer.py +0 -0
  18. {sourcecode-1.32.6 → sourcecode-1.32.7}/src/sourcecode/architecture_summary.py +0 -0
  19. {sourcecode-1.32.6 → sourcecode-1.32.7}/src/sourcecode/ast_extractor.py +0 -0
  20. {sourcecode-1.32.6 → sourcecode-1.32.7}/src/sourcecode/cache.py +0 -0
  21. {sourcecode-1.32.6 → sourcecode-1.32.7}/src/sourcecode/cache.tmp_new +0 -0
  22. {sourcecode-1.32.6 → sourcecode-1.32.7}/src/sourcecode/canonical_ir.py +0 -0
  23. {sourcecode-1.32.6 → sourcecode-1.32.7}/src/sourcecode/classifier.py +0 -0
  24. {sourcecode-1.32.6 → sourcecode-1.32.7}/src/sourcecode/code_notes_analyzer.py +0 -0
  25. {sourcecode-1.32.6 → sourcecode-1.32.7}/src/sourcecode/confidence_analyzer.py +0 -0
  26. {sourcecode-1.32.6 → sourcecode-1.32.7}/src/sourcecode/context_scorer.py +0 -0
  27. {sourcecode-1.32.6 → sourcecode-1.32.7}/src/sourcecode/context_summarizer.py +0 -0
  28. {sourcecode-1.32.6 → sourcecode-1.32.7}/src/sourcecode/contract_model.py +0 -0
  29. {sourcecode-1.32.6 → sourcecode-1.32.7}/src/sourcecode/contract_pipeline.py +0 -0
  30. {sourcecode-1.32.6 → sourcecode-1.32.7}/src/sourcecode/coverage_parser.py +0 -0
  31. {sourcecode-1.32.6 → sourcecode-1.32.7}/src/sourcecode/dependency_analyzer.py +0 -0
  32. {sourcecode-1.32.6 → sourcecode-1.32.7}/src/sourcecode/detectors/__init__.py +0 -0
  33. {sourcecode-1.32.6 → sourcecode-1.32.7}/src/sourcecode/detectors/base.py +0 -0
  34. {sourcecode-1.32.6 → sourcecode-1.32.7}/src/sourcecode/detectors/csproj_parser.py +0 -0
  35. {sourcecode-1.32.6 → sourcecode-1.32.7}/src/sourcecode/detectors/dart.py +0 -0
  36. {sourcecode-1.32.6 → sourcecode-1.32.7}/src/sourcecode/detectors/dotnet.py +0 -0
  37. {sourcecode-1.32.6 → sourcecode-1.32.7}/src/sourcecode/detectors/elixir.py +0 -0
  38. {sourcecode-1.32.6 → sourcecode-1.32.7}/src/sourcecode/detectors/go.py +0 -0
  39. {sourcecode-1.32.6 → sourcecode-1.32.7}/src/sourcecode/detectors/heuristic.py +0 -0
  40. {sourcecode-1.32.6 → sourcecode-1.32.7}/src/sourcecode/detectors/hybrid.py +0 -0
  41. {sourcecode-1.32.6 → sourcecode-1.32.7}/src/sourcecode/detectors/java.py +0 -0
  42. {sourcecode-1.32.6 → sourcecode-1.32.7}/src/sourcecode/detectors/jvm_ext.py +0 -0
  43. {sourcecode-1.32.6 → sourcecode-1.32.7}/src/sourcecode/detectors/nodejs.py +0 -0
  44. {sourcecode-1.32.6 → sourcecode-1.32.7}/src/sourcecode/detectors/parsers.py +0 -0
  45. {sourcecode-1.32.6 → sourcecode-1.32.7}/src/sourcecode/detectors/php.py +0 -0
  46. {sourcecode-1.32.6 → sourcecode-1.32.7}/src/sourcecode/detectors/project.py +0 -0
  47. {sourcecode-1.32.6 → sourcecode-1.32.7}/src/sourcecode/detectors/python.py +0 -0
  48. {sourcecode-1.32.6 → sourcecode-1.32.7}/src/sourcecode/detectors/ruby.py +0 -0
  49. {sourcecode-1.32.6 → sourcecode-1.32.7}/src/sourcecode/detectors/rust.py +0 -0
  50. {sourcecode-1.32.6 → sourcecode-1.32.7}/src/sourcecode/detectors/systems.py +0 -0
  51. {sourcecode-1.32.6 → sourcecode-1.32.7}/src/sourcecode/detectors/terraform.py +0 -0
  52. {sourcecode-1.32.6 → sourcecode-1.32.7}/src/sourcecode/detectors/tooling.py +0 -0
  53. {sourcecode-1.32.6 → sourcecode-1.32.7}/src/sourcecode/doc_analyzer.py +0 -0
  54. {sourcecode-1.32.6 → sourcecode-1.32.7}/src/sourcecode/entrypoint_classifier.py +0 -0
  55. {sourcecode-1.32.6 → sourcecode-1.32.7}/src/sourcecode/env_analyzer.py +0 -0
  56. {sourcecode-1.32.6 → sourcecode-1.32.7}/src/sourcecode/file_classifier.py +0 -0
  57. {sourcecode-1.32.6 → sourcecode-1.32.7}/src/sourcecode/flow_analyzer.py +0 -0
  58. {sourcecode-1.32.6 → sourcecode-1.32.7}/src/sourcecode/git_analyzer.py +0 -0
  59. {sourcecode-1.32.6 → sourcecode-1.32.7}/src/sourcecode/graph_analyzer.py +0 -0
  60. {sourcecode-1.32.6 → sourcecode-1.32.7}/src/sourcecode/license.py +0 -0
  61. {sourcecode-1.32.6 → sourcecode-1.32.7}/src/sourcecode/mcp/__init__.py +0 -0
  62. {sourcecode-1.32.6 → sourcecode-1.32.7}/src/sourcecode/mcp/onboarding/__init__.py +0 -0
  63. {sourcecode-1.32.6 → sourcecode-1.32.7}/src/sourcecode/mcp/onboarding/applier.py +0 -0
  64. {sourcecode-1.32.6 → sourcecode-1.32.7}/src/sourcecode/mcp/onboarding/backup.py +0 -0
  65. {sourcecode-1.32.6 → sourcecode-1.32.7}/src/sourcecode/mcp/onboarding/detector.py +0 -0
  66. {sourcecode-1.32.6 → sourcecode-1.32.7}/src/sourcecode/mcp/onboarding/planner.py +0 -0
  67. {sourcecode-1.32.6 → sourcecode-1.32.7}/src/sourcecode/mcp/runner.py +0 -0
  68. {sourcecode-1.32.6 → sourcecode-1.32.7}/src/sourcecode/mcp/server.py +0 -0
  69. {sourcecode-1.32.6 → sourcecode-1.32.7}/src/sourcecode/mcp_nudge.py +0 -0
  70. {sourcecode-1.32.6 → sourcecode-1.32.7}/src/sourcecode/metrics_analyzer.py +0 -0
  71. {sourcecode-1.32.6 → sourcecode-1.32.7}/src/sourcecode/output_budget.py +0 -0
  72. {sourcecode-1.32.6 → sourcecode-1.32.7}/src/sourcecode/path_filters.py +0 -0
  73. {sourcecode-1.32.6 → sourcecode-1.32.7}/src/sourcecode/pr_comment_renderer.py +0 -0
  74. {sourcecode-1.32.6 → sourcecode-1.32.7}/src/sourcecode/progress.py +0 -0
  75. {sourcecode-1.32.6 → sourcecode-1.32.7}/src/sourcecode/ranking_engine.py +0 -0
  76. {sourcecode-1.32.6 → sourcecode-1.32.7}/src/sourcecode/redactor.py +0 -0
  77. {sourcecode-1.32.6 → sourcecode-1.32.7}/src/sourcecode/relevance_scorer.py +0 -0
  78. {sourcecode-1.32.6 → sourcecode-1.32.7}/src/sourcecode/repo_classifier.py +0 -0
  79. {sourcecode-1.32.6 → sourcecode-1.32.7}/src/sourcecode/repository_ir.py +0 -0
  80. {sourcecode-1.32.6 → sourcecode-1.32.7}/src/sourcecode/runtime_classifier.py +0 -0
  81. {sourcecode-1.32.6 → sourcecode-1.32.7}/src/sourcecode/scanner.py +0 -0
  82. {sourcecode-1.32.6 → sourcecode-1.32.7}/src/sourcecode/schema.py +0 -0
  83. {sourcecode-1.32.6 → sourcecode-1.32.7}/src/sourcecode/semantic_analyzer.py +0 -0
  84. {sourcecode-1.32.6 → sourcecode-1.32.7}/src/sourcecode/serializer.py +0 -0
  85. {sourcecode-1.32.6 → sourcecode-1.32.7}/src/sourcecode/summarizer.py +0 -0
  86. {sourcecode-1.32.6 → sourcecode-1.32.7}/src/sourcecode/telemetry/__init__.py +0 -0
  87. {sourcecode-1.32.6 → sourcecode-1.32.7}/src/sourcecode/telemetry/config.py +0 -0
  88. {sourcecode-1.32.6 → sourcecode-1.32.7}/src/sourcecode/telemetry/consent.py +0 -0
  89. {sourcecode-1.32.6 → sourcecode-1.32.7}/src/sourcecode/telemetry/events.py +0 -0
  90. {sourcecode-1.32.6 → sourcecode-1.32.7}/src/sourcecode/telemetry/filters.py +0 -0
  91. {sourcecode-1.32.6 → sourcecode-1.32.7}/src/sourcecode/telemetry/transport.py +0 -0
  92. {sourcecode-1.32.6 → sourcecode-1.32.7}/src/sourcecode/tree_utils.py +0 -0
  93. {sourcecode-1.32.6 → sourcecode-1.32.7}/src/sourcecode/workspace.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: sourcecode
3
- Version: 1.32.6
3
+ Version: 1.32.7
4
4
  Summary: Deterministic codebase context for AI coding agents
5
5
  License-File: LICENSE
6
6
  Keywords: agents,ai,codebase,context,developer-tools,llm
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "sourcecode"
7
- version = "1.32.6"
7
+ version = "1.32.7"
8
8
  description = "Deterministic codebase context for AI coding agents"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.9"
@@ -1,3 +1,3 @@
1
1
  """sourcecode — Deterministic codebase context maps for AI coding agents."""
2
2
 
3
- __version__ = "1.32.6"
3
+ __version__ = "1.32.7"
@@ -3753,6 +3753,24 @@ def config_cmd() -> None:
3753
3753
  typer.echo(" sourcecode telemetry status")
3754
3754
 
3755
3755
 
3756
+ # ── cold-start (RIS bootstrap for external MCP and agents) ───────────────────
3757
+
3758
+ @app.command("cold-start")
3759
+ def cold_start_cmd(
3760
+ path: Path = typer.Argument(Path("."), help="Repository path (default: current directory)"),
3761
+ ) -> None:
3762
+ """Output Repository Intelligence Snapshot bootstrap context as JSON.
3763
+
3764
+ Returns instantly from persisted RIS — zero re-analysis cost.
3765
+ status: cold_start_ready | cold_start_stale | no_ris
3766
+ """
3767
+ import json as _json
3768
+ from sourcecode.ris import get_cold_start_context as _gcs
3769
+ target = Path(path).resolve()
3770
+ result = _gcs(target)
3771
+ typer.echo(_json.dumps(result, indent=2, ensure_ascii=False))
3772
+
3773
+
3756
3774
  # ── analyze (legacy alias) ────────────────────────────────────────────────────
3757
3775
 
3758
3776
  @app.command("analyze", hidden=True)
@@ -4207,11 +4225,13 @@ def cache_warm_cmd(
4207
4225
  agent: bool = typer.Option(False, "--agent", help="Also warm agent view."),
4208
4226
  ) -> None:
4209
4227
  """Pre-populate the cache by running a fresh analysis."""
4228
+ import shutil as _shutil
4210
4229
  import subprocess as _sub
4211
4230
  import sys as _sys
4212
4231
  target = Path(path).resolve()
4213
4232
  typer.echo(f"Warming cache for {target} …", err=True)
4214
- cmd = [_sys.executable, "-m", "sourcecode", str(target)]
4233
+ _sc_bin = _shutil.which("sourcecode") or _sys.argv[0]
4234
+ cmd = [_sc_bin, str(target)]
4215
4235
  if compact:
4216
4236
  cmd.append("--compact")
4217
4237
  if agent:
@@ -734,6 +734,77 @@ class TaskContextBuilder:
734
734
  def __init__(self, root: Path) -> None:
735
735
  self.root = root
736
736
 
737
+ # ------------------------------------------------------------------
738
+ # RIS fast-path: serve onboard/explain from warm snapshot (<50ms)
739
+ # ------------------------------------------------------------------
740
+
741
+ def _try_ris_fast_path(self, task_name: str, spec: "TaskSpec") -> Optional[TaskOutput]:
742
+ """Return TaskOutput from a warm RIS without running the full scan.
743
+
744
+ Only activated for onboard/explain when git HEAD matches stored RIS.
745
+ Falls through (returns None) on any error or cache miss.
746
+ """
747
+ try:
748
+ import subprocess as _sp
749
+ from sourcecode.ris import load_ris as _lris
750
+ _ris = _lris(self.root)
751
+ if _ris is None or not _ris.compact_summary:
752
+ return None
753
+ _r = _sp.run(
754
+ ["git", "-C", str(self.root), "rev-parse", "--short", "HEAD"],
755
+ capture_output=True, text=True, timeout=2,
756
+ )
757
+ if _r.returncode != 0 or _r.stdout.strip() != _ris.git_head:
758
+ return None
759
+
760
+ compact = _ris.compact_summary
761
+ struct = _ris.structural_map
762
+
763
+ entry_points = struct.get("entrypoints") or compact.get("entry_points") or []
764
+ controllers = struct.get("controllers") or []
765
+ services = struct.get("services") or []
766
+
767
+ _seen: set = set()
768
+ relevant: list[RelevantFile] = []
769
+ for fp in entry_points[:10]:
770
+ if isinstance(fp, str) and fp not in _seen:
771
+ _seen.add(fp)
772
+ relevant.append(RelevantFile(path=fp, role="entrypoint", score=1.0, reason="entry_point", why="Primary entry point"))
773
+ for fp in controllers[:8]:
774
+ if isinstance(fp, str) and fp not in _seen:
775
+ _seen.add(fp)
776
+ relevant.append(RelevantFile(path=fp, role="source", score=0.9, reason="controller", why="Controller"))
777
+ for fp in services[:8]:
778
+ if isinstance(fp, str) and fp not in _seen:
779
+ _seen.add(fp)
780
+ relevant.append(RelevantFile(path=fp, role="source", score=0.8, reason="service", why="Service layer"))
781
+
782
+ # compact_summary uses "analysis_gaps" (list[dict]) not "gaps" (list[str])
783
+ _raw_gaps = compact.get("gaps") or compact.get("analysis_gaps") or []
784
+ _gap_strs: list[str] = [
785
+ g.get("reason", str(g)) if isinstance(g, dict) else str(g)
786
+ for g in _raw_gaps
787
+ if g
788
+ ]
789
+
790
+ return TaskOutput(
791
+ task=task_name,
792
+ goal=spec.goal,
793
+ project_summary=compact.get("project_summary") or compact.get("summary"),
794
+ architecture_summary=compact.get("architecture_summary"),
795
+ relevant_files=relevant,
796
+ suspected_areas=[],
797
+ improvement_opportunities=[],
798
+ test_gaps=[],
799
+ key_dependencies=compact.get("key_dependencies") or [],
800
+ code_notes_summary=None,
801
+ limitations=[],
802
+ confidence=compact.get("confidence") or compact.get("confidence_summary") or "high",
803
+ gaps=_gap_strs,
804
+ )
805
+ except Exception:
806
+ return None
807
+
737
808
  def build(self, task_name: str, *, since: Optional[str] = None, symptom: Optional[str] = None, fast: bool = False, include_config: bool = False, all_gaps: bool = False) -> TaskOutput:
738
809
  if task_name not in TASKS:
739
810
  raise ValueError(
@@ -741,6 +812,12 @@ class TaskContextBuilder:
741
812
  )
742
813
  spec = TASKS[task_name]
743
814
 
815
+ # ── RIS fast-path (onboard / explain only) ────────────────────────────
816
+ if task_name in ("onboard", "explain") and not fast:
817
+ _warm = self._try_ris_fast_path(task_name, spec)
818
+ if _warm is not None:
819
+ return _warm
820
+
744
821
  # ── 0. review-pr: git-first scope resolution (before any filesystem scan) ─
745
822
  _pr_git_root: Optional[Path] = None
746
823
  _pr_scope_files: Optional[list[str]] = None
@@ -362,7 +362,8 @@ def get_cold_start_context(repo_root: Path) -> dict:
362
362
  current_head = _current_git_head(repo_root)
363
363
  stale = bool(current_head and ris.git_head and current_head != ris.git_head)
364
364
 
365
- return {
365
+ endpoints = ris.api_surface.get("endpoints", [])
366
+ result: dict = {
366
367
  "status": "cold_start_stale" if stale else "cold_start_ready",
367
368
  "repo_id": ris.repo_id,
368
369
  "git_head": ris.git_head,
@@ -370,8 +371,18 @@ def get_cold_start_context(repo_root: Path) -> dict:
370
371
  "last_updated_at": ris.last_updated_at,
371
372
  "summary": ris.compact_summary,
372
373
  "entrypoints": ris.structural_map.get("entrypoints", []),
373
- "endpoints": ris.api_surface.get("endpoints", []),
374
+ "endpoints": endpoints,
374
375
  "hotspots": ris.git_context_snapshot.get("hotspots", []),
375
376
  }
377
+ if not endpoints:
378
+ _is_java = (repo_root / "pom.xml").exists() or \
379
+ (repo_root / "build.gradle").exists() or \
380
+ (repo_root / "build.gradle.kts").exists()
381
+ if _is_java:
382
+ result["endpoints_hint"] = (
383
+ "Java repo detected but no endpoint index found. "
384
+ "Call get_endpoints (or: sourcecode endpoints <path>) to populate."
385
+ )
386
+ return result
376
387
  except Exception:
377
388
  return {"status": "no_ris"}
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes