sourcecode 1.33.14__tar.gz → 1.33.16__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.
- {sourcecode-1.33.14 → sourcecode-1.33.16}/PKG-INFO +1 -1
- {sourcecode-1.33.14 → sourcecode-1.33.16}/pyproject.toml +1 -1
- {sourcecode-1.33.14 → sourcecode-1.33.16}/src/sourcecode/__init__.py +1 -1
- {sourcecode-1.33.14 → sourcecode-1.33.16}/src/sourcecode/cli.py +20 -4
- {sourcecode-1.33.14 → sourcecode-1.33.16}/src/sourcecode/file_classifier.py +9 -6
- {sourcecode-1.33.14 → sourcecode-1.33.16}/src/sourcecode/mcp/server.py +50 -1
- {sourcecode-1.33.14 → sourcecode-1.33.16}/src/sourcecode/prepare_context.py +31 -15
- {sourcecode-1.33.14 → sourcecode-1.33.16}/src/sourcecode/ris.py +12 -0
- {sourcecode-1.33.14 → sourcecode-1.33.16}/.github/workflows/build-windows.yml +0 -0
- {sourcecode-1.33.14 → sourcecode-1.33.16}/.gitignore +0 -0
- {sourcecode-1.33.14 → sourcecode-1.33.16}/.ruff.toml +0 -0
- {sourcecode-1.33.14 → sourcecode-1.33.16}/CHANGELOG.md +0 -0
- {sourcecode-1.33.14 → sourcecode-1.33.16}/CONTRIBUTING.md +0 -0
- {sourcecode-1.33.14 → sourcecode-1.33.16}/LICENSE +0 -0
- {sourcecode-1.33.14 → sourcecode-1.33.16}/README.md +0 -0
- {sourcecode-1.33.14 → sourcecode-1.33.16}/SECURITY.md +0 -0
- {sourcecode-1.33.14 → sourcecode-1.33.16}/raw +0 -0
- {sourcecode-1.33.14 → sourcecode-1.33.16}/src/sourcecode/adaptive_scanner.py +0 -0
- {sourcecode-1.33.14 → sourcecode-1.33.16}/src/sourcecode/architecture_analyzer.py +0 -0
- {sourcecode-1.33.14 → sourcecode-1.33.16}/src/sourcecode/architecture_summary.py +0 -0
- {sourcecode-1.33.14 → sourcecode-1.33.16}/src/sourcecode/ast_extractor.py +0 -0
- {sourcecode-1.33.14 → sourcecode-1.33.16}/src/sourcecode/cache.py +0 -0
- {sourcecode-1.33.14 → sourcecode-1.33.16}/src/sourcecode/canonical_ir.py +0 -0
- {sourcecode-1.33.14 → sourcecode-1.33.16}/src/sourcecode/classifier.py +0 -0
- {sourcecode-1.33.14 → sourcecode-1.33.16}/src/sourcecode/code_notes_analyzer.py +0 -0
- {sourcecode-1.33.14 → sourcecode-1.33.16}/src/sourcecode/confidence_analyzer.py +0 -0
- {sourcecode-1.33.14 → sourcecode-1.33.16}/src/sourcecode/context_scorer.py +0 -0
- {sourcecode-1.33.14 → sourcecode-1.33.16}/src/sourcecode/context_summarizer.py +0 -0
- {sourcecode-1.33.14 → sourcecode-1.33.16}/src/sourcecode/contract_model.py +0 -0
- {sourcecode-1.33.14 → sourcecode-1.33.16}/src/sourcecode/contract_pipeline.py +0 -0
- {sourcecode-1.33.14 → sourcecode-1.33.16}/src/sourcecode/coverage_parser.py +0 -0
- {sourcecode-1.33.14 → sourcecode-1.33.16}/src/sourcecode/dependency_analyzer.py +0 -0
- {sourcecode-1.33.14 → sourcecode-1.33.16}/src/sourcecode/detectors/__init__.py +0 -0
- {sourcecode-1.33.14 → sourcecode-1.33.16}/src/sourcecode/detectors/base.py +0 -0
- {sourcecode-1.33.14 → sourcecode-1.33.16}/src/sourcecode/detectors/csproj_parser.py +0 -0
- {sourcecode-1.33.14 → sourcecode-1.33.16}/src/sourcecode/detectors/dart.py +0 -0
- {sourcecode-1.33.14 → sourcecode-1.33.16}/src/sourcecode/detectors/dotnet.py +0 -0
- {sourcecode-1.33.14 → sourcecode-1.33.16}/src/sourcecode/detectors/elixir.py +0 -0
- {sourcecode-1.33.14 → sourcecode-1.33.16}/src/sourcecode/detectors/go.py +0 -0
- {sourcecode-1.33.14 → sourcecode-1.33.16}/src/sourcecode/detectors/heuristic.py +0 -0
- {sourcecode-1.33.14 → sourcecode-1.33.16}/src/sourcecode/detectors/hybrid.py +0 -0
- {sourcecode-1.33.14 → sourcecode-1.33.16}/src/sourcecode/detectors/java.py +0 -0
- {sourcecode-1.33.14 → sourcecode-1.33.16}/src/sourcecode/detectors/jvm_ext.py +0 -0
- {sourcecode-1.33.14 → sourcecode-1.33.16}/src/sourcecode/detectors/nodejs.py +0 -0
- {sourcecode-1.33.14 → sourcecode-1.33.16}/src/sourcecode/detectors/parsers.py +0 -0
- {sourcecode-1.33.14 → sourcecode-1.33.16}/src/sourcecode/detectors/php.py +0 -0
- {sourcecode-1.33.14 → sourcecode-1.33.16}/src/sourcecode/detectors/project.py +0 -0
- {sourcecode-1.33.14 → sourcecode-1.33.16}/src/sourcecode/detectors/python.py +0 -0
- {sourcecode-1.33.14 → sourcecode-1.33.16}/src/sourcecode/detectors/ruby.py +0 -0
- {sourcecode-1.33.14 → sourcecode-1.33.16}/src/sourcecode/detectors/rust.py +0 -0
- {sourcecode-1.33.14 → sourcecode-1.33.16}/src/sourcecode/detectors/systems.py +0 -0
- {sourcecode-1.33.14 → sourcecode-1.33.16}/src/sourcecode/detectors/terraform.py +0 -0
- {sourcecode-1.33.14 → sourcecode-1.33.16}/src/sourcecode/detectors/tooling.py +0 -0
- {sourcecode-1.33.14 → sourcecode-1.33.16}/src/sourcecode/doc_analyzer.py +0 -0
- {sourcecode-1.33.14 → sourcecode-1.33.16}/src/sourcecode/entrypoint_classifier.py +0 -0
- {sourcecode-1.33.14 → sourcecode-1.33.16}/src/sourcecode/env_analyzer.py +0 -0
- {sourcecode-1.33.14 → sourcecode-1.33.16}/src/sourcecode/error_schema.py +0 -0
- {sourcecode-1.33.14 → sourcecode-1.33.16}/src/sourcecode/flow_analyzer.py +0 -0
- {sourcecode-1.33.14 → sourcecode-1.33.16}/src/sourcecode/git_analyzer.py +0 -0
- {sourcecode-1.33.14 → sourcecode-1.33.16}/src/sourcecode/graph_analyzer.py +0 -0
- {sourcecode-1.33.14 → sourcecode-1.33.16}/src/sourcecode/license.py +0 -0
- {sourcecode-1.33.14 → sourcecode-1.33.16}/src/sourcecode/mcp/__init__.py +0 -0
- {sourcecode-1.33.14 → sourcecode-1.33.16}/src/sourcecode/mcp/onboarding/__init__.py +0 -0
- {sourcecode-1.33.14 → sourcecode-1.33.16}/src/sourcecode/mcp/onboarding/applier.py +0 -0
- {sourcecode-1.33.14 → sourcecode-1.33.16}/src/sourcecode/mcp/onboarding/backup.py +0 -0
- {sourcecode-1.33.14 → sourcecode-1.33.16}/src/sourcecode/mcp/onboarding/detector.py +0 -0
- {sourcecode-1.33.14 → sourcecode-1.33.16}/src/sourcecode/mcp/onboarding/planner.py +0 -0
- {sourcecode-1.33.14 → sourcecode-1.33.16}/src/sourcecode/mcp/orchestrator.py +0 -0
- {sourcecode-1.33.14 → sourcecode-1.33.16}/src/sourcecode/mcp/registry.py +0 -0
- {sourcecode-1.33.14 → sourcecode-1.33.16}/src/sourcecode/mcp/runner.py +0 -0
- {sourcecode-1.33.14 → sourcecode-1.33.16}/src/sourcecode/mcp_nudge.py +0 -0
- {sourcecode-1.33.14 → sourcecode-1.33.16}/src/sourcecode/metrics_analyzer.py +0 -0
- {sourcecode-1.33.14 → sourcecode-1.33.16}/src/sourcecode/output_budget.py +0 -0
- {sourcecode-1.33.14 → sourcecode-1.33.16}/src/sourcecode/path_filters.py +0 -0
- {sourcecode-1.33.14 → sourcecode-1.33.16}/src/sourcecode/pr_comment_renderer.py +0 -0
- {sourcecode-1.33.14 → sourcecode-1.33.16}/src/sourcecode/progress.py +0 -0
- {sourcecode-1.33.14 → sourcecode-1.33.16}/src/sourcecode/ranking_engine.py +0 -0
- {sourcecode-1.33.14 → sourcecode-1.33.16}/src/sourcecode/redactor.py +0 -0
- {sourcecode-1.33.14 → sourcecode-1.33.16}/src/sourcecode/relevance_scorer.py +0 -0
- {sourcecode-1.33.14 → sourcecode-1.33.16}/src/sourcecode/repo_classifier.py +0 -0
- {sourcecode-1.33.14 → sourcecode-1.33.16}/src/sourcecode/repository_ir.py +0 -0
- {sourcecode-1.33.14 → sourcecode-1.33.16}/src/sourcecode/runtime_classifier.py +0 -0
- {sourcecode-1.33.14 → sourcecode-1.33.16}/src/sourcecode/scanner.py +0 -0
- {sourcecode-1.33.14 → sourcecode-1.33.16}/src/sourcecode/schema.py +0 -0
- {sourcecode-1.33.14 → sourcecode-1.33.16}/src/sourcecode/semantic_analyzer.py +0 -0
- {sourcecode-1.33.14 → sourcecode-1.33.16}/src/sourcecode/serializer.py +0 -0
- {sourcecode-1.33.14 → sourcecode-1.33.16}/src/sourcecode/summarizer.py +0 -0
- {sourcecode-1.33.14 → sourcecode-1.33.16}/src/sourcecode/telemetry/__init__.py +0 -0
- {sourcecode-1.33.14 → sourcecode-1.33.16}/src/sourcecode/telemetry/config.py +0 -0
- {sourcecode-1.33.14 → sourcecode-1.33.16}/src/sourcecode/telemetry/consent.py +0 -0
- {sourcecode-1.33.14 → sourcecode-1.33.16}/src/sourcecode/telemetry/events.py +0 -0
- {sourcecode-1.33.14 → sourcecode-1.33.16}/src/sourcecode/telemetry/filters.py +0 -0
- {sourcecode-1.33.14 → sourcecode-1.33.16}/src/sourcecode/telemetry/transport.py +0 -0
- {sourcecode-1.33.14 → sourcecode-1.33.16}/src/sourcecode/tree_utils.py +0 -0
- {sourcecode-1.33.14 → sourcecode-1.33.16}/src/sourcecode/workspace.py +0 -0
|
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "sourcecode"
|
|
7
|
-
version = "1.33.
|
|
7
|
+
version = "1.33.16"
|
|
8
8
|
description = "Persistent structural context and ultra-fast repeated analysis for AI coding agents"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.9"
|
|
@@ -1141,9 +1141,23 @@ def main(
|
|
|
1141
1141
|
capture_output=True, text=True, timeout=3,
|
|
1142
1142
|
)
|
|
1143
1143
|
_git_sha = _sha_r.stdout.strip()
|
|
1144
|
-
|
|
1145
|
-
#
|
|
1146
|
-
|
|
1144
|
+
|
|
1145
|
+
# Detect actual git root (may be an ancestor of target for monorepos,
|
|
1146
|
+
# multi-project repos, or SVN-migrated trees where .git is in a parent).
|
|
1147
|
+
# The original "(target / '.git').exists()" check broke these layouts.
|
|
1148
|
+
_git_root_str = ""
|
|
1149
|
+
if _git_sha:
|
|
1150
|
+
try:
|
|
1151
|
+
_gr_r = _sub.run(
|
|
1152
|
+
["git", "-C", str(target), "rev-parse", "--show-toplevel"],
|
|
1153
|
+
capture_output=True, text=True, timeout=3,
|
|
1154
|
+
)
|
|
1155
|
+
if _gr_r.returncode == 0:
|
|
1156
|
+
_git_root_str = _gr_r.stdout.strip()
|
|
1157
|
+
except Exception:
|
|
1158
|
+
pass
|
|
1159
|
+
|
|
1160
|
+
if _git_sha and _git_root_str:
|
|
1147
1161
|
_excl_key = (
|
|
1148
1162
|
",".join(sorted(e.strip() for e in exclude.split(",") if e.strip()))
|
|
1149
1163
|
if exclude else ""
|
|
@@ -2241,7 +2255,9 @@ def main(
|
|
|
2241
2255
|
_atexit.register(_cache_write_thread.join, 5.0)
|
|
2242
2256
|
|
|
2243
2257
|
# Update RIS with aggregated snapshot data (non-fatal side-effect).
|
|
2244
|
-
|
|
2258
|
+
# Update RIS whenever git is available, even when L1/L2 cache is skipped
|
|
2259
|
+
# (e.g. target is a subdirectory of the git root — _core_key may be "").
|
|
2260
|
+
if not no_cache and not _pipeline_error and _git_sha:
|
|
2245
2261
|
try:
|
|
2246
2262
|
from sourcecode.serializer import core_view as _ris_core_view
|
|
2247
2263
|
from sourcecode.ris import maybe_update_ris as _ris_update
|
|
@@ -187,16 +187,19 @@ class FileClassifier:
|
|
|
187
187
|
if java_class is not None:
|
|
188
188
|
return java_class
|
|
189
189
|
|
|
190
|
-
|
|
191
|
-
|
|
190
|
+
# Fix 4: call _matched_imports once per category instead of twice
|
|
191
|
+
# (_has_any_import was calling _matched_imports and discarding the result,
|
|
192
|
+
# then the caller invoked it again to get the evidence — halving throughput).
|
|
193
|
+
evidence = self._matched_imports(imports, _API_IMPORTS)
|
|
194
|
+
if evidence:
|
|
192
195
|
return FileClassification(norm, "api_layer", "high", 0.82, "imports API/server framework", evidence)
|
|
193
196
|
|
|
194
|
-
|
|
195
|
-
|
|
197
|
+
evidence = self._matched_imports(imports, _DB_IMPORTS)
|
|
198
|
+
if evidence:
|
|
196
199
|
return FileClassification(norm, "database_layer", "high", 0.78, "imports database/persistence dependency", evidence)
|
|
197
200
|
|
|
198
|
-
|
|
199
|
-
|
|
201
|
+
evidence = self._matched_imports(imports, _INFRA_IMPORTS)
|
|
202
|
+
if evidence:
|
|
200
203
|
return FileClassification(norm, "infrastructure", "high", 0.72, "imports infrastructure dependency", evidence)
|
|
201
204
|
|
|
202
205
|
role = self._package_role(norm)
|
|
@@ -650,7 +650,56 @@ def check_freshness(repo_path: str = ".") -> dict:
|
|
|
650
650
|
_path_err = _check_repo_path(repo_path)
|
|
651
651
|
if _path_err is not None:
|
|
652
652
|
return _path_err
|
|
653
|
-
|
|
653
|
+
|
|
654
|
+
# Call Python functions directly — avoids CliRunner/subprocess nesting
|
|
655
|
+
# that caused current_git_head to return "" on Windows parent-git repos.
|
|
656
|
+
import subprocess as _sp
|
|
657
|
+
from pathlib import Path as _Path
|
|
658
|
+
from sourcecode.cache import _get_git_head as _cache_head
|
|
659
|
+
from sourcecode.ris import load_ris as _load_ris, _has_uncommitted_changes as _huc
|
|
660
|
+
|
|
661
|
+
target = _Path(repo_path).resolve()
|
|
662
|
+
current_head = _cache_head(target)
|
|
663
|
+
ris = _load_ris(target)
|
|
664
|
+
|
|
665
|
+
if ris is None:
|
|
666
|
+
result: dict = {
|
|
667
|
+
"fresh": False,
|
|
668
|
+
"ris_exists": False,
|
|
669
|
+
"current_git_head": current_head,
|
|
670
|
+
"ris_git_head": None,
|
|
671
|
+
"delta_commits": None,
|
|
672
|
+
"has_uncommitted_changes": _huc(target),
|
|
673
|
+
"ris_last_updated_at": None,
|
|
674
|
+
}
|
|
675
|
+
else:
|
|
676
|
+
ris_head = ris.git_head
|
|
677
|
+
head_matches = bool(current_head and ris_head and current_head == ris_head)
|
|
678
|
+
uncommitted = _huc(target)
|
|
679
|
+
delta = None
|
|
680
|
+
if ris_head and current_head and ris_head != current_head:
|
|
681
|
+
try:
|
|
682
|
+
_r = _sp.run(
|
|
683
|
+
["git", "-C", str(target), "rev-list", "--count", f"{ris_head}..HEAD"],
|
|
684
|
+
capture_output=True, text=True, timeout=5,
|
|
685
|
+
)
|
|
686
|
+
if _r.returncode == 0:
|
|
687
|
+
delta = int(_r.stdout.strip())
|
|
688
|
+
except Exception:
|
|
689
|
+
pass
|
|
690
|
+
elif head_matches:
|
|
691
|
+
delta = 0
|
|
692
|
+
result = {
|
|
693
|
+
"fresh": head_matches and not uncommitted,
|
|
694
|
+
"ris_exists": True,
|
|
695
|
+
"current_git_head": current_head,
|
|
696
|
+
"ris_git_head": ris_head,
|
|
697
|
+
"delta_commits": delta,
|
|
698
|
+
"has_uncommitted_changes": uncommitted,
|
|
699
|
+
"ris_last_updated_at": ris.last_updated_at,
|
|
700
|
+
}
|
|
701
|
+
|
|
702
|
+
return _ok(result)
|
|
654
703
|
except Exception as exc:
|
|
655
704
|
return _err(
|
|
656
705
|
f"Internal error: {type(exc).__name__}: {exc} — repo_path: {_raw}",
|
|
@@ -1750,8 +1750,14 @@ class TaskContextBuilder:
|
|
|
1750
1750
|
for _cr in _commits_scanned:
|
|
1751
1751
|
_msg_lower = (_cr.message or "").lower()
|
|
1752
1752
|
if _kw_re.search(_msg_lower):
|
|
1753
|
+
_rn_prefix = self.root.name + "/"
|
|
1753
1754
|
for _cf in (_cr.files_changed or []):
|
|
1754
1755
|
_cf_norm = _cf.replace("\\", "/")
|
|
1756
|
+
# Git reports paths relative to the git root, which may be
|
|
1757
|
+
# a parent of the analyzed directory (e.g. MSAS/saint-server/).
|
|
1758
|
+
# Strip the analyzed-dir prefix so paths match all_paths.
|
|
1759
|
+
if _cf_norm.startswith(_rn_prefix):
|
|
1760
|
+
_cf_norm = _cf_norm[len(_rn_prefix):]
|
|
1755
1761
|
_commit_file_hits[_cf_norm] = _commit_file_hits.get(_cf_norm, 0) + 1
|
|
1756
1762
|
_sx_commits.append({
|
|
1757
1763
|
"message": (_cr.message or "")[:80],
|
|
@@ -1836,6 +1842,15 @@ class TaskContextBuilder:
|
|
|
1836
1842
|
# the candidate pool (e.g. AkitaBaseService containing setLoading).
|
|
1837
1843
|
_src_exts = frozenset({".java", ".py", ".ts", ".js", ".kt", ".go"})
|
|
1838
1844
|
_frontend_kws = [kw for kw in symptom_keywords if kw in _FRONTEND_SYMPTOM_MAP]
|
|
1845
|
+
# Fix 5: In large repos, skip frontend→backend synonym grep for keywords
|
|
1846
|
+
# that already have direct path matches — those are backend terms (e.g.
|
|
1847
|
+
# "login" in an IAM repo) that don't need UI→service-layer translation.
|
|
1848
|
+
# Prevents "authentication" grep flooding keycloak with SAML adapter files.
|
|
1849
|
+
if _is_large_repo and _frontend_kws:
|
|
1850
|
+
_frontend_kws = [
|
|
1851
|
+
kw for kw in _frontend_kws
|
|
1852
|
+
if not any(kw in p.lower() for p in _sx_direct_path)
|
|
1853
|
+
]
|
|
1839
1854
|
_backend_terms_set: list[str] = []
|
|
1840
1855
|
if _frontend_kws:
|
|
1841
1856
|
_bt: list[str] = []
|
|
@@ -1923,6 +1938,7 @@ class TaskContextBuilder:
|
|
|
1923
1938
|
_no_scan_candidates = relevant_files[_CONTENT_SCAN_LIMIT:]
|
|
1924
1939
|
|
|
1925
1940
|
_boosted: list[RelevantFile] = []
|
|
1941
|
+
_raw_signals: dict[str, float] = {} # uncapped accumulated signal per file
|
|
1926
1942
|
_scanned_body: dict[str, str] = {} # cache for graph expansion (Pass 5)
|
|
1927
1943
|
for _rf in _scan_candidates:
|
|
1928
1944
|
_extra = 0.0
|
|
@@ -1996,7 +2012,9 @@ class TaskContextBuilder:
|
|
|
1996
2012
|
elif _extra_syn > 0:
|
|
1997
2013
|
_new_reason = _rf.reason + f", synonym-match backend (+{_extra_syn:.2f})"
|
|
1998
2014
|
|
|
1999
|
-
|
|
2015
|
+
_raw_signal = _rf.score + _total_extra # uncapped for ranking
|
|
2016
|
+
_raw_signals[_rf.path] = _raw_signal
|
|
2017
|
+
_final_score = round(min(_raw_signal, 1.0), 2)
|
|
2000
2018
|
_boosted.append(RelevantFile(
|
|
2001
2019
|
path=_rf.path,
|
|
2002
2020
|
role=_rf.role,
|
|
@@ -2005,21 +2023,14 @@ class TaskContextBuilder:
|
|
|
2005
2023
|
why=_rf.why,
|
|
2006
2024
|
))
|
|
2007
2025
|
|
|
2008
|
-
#
|
|
2009
|
-
#
|
|
2010
|
-
#
|
|
2011
|
-
#
|
|
2012
|
-
|
|
2013
|
-
for _rf in _scan_candidates:
|
|
2014
|
-
pass # populated below
|
|
2015
|
-
_boost_totals = {}
|
|
2016
|
-
for _idx, _rf in enumerate(_scan_candidates):
|
|
2017
|
-
_b_rf = _boosted[_idx]
|
|
2018
|
-
_boost_totals[_b_rf.path] = round(_b_rf.score - _rf.score, 4)
|
|
2019
|
-
|
|
2026
|
+
# Sort by uncapped raw signal so files with more accumulated evidence
|
|
2027
|
+
# (path matches + content hits + commit matches) rank above files that
|
|
2028
|
+
# merely cap at the same display score of 1.0.
|
|
2029
|
+
# _raw_signals holds each file's full sum before the display cap.
|
|
2030
|
+
# Files not content-scanned (_no_scan_candidates) use their base score.
|
|
2020
2031
|
relevant_files = sorted(
|
|
2021
2032
|
_boosted + _no_scan_candidates,
|
|
2022
|
-
key=lambda rf:
|
|
2033
|
+
key=lambda rf: -_raw_signals.get(rf.path, rf.score),
|
|
2023
2034
|
)
|
|
2024
2035
|
|
|
2025
2036
|
# Pass 5: reverse graph expansion from high-score seed nodes.
|
|
@@ -2118,9 +2129,14 @@ class TaskContextBuilder:
|
|
|
2118
2129
|
if _gx_new:
|
|
2119
2130
|
relevant_files = sorted(
|
|
2120
2131
|
relevant_files + _gx_new,
|
|
2121
|
-
key=lambda rf:
|
|
2132
|
+
key=lambda rf: -_raw_signals.get(rf.path, rf.score),
|
|
2122
2133
|
)
|
|
2123
2134
|
|
|
2135
|
+
# Fix 2: Cap output for large repos to stay within agent context budgets.
|
|
2136
|
+
# Raw signal sort above ensures highest-signal files survive the cut.
|
|
2137
|
+
if _is_large_repo and len(relevant_files) > 40:
|
|
2138
|
+
relevant_files = relevant_files[:40]
|
|
2139
|
+
|
|
2124
2140
|
# Synonym note (only when synonyms actually fired)
|
|
2125
2141
|
if _frontend_kws and _sx_synonyms:
|
|
2126
2142
|
symptom_note = (
|
|
@@ -437,6 +437,18 @@ def get_cold_start_context(repo_root: Path) -> dict:
|
|
|
437
437
|
"endpoints": endpoints,
|
|
438
438
|
"hotspots": ris.git_context_snapshot.get("hotspots", []),
|
|
439
439
|
"validation": _validation,
|
|
440
|
+
# Fix 3: _cache wrapper for backward compat with CLI schema consumers.
|
|
441
|
+
# CLI outputs inject _cache via _inject_cache_meta; MCP cold-start path
|
|
442
|
+
# skips that step, leaving agents that read _cache.cache_source with None.
|
|
443
|
+
"_cache": {
|
|
444
|
+
"cache_source": "RIS",
|
|
445
|
+
"git_head_at_generation": ris.git_head or "",
|
|
446
|
+
"current_git_head": current_head or "",
|
|
447
|
+
"is_stale": stale,
|
|
448
|
+
"has_uncommitted_changes": uncommitted,
|
|
449
|
+
"generated_at": ris.last_updated_at,
|
|
450
|
+
"data_scope": "RIS_BOOTSTRAP",
|
|
451
|
+
},
|
|
440
452
|
}
|
|
441
453
|
if not endpoints and _is_java:
|
|
442
454
|
result["endpoints_hint"] = (
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|