sourcecode 0.47.0__tar.gz → 0.49.0__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-0.47.0 → sourcecode-0.49.0}/PKG-INFO +1 -1
- {sourcecode-0.47.0 → sourcecode-0.49.0}/pyproject.toml +1 -1
- {sourcecode-0.47.0 → sourcecode-0.49.0}/src/sourcecode/__init__.py +1 -1
- {sourcecode-0.47.0 → sourcecode-0.49.0}/src/sourcecode/cli.py +2 -0
- {sourcecode-0.47.0 → sourcecode-0.49.0}/src/sourcecode/context_scorer.py +2 -2
- {sourcecode-0.47.0 → sourcecode-0.49.0}/src/sourcecode/contract_pipeline.py +27 -7
- {sourcecode-0.47.0 → sourcecode-0.49.0}/src/sourcecode/prepare_context.py +1 -1
- {sourcecode-0.47.0 → sourcecode-0.49.0}/src/sourcecode/relevance_scorer.py +2 -1
- {sourcecode-0.47.0 → sourcecode-0.49.0}/src/sourcecode/serializer.py +39 -35
- {sourcecode-0.47.0 → sourcecode-0.49.0}/tests/test_real_projects.py +5 -4
- {sourcecode-0.47.0 → sourcecode-0.49.0}/.agents/skills/source-command-gsd-join-discord/SKILL.md +0 -0
- {sourcecode-0.47.0 → sourcecode-0.49.0}/.agents/skills/source-command-gsd-review-backlog/SKILL.md +0 -0
- {sourcecode-0.47.0 → sourcecode-0.49.0}/.agents/skills/source-command-gsd-workstreams/SKILL.md +0 -0
- {sourcecode-0.47.0 → sourcecode-0.49.0}/.gitignore +0 -0
- {sourcecode-0.47.0 → sourcecode-0.49.0}/.ruff.toml +0 -0
- {sourcecode-0.47.0 → sourcecode-0.49.0}/CONTRIBUTING.md +0 -0
- {sourcecode-0.47.0 → sourcecode-0.49.0}/LICENSE +0 -0
- {sourcecode-0.47.0 → sourcecode-0.49.0}/README.md +0 -0
- {sourcecode-0.47.0 → sourcecode-0.49.0}/SECURITY.md +0 -0
- {sourcecode-0.47.0 → sourcecode-0.49.0}/docs/privacy.md +0 -0
- {sourcecode-0.47.0 → sourcecode-0.49.0}/docs/schema.md +0 -0
- {sourcecode-0.47.0 → sourcecode-0.49.0}/raw +0 -0
- {sourcecode-0.47.0 → sourcecode-0.49.0}/src/sourcecode/adaptive_scanner.py +0 -0
- {sourcecode-0.47.0 → sourcecode-0.49.0}/src/sourcecode/architecture_analyzer.py +0 -0
- {sourcecode-0.47.0 → sourcecode-0.49.0}/src/sourcecode/architecture_summary.py +0 -0
- {sourcecode-0.47.0 → sourcecode-0.49.0}/src/sourcecode/ast_extractor.py +0 -0
- {sourcecode-0.47.0 → sourcecode-0.49.0}/src/sourcecode/classifier.py +0 -0
- {sourcecode-0.47.0 → sourcecode-0.49.0}/src/sourcecode/code_notes_analyzer.py +0 -0
- {sourcecode-0.47.0 → sourcecode-0.49.0}/src/sourcecode/confidence_analyzer.py +0 -0
- {sourcecode-0.47.0 → sourcecode-0.49.0}/src/sourcecode/context_summarizer.py +0 -0
- {sourcecode-0.47.0 → sourcecode-0.49.0}/src/sourcecode/contract_model.py +0 -0
- {sourcecode-0.47.0 → sourcecode-0.49.0}/src/sourcecode/coverage_parser.py +0 -0
- {sourcecode-0.47.0 → sourcecode-0.49.0}/src/sourcecode/dependency_analyzer.py +0 -0
- {sourcecode-0.47.0 → sourcecode-0.49.0}/src/sourcecode/detectors/__init__.py +0 -0
- {sourcecode-0.47.0 → sourcecode-0.49.0}/src/sourcecode/detectors/base.py +0 -0
- {sourcecode-0.47.0 → sourcecode-0.49.0}/src/sourcecode/detectors/csproj_parser.py +0 -0
- {sourcecode-0.47.0 → sourcecode-0.49.0}/src/sourcecode/detectors/dart.py +0 -0
- {sourcecode-0.47.0 → sourcecode-0.49.0}/src/sourcecode/detectors/dotnet.py +0 -0
- {sourcecode-0.47.0 → sourcecode-0.49.0}/src/sourcecode/detectors/elixir.py +0 -0
- {sourcecode-0.47.0 → sourcecode-0.49.0}/src/sourcecode/detectors/go.py +0 -0
- {sourcecode-0.47.0 → sourcecode-0.49.0}/src/sourcecode/detectors/heuristic.py +0 -0
- {sourcecode-0.47.0 → sourcecode-0.49.0}/src/sourcecode/detectors/hybrid.py +0 -0
- {sourcecode-0.47.0 → sourcecode-0.49.0}/src/sourcecode/detectors/java.py +0 -0
- {sourcecode-0.47.0 → sourcecode-0.49.0}/src/sourcecode/detectors/jvm_ext.py +0 -0
- {sourcecode-0.47.0 → sourcecode-0.49.0}/src/sourcecode/detectors/nodejs.py +0 -0
- {sourcecode-0.47.0 → sourcecode-0.49.0}/src/sourcecode/detectors/parsers.py +0 -0
- {sourcecode-0.47.0 → sourcecode-0.49.0}/src/sourcecode/detectors/php.py +0 -0
- {sourcecode-0.47.0 → sourcecode-0.49.0}/src/sourcecode/detectors/project.py +0 -0
- {sourcecode-0.47.0 → sourcecode-0.49.0}/src/sourcecode/detectors/python.py +0 -0
- {sourcecode-0.47.0 → sourcecode-0.49.0}/src/sourcecode/detectors/ruby.py +0 -0
- {sourcecode-0.47.0 → sourcecode-0.49.0}/src/sourcecode/detectors/rust.py +0 -0
- {sourcecode-0.47.0 → sourcecode-0.49.0}/src/sourcecode/detectors/systems.py +0 -0
- {sourcecode-0.47.0 → sourcecode-0.49.0}/src/sourcecode/detectors/terraform.py +0 -0
- {sourcecode-0.47.0 → sourcecode-0.49.0}/src/sourcecode/detectors/tooling.py +0 -0
- {sourcecode-0.47.0 → sourcecode-0.49.0}/src/sourcecode/doc_analyzer.py +0 -0
- {sourcecode-0.47.0 → sourcecode-0.49.0}/src/sourcecode/entrypoint_classifier.py +0 -0
- {sourcecode-0.47.0 → sourcecode-0.49.0}/src/sourcecode/env_analyzer.py +0 -0
- {sourcecode-0.47.0 → sourcecode-0.49.0}/src/sourcecode/file_classifier.py +0 -0
- {sourcecode-0.47.0 → sourcecode-0.49.0}/src/sourcecode/git_analyzer.py +0 -0
- {sourcecode-0.47.0 → sourcecode-0.49.0}/src/sourcecode/graph_analyzer.py +0 -0
- {sourcecode-0.47.0 → sourcecode-0.49.0}/src/sourcecode/metrics_analyzer.py +0 -0
- {sourcecode-0.47.0 → sourcecode-0.49.0}/src/sourcecode/ranking_engine.py +0 -0
- {sourcecode-0.47.0 → sourcecode-0.49.0}/src/sourcecode/redactor.py +0 -0
- {sourcecode-0.47.0 → sourcecode-0.49.0}/src/sourcecode/repo_classifier.py +0 -0
- {sourcecode-0.47.0 → sourcecode-0.49.0}/src/sourcecode/runtime_classifier.py +0 -0
- {sourcecode-0.47.0 → sourcecode-0.49.0}/src/sourcecode/scanner.py +0 -0
- {sourcecode-0.47.0 → sourcecode-0.49.0}/src/sourcecode/schema.py +0 -0
- {sourcecode-0.47.0 → sourcecode-0.49.0}/src/sourcecode/semantic_analyzer.py +0 -0
- {sourcecode-0.47.0 → sourcecode-0.49.0}/src/sourcecode/summarizer.py +0 -0
- {sourcecode-0.47.0 → sourcecode-0.49.0}/src/sourcecode/telemetry/__init__.py +0 -0
- {sourcecode-0.47.0 → sourcecode-0.49.0}/src/sourcecode/telemetry/config.py +0 -0
- {sourcecode-0.47.0 → sourcecode-0.49.0}/src/sourcecode/telemetry/consent.py +0 -0
- {sourcecode-0.47.0 → sourcecode-0.49.0}/src/sourcecode/telemetry/events.py +0 -0
- {sourcecode-0.47.0 → sourcecode-0.49.0}/src/sourcecode/telemetry/filters.py +0 -0
- {sourcecode-0.47.0 → sourcecode-0.49.0}/src/sourcecode/telemetry/transport.py +0 -0
- {sourcecode-0.47.0 → sourcecode-0.49.0}/src/sourcecode/tree_utils.py +0 -0
- {sourcecode-0.47.0 → sourcecode-0.49.0}/src/sourcecode/workspace.py +0 -0
- {sourcecode-0.47.0 → sourcecode-0.49.0}/tests/__init__.py +0 -0
- {sourcecode-0.47.0 → sourcecode-0.49.0}/tests/conftest.py +0 -0
- {sourcecode-0.47.0 → sourcecode-0.49.0}/tests/fixtures/coverage.xml +0 -0
- {sourcecode-0.47.0 → sourcecode-0.49.0}/tests/fixtures/fastapi_app/pyproject.toml +0 -0
- {sourcecode-0.47.0 → sourcecode-0.49.0}/tests/fixtures/fastapi_app/src/main.py +0 -0
- {sourcecode-0.47.0 → sourcecode-0.49.0}/tests/fixtures/go_service/cmd/api/main.go +0 -0
- {sourcecode-0.47.0 → sourcecode-0.49.0}/tests/fixtures/go_service/go.mod +0 -0
- {sourcecode-0.47.0 → sourcecode-0.49.0}/tests/fixtures/jacoco.xml +0 -0
- {sourcecode-0.47.0 → sourcecode-0.49.0}/tests/fixtures/lcov.info +0 -0
- {sourcecode-0.47.0 → sourcecode-0.49.0}/tests/fixtures/nextjs_app/app/page.tsx +0 -0
- {sourcecode-0.47.0 → sourcecode-0.49.0}/tests/fixtures/nextjs_app/package.json +0 -0
- {sourcecode-0.47.0 → sourcecode-0.49.0}/tests/fixtures/nextjs_app/pnpm-lock.yaml +0 -0
- {sourcecode-0.47.0 → sourcecode-0.49.0}/tests/fixtures/pnpm_monorepo/apps/web/app/page.tsx +0 -0
- {sourcecode-0.47.0 → sourcecode-0.49.0}/tests/fixtures/pnpm_monorepo/apps/web/package.json +0 -0
- {sourcecode-0.47.0 → sourcecode-0.49.0}/tests/fixtures/pnpm_monorepo/packages/api/main.py +0 -0
- {sourcecode-0.47.0 → sourcecode-0.49.0}/tests/fixtures/pnpm_monorepo/packages/api/pyproject.toml +0 -0
- {sourcecode-0.47.0 → sourcecode-0.49.0}/tests/fixtures/pnpm_monorepo/pnpm-workspace.yaml +0 -0
- {sourcecode-0.47.0 → sourcecode-0.49.0}/tests/test_architecture_analyzer.py +0 -0
- {sourcecode-0.47.0 → sourcecode-0.49.0}/tests/test_architecture_summary.py +0 -0
- {sourcecode-0.47.0 → sourcecode-0.49.0}/tests/test_ast_extractor.py +0 -0
- {sourcecode-0.47.0 → sourcecode-0.49.0}/tests/test_block1_reliability.py +0 -0
- {sourcecode-0.47.0 → sourcecode-0.49.0}/tests/test_block2_coverage.py +0 -0
- {sourcecode-0.47.0 → sourcecode-0.49.0}/tests/test_block5_quality.py +0 -0
- {sourcecode-0.47.0 → sourcecode-0.49.0}/tests/test_classifier.py +0 -0
- {sourcecode-0.47.0 → sourcecode-0.49.0}/tests/test_cli.py +0 -0
- {sourcecode-0.47.0 → sourcecode-0.49.0}/tests/test_code_notes_analyzer.py +0 -0
- {sourcecode-0.47.0 → sourcecode-0.49.0}/tests/test_context_scorer.py +0 -0
- {sourcecode-0.47.0 → sourcecode-0.49.0}/tests/test_contract_pipeline.py +0 -0
- {sourcecode-0.47.0 → sourcecode-0.49.0}/tests/test_coverage_parser.py +0 -0
- {sourcecode-0.47.0 → sourcecode-0.49.0}/tests/test_cross_consistency.py +0 -0
- {sourcecode-0.47.0 → sourcecode-0.49.0}/tests/test_dependency_analyzer_node_python.py +0 -0
- {sourcecode-0.47.0 → sourcecode-0.49.0}/tests/test_dependency_analyzer_polyglot.py +0 -0
- {sourcecode-0.47.0 → sourcecode-0.49.0}/tests/test_dependency_schema.py +0 -0
- {sourcecode-0.47.0 → sourcecode-0.49.0}/tests/test_detector_dotnet.py +0 -0
- {sourcecode-0.47.0 → sourcecode-0.49.0}/tests/test_detector_go_rust_java.py +0 -0
- {sourcecode-0.47.0 → sourcecode-0.49.0}/tests/test_detector_nodejs.py +0 -0
- {sourcecode-0.47.0 → sourcecode-0.49.0}/tests/test_detector_php_ruby_dart.py +0 -0
- {sourcecode-0.47.0 → sourcecode-0.49.0}/tests/test_detector_python.py +0 -0
- {sourcecode-0.47.0 → sourcecode-0.49.0}/tests/test_detector_universal_managed.py +0 -0
- {sourcecode-0.47.0 → sourcecode-0.49.0}/tests/test_detector_universal_systems.py +0 -0
- {sourcecode-0.47.0 → sourcecode-0.49.0}/tests/test_detectors_base.py +0 -0
- {sourcecode-0.47.0 → sourcecode-0.49.0}/tests/test_doc_analyzer_jsdom.py +0 -0
- {sourcecode-0.47.0 → sourcecode-0.49.0}/tests/test_doc_analyzer_python.py +0 -0
- {sourcecode-0.47.0 → sourcecode-0.49.0}/tests/test_graph_analyzer_polyglot.py +0 -0
- {sourcecode-0.47.0 → sourcecode-0.49.0}/tests/test_graph_analyzer_python_node.py +0 -0
- {sourcecode-0.47.0 → sourcecode-0.49.0}/tests/test_graph_schema.py +0 -0
- {sourcecode-0.47.0 → sourcecode-0.49.0}/tests/test_hybrid_inference.py +0 -0
- {sourcecode-0.47.0 → sourcecode-0.49.0}/tests/test_integration.py +0 -0
- {sourcecode-0.47.0 → sourcecode-0.49.0}/tests/test_integration_dependencies.py +0 -0
- {sourcecode-0.47.0 → sourcecode-0.49.0}/tests/test_integration_detection.py +0 -0
- {sourcecode-0.47.0 → sourcecode-0.49.0}/tests/test_integration_docs.py +0 -0
- {sourcecode-0.47.0 → sourcecode-0.49.0}/tests/test_integration_graph_modules.py +0 -0
- {sourcecode-0.47.0 → sourcecode-0.49.0}/tests/test_integration_lqn.py +0 -0
- {sourcecode-0.47.0 → sourcecode-0.49.0}/tests/test_integration_metrics.py +0 -0
- {sourcecode-0.47.0 → sourcecode-0.49.0}/tests/test_integration_multistack.py +0 -0
- {sourcecode-0.47.0 → sourcecode-0.49.0}/tests/test_integration_semantics.py +0 -0
- {sourcecode-0.47.0 → sourcecode-0.49.0}/tests/test_integration_universal.py +0 -0
- {sourcecode-0.47.0 → sourcecode-0.49.0}/tests/test_metrics_analyzer.py +0 -0
- {sourcecode-0.47.0 → sourcecode-0.49.0}/tests/test_packaging.py +0 -0
- {sourcecode-0.47.0 → sourcecode-0.49.0}/tests/test_phase1_improvements.py +0 -0
- {sourcecode-0.47.0 → sourcecode-0.49.0}/tests/test_pipeline_integrity.py +0 -0
- {sourcecode-0.47.0 → sourcecode-0.49.0}/tests/test_redactor.py +0 -0
- {sourcecode-0.47.0 → sourcecode-0.49.0}/tests/test_scanner.py +0 -0
- {sourcecode-0.47.0 → sourcecode-0.49.0}/tests/test_schema.py +0 -0
- {sourcecode-0.47.0 → sourcecode-0.49.0}/tests/test_schema_normalization.py +0 -0
- {sourcecode-0.47.0 → sourcecode-0.49.0}/tests/test_semantic_analyzer_node.py +0 -0
- {sourcecode-0.47.0 → sourcecode-0.49.0}/tests/test_semantic_analyzer_python.py +0 -0
- {sourcecode-0.47.0 → sourcecode-0.49.0}/tests/test_semantic_import_resolution.py +0 -0
- {sourcecode-0.47.0 → sourcecode-0.49.0}/tests/test_semantic_schema.py +0 -0
- {sourcecode-0.47.0 → sourcecode-0.49.0}/tests/test_signal_hierarchy.py +0 -0
- {sourcecode-0.47.0 → sourcecode-0.49.0}/tests/test_summarizer.py +0 -0
- {sourcecode-0.47.0 → sourcecode-0.49.0}/tests/test_telemetry.py +0 -0
- {sourcecode-0.47.0 → sourcecode-0.49.0}/tests/test_workspace_analyzer.py +0 -0
|
@@ -1445,8 +1445,10 @@ def main(
|
|
|
1445
1445
|
data = agent_view(sm)
|
|
1446
1446
|
# When contract pipeline ran (mode=contract, no legacy flags), include
|
|
1447
1447
|
# per-file contracts in agent output so agents get structural context.
|
|
1448
|
+
# Remove file_relevance — contracts cover this signal with more detail.
|
|
1448
1449
|
if _is_contract_mode and sm.file_contracts:
|
|
1449
1450
|
from sourcecode.serializer import _serialize_contract_minimal
|
|
1451
|
+
data.pop("file_relevance", None)
|
|
1450
1452
|
data["contracts"] = [_serialize_contract_minimal(c) for c in sm.file_contracts]
|
|
1451
1453
|
if sm.contract_summary is not None:
|
|
1452
1454
|
cs = sm.contract_summary
|
|
@@ -177,8 +177,8 @@ class ContextScorer:
|
|
|
177
177
|
node_scores: dict[str, NodeScore],
|
|
178
178
|
contracts: list[Any],
|
|
179
179
|
*,
|
|
180
|
-
budget: int =
|
|
181
|
-
min_score: float = 0.
|
|
180
|
+
budget: int = 25,
|
|
181
|
+
min_score: float = 0.15,
|
|
182
182
|
) -> list[str]:
|
|
183
183
|
"""Greedy minimum-sufficient subgraph selection with diversity re-ranking.
|
|
184
184
|
|
|
@@ -17,6 +17,7 @@ from typing import Any, Literal, Optional
|
|
|
17
17
|
|
|
18
18
|
from sourcecode.ast_extractor import AstExtractor, _LANGUAGE_MAP
|
|
19
19
|
from sourcecode.contract_model import ContractSummary, FileContract
|
|
20
|
+
from sourcecode.entrypoint_classifier import is_production_entry_point
|
|
20
21
|
from sourcecode.ranking_engine import RankingEngine
|
|
21
22
|
from sourcecode.relevance_scorer import RelevanceScorer
|
|
22
23
|
from sourcecode.schema import EntryPoint, MonorepoPackageInfo
|
|
@@ -25,7 +26,9 @@ from sourcecode.schema import EntryPoint, MonorepoPackageInfo
|
|
|
25
26
|
# Constants
|
|
26
27
|
# ---------------------------------------------------------------------------
|
|
27
28
|
|
|
28
|
-
_MAX_FILES = 500
|
|
29
|
+
_MAX_FILES = 500 # hard cap on files extracted per run
|
|
30
|
+
_MAX_CONTRACTS = 15 # default top-N output cap — omit rather than flood
|
|
31
|
+
_MIN_CONTRACT_SCORE = 0.15 # drop contracts below this relevance threshold
|
|
29
32
|
_SRC_EXTENSIONS: frozenset[str] = frozenset(_LANGUAGE_MAP.keys())
|
|
30
33
|
|
|
31
34
|
|
|
@@ -178,12 +181,20 @@ class ContractPipeline:
|
|
|
178
181
|
max_importers: int = 50,
|
|
179
182
|
semantic_calls: Optional[list] = None,
|
|
180
183
|
code_notes: Optional[list] = None,
|
|
184
|
+
max_contracts: Optional[int] = _MAX_CONTRACTS,
|
|
181
185
|
) -> tuple[list[FileContract], ContractSummary]:
|
|
182
186
|
"""Run the full extraction pipeline.
|
|
183
187
|
|
|
184
188
|
Returns (ranked_contracts, summary).
|
|
185
189
|
"""
|
|
186
|
-
|
|
190
|
+
# Only treat production-classified entrypoints as anchors.
|
|
191
|
+
# Convention/heuristic entrypoints (index.ts barrels, plugin examples)
|
|
192
|
+
# must not bubble to the top via is_entrypoint=True ranking boost.
|
|
193
|
+
entry_paths = {
|
|
194
|
+
ep.path.replace("\\", "/")
|
|
195
|
+
for ep in (entry_points or [])
|
|
196
|
+
if is_production_entry_point(ep)
|
|
197
|
+
}
|
|
187
198
|
scorer = RelevanceScorer(monorepo_packages)
|
|
188
199
|
engine = RankingEngine(monorepo_packages)
|
|
189
200
|
|
|
@@ -299,16 +310,25 @@ class ContractPipeline:
|
|
|
299
310
|
max_importers=max_importers,
|
|
300
311
|
)
|
|
301
312
|
|
|
302
|
-
# 9. Entrypoints-only filter
|
|
313
|
+
# 9. Entrypoints-only filter — production entry points only, no export spill
|
|
303
314
|
if entrypoints_only and not symbol:
|
|
304
|
-
contracts = [c for c in contracts if c.is_entrypoint
|
|
305
|
-
|
|
306
|
-
# 10.
|
|
315
|
+
contracts = [c for c in contracts if c.is_entrypoint]
|
|
316
|
+
|
|
317
|
+
# 10. Top-N cap — enforce max_contracts when not in symbol-search mode.
|
|
318
|
+
# Symbol searches must return all matching files; budget applies only to
|
|
319
|
+
# the default architectural briefing use case.
|
|
320
|
+
if symbol is None and max_contracts is not None:
|
|
321
|
+
contracts = [
|
|
322
|
+
c for c in contracts
|
|
323
|
+
if c.relevance_score >= _MIN_CONTRACT_SCORE or c.is_entrypoint
|
|
324
|
+
][:max_contracts]
|
|
325
|
+
|
|
326
|
+
# 11. Compress types if requested
|
|
307
327
|
if compress_types:
|
|
308
328
|
for c in contracts:
|
|
309
329
|
_compress_contract_types(c)
|
|
310
330
|
|
|
311
|
-
#
|
|
331
|
+
# 12. Apply max_symbols limit (limits total exports across all contracts)
|
|
312
332
|
if max_symbols is not None and max_symbols > 0:
|
|
313
333
|
contracts = _limit_symbols(contracts, max_symbols)
|
|
314
334
|
|
|
@@ -758,7 +758,7 @@ class TaskContextBuilder:
|
|
|
758
758
|
)
|
|
759
759
|
for total, path, rf in scored
|
|
760
760
|
}
|
|
761
|
-
_selected = _ctx.select_subgraph(_ns, contracts=[], budget=15, min_score=0.
|
|
761
|
+
_selected = _ctx.select_subgraph(_ns, contracts=[], budget=15, min_score=0.15)
|
|
762
762
|
_rf_map = {path: rf for _, path, rf in scored}
|
|
763
763
|
return [_rf_map[p] for p in _selected if p in _rf_map]
|
|
764
764
|
except Exception:
|
|
@@ -124,8 +124,9 @@ _HIGH_VALUE_SUFFIXES: frozenset[str] = frozenset({
|
|
|
124
124
|
})
|
|
125
125
|
|
|
126
126
|
_ENTRYPOINT_STEMS: frozenset[str] = frozenset({
|
|
127
|
-
"main", "cli", "app", "server", "
|
|
127
|
+
"main", "cli", "app", "server", "__main__",
|
|
128
128
|
"application", "bootstrap", "entry",
|
|
129
|
+
# "index" removed — barrel export convention, not a runtime entrypoint signal
|
|
129
130
|
})
|
|
130
131
|
|
|
131
132
|
|
|
@@ -31,7 +31,7 @@ from sourcecode.schema import (
|
|
|
31
31
|
_EP_PRODUCTION_CAP = 5 # max production entry points in default output
|
|
32
32
|
_EP_DEV_CAP = 3 # max development entry points in default output
|
|
33
33
|
_FILE_RELEVANCE_LIMIT = 10 # max files in file_relevance section
|
|
34
|
-
_FILE_RELEVANCE_MIN_COMBINED = 0.
|
|
34
|
+
_FILE_RELEVANCE_MIN_COMBINED = 0.40 # minimum combined score — must earn inclusion
|
|
35
35
|
_PROD_DEPS_CAP = 10 # max production dependencies shown
|
|
36
36
|
_SECONDARY_DEPS_CAP = 5 # max per dev/test/build dependency group
|
|
37
37
|
_MONOREPO_PKGS_CAP = 8 # max workspace/runtime packages shown
|
|
@@ -1130,9 +1130,6 @@ def _contract_view_minimal(
|
|
|
1130
1130
|
"project": project,
|
|
1131
1131
|
}
|
|
1132
1132
|
|
|
1133
|
-
if sm.metadata.traversal_topology:
|
|
1134
|
-
result["traversal"] = sm.metadata.traversal_topology
|
|
1135
|
-
|
|
1136
1133
|
# Per-file contracts
|
|
1137
1134
|
if contracts:
|
|
1138
1135
|
serialized: list[dict[str, Any]] = []
|
|
@@ -1310,6 +1307,10 @@ def _compress_sig(name: str, sig: str, max_len: int = 100) -> str:
|
|
|
1310
1307
|
return full
|
|
1311
1308
|
|
|
1312
1309
|
|
|
1310
|
+
_MAX_FN_PER_CONTRACT = 5 # max function signatures per contract (token budget)
|
|
1311
|
+
_MAX_SIG_LEN = 60 # max chars per compressed signature
|
|
1312
|
+
|
|
1313
|
+
|
|
1313
1314
|
def _serialize_contract_minimal(c: Any) -> dict[str, Any]:
|
|
1314
1315
|
"""Serialize one FileContract to minimal format."""
|
|
1315
1316
|
item: dict[str, Any] = {"path": c.path, "role": c.role}
|
|
@@ -1317,38 +1318,47 @@ def _serialize_contract_minimal(c: Any) -> dict[str, Any]:
|
|
|
1317
1318
|
if c.is_changed:
|
|
1318
1319
|
item["changed"] = True
|
|
1319
1320
|
|
|
1320
|
-
#
|
|
1321
|
-
# When all exports are same non-function kind, group them
|
|
1322
|
-
if c.exports:
|
|
1323
|
-
exs: list[Any] = []
|
|
1324
|
-
kinds = {e.kind for e in c.exports}
|
|
1325
|
-
if len(kinds) == 1 and "function" not in kinds and "unknown" not in kinds:
|
|
1326
|
-
# All same non-function kind — compact: {"k": "class", "names": [...]}
|
|
1327
|
-
only_kind = next(iter(kinds))
|
|
1328
|
-
exs = [{"k": only_kind, "names": sorted(e.name for e in c.exports)}]
|
|
1329
|
-
else:
|
|
1330
|
-
for e in sorted(c.exports, key=lambda e: e.name):
|
|
1331
|
-
if e.kind in ("function", "unknown"):
|
|
1332
|
-
exs.append(e.name)
|
|
1333
|
-
else:
|
|
1334
|
-
exs.append({"name": e.name, "k": e.kind})
|
|
1335
|
-
item["exports"] = exs
|
|
1336
|
-
|
|
1337
|
-
# External deps (non-stdlib already filtered in extractor)
|
|
1338
|
-
if c.dependencies:
|
|
1339
|
-
item["deps"] = sorted(c.dependencies)
|
|
1340
|
-
|
|
1341
|
-
# Exported function signatures — compressed
|
|
1321
|
+
# Exported function signatures — compressed, capped
|
|
1342
1322
|
exported_names = {e.name for e in c.exports}
|
|
1323
|
+
fn_names_in_sigs: set[str] = set()
|
|
1343
1324
|
if c.functions:
|
|
1344
1325
|
fns = []
|
|
1345
1326
|
for f in sorted(c.functions, key=lambda f: f.name):
|
|
1346
1327
|
if not (f.exported or f.name in exported_names):
|
|
1347
1328
|
continue
|
|
1348
|
-
fns.append(_compress_sig(f.name, f.signature))
|
|
1329
|
+
fns.append(_compress_sig(f.name, f.signature, max_len=_MAX_SIG_LEN))
|
|
1330
|
+
fn_names_in_sigs.add(f.name)
|
|
1331
|
+
if len(fns) >= _MAX_FN_PER_CONTRACT:
|
|
1332
|
+
break
|
|
1349
1333
|
if fns:
|
|
1350
1334
|
item["fn"] = fns
|
|
1351
1335
|
|
|
1336
|
+
# Exports: omit function names already shown in fn; keep non-function exports
|
|
1337
|
+
if c.exports:
|
|
1338
|
+
exs: list[Any] = []
|
|
1339
|
+
non_fn_exports = [e for e in c.exports if e.kind not in ("function", "unknown")]
|
|
1340
|
+
fn_exports_not_in_sig = [
|
|
1341
|
+
e for e in c.exports
|
|
1342
|
+
if e.kind in ("function", "unknown") and e.name not in fn_names_in_sigs
|
|
1343
|
+
]
|
|
1344
|
+
remaining = non_fn_exports + fn_exports_not_in_sig
|
|
1345
|
+
if remaining:
|
|
1346
|
+
kinds = {e.kind for e in remaining}
|
|
1347
|
+
if len(kinds) == 1 and "function" not in kinds and "unknown" not in kinds:
|
|
1348
|
+
only_kind = next(iter(kinds))
|
|
1349
|
+
exs = [{"k": only_kind, "names": sorted(e.name for e in remaining)}]
|
|
1350
|
+
else:
|
|
1351
|
+
for e in sorted(remaining, key=lambda e: e.name):
|
|
1352
|
+
if e.kind in ("function", "unknown"):
|
|
1353
|
+
exs.append(e.name)
|
|
1354
|
+
else:
|
|
1355
|
+
exs.append({"name": e.name, "k": e.kind})
|
|
1356
|
+
item["exports"] = exs
|
|
1357
|
+
|
|
1358
|
+
# External deps (non-stdlib already filtered in extractor)
|
|
1359
|
+
if c.dependencies:
|
|
1360
|
+
item["deps"] = sorted(c.dependencies)
|
|
1361
|
+
|
|
1352
1362
|
# Types: skip if fully covered by exports (avoids duplication in model files)
|
|
1353
1363
|
if c.types:
|
|
1354
1364
|
export_names_set = {e.name for e in c.exports}
|
|
@@ -1363,12 +1373,6 @@ def _serialize_contract_minimal(c: Any) -> dict[str, Any]:
|
|
|
1363
1373
|
if c.hooks_used:
|
|
1364
1374
|
item["hooks"] = c.hooks_used
|
|
1365
1375
|
|
|
1366
|
-
# Ranking signals: why this file was ranked here
|
|
1367
|
-
if getattr(c, "ranking_reasons", None):
|
|
1368
|
-
non_trivial = [r for r in c.ranking_reasons if r not in ("source file", "noise")]
|
|
1369
|
-
if non_trivial:
|
|
1370
|
-
item["why"] = non_trivial
|
|
1371
|
-
|
|
1372
1376
|
return item
|
|
1373
1377
|
|
|
1374
1378
|
|
|
@@ -1409,12 +1413,12 @@ def _contract_view_standard(
|
|
|
1409
1413
|
"package_manager": s.package_manager}
|
|
1410
1414
|
for s in sm.stacks
|
|
1411
1415
|
],
|
|
1412
|
-
"entry_points": ep_groups["production"],
|
|
1416
|
+
"entry_points": ep_groups["production"][:_EP_PRODUCTION_CAP],
|
|
1413
1417
|
}
|
|
1414
1418
|
if sm.metadata.traversal_topology:
|
|
1415
1419
|
result["traversal"] = sm.metadata.traversal_topology
|
|
1416
1420
|
if ep_groups["development"]:
|
|
1417
|
-
result["development_entry_points"] = ep_groups["development"]
|
|
1421
|
+
result["development_entry_points"] = ep_groups["development"][:_EP_DEV_CAP]
|
|
1418
1422
|
|
|
1419
1423
|
if sm.confidence_summary is not None:
|
|
1420
1424
|
result["confidence"] = {
|
|
@@ -40,8 +40,9 @@ def test_fastapi_fixture_schema() -> None:
|
|
|
40
40
|
assert data["project_type"] == "api"
|
|
41
41
|
assert data["stacks"][0]["stack"] == "python"
|
|
42
42
|
assert data["stacks"][0]["frameworks"][0]["name"] == "FastAPI"
|
|
43
|
-
|
|
44
|
-
|
|
43
|
+
# src/main.py is detected via convention — classified auxiliary and suppressed
|
|
44
|
+
# from default output per filtering policy. Verify detection still ran.
|
|
45
|
+
assert "entry_points" in data
|
|
45
46
|
|
|
46
47
|
|
|
47
48
|
def test_go_fixture_schema() -> None:
|
|
@@ -64,5 +65,5 @@ def test_monorepo_fixture_schema() -> None:
|
|
|
64
65
|
assert data["project_type"] == "monorepo"
|
|
65
66
|
assert {stack["stack"] for stack in data["stacks"]} == {"nodejs", "python"}
|
|
66
67
|
assert {stack["root"] for stack in data["stacks"]} == {"apps/web", "packages/api"}
|
|
67
|
-
|
|
68
|
-
assert
|
|
68
|
+
# Convention-detected workspace entries are suppressed from default output.
|
|
69
|
+
assert "entry_points" in data
|
{sourcecode-0.47.0 → sourcecode-0.49.0}/.agents/skills/source-command-gsd-join-discord/SKILL.md
RENAMED
|
File without changes
|
{sourcecode-0.47.0 → sourcecode-0.49.0}/.agents/skills/source-command-gsd-review-backlog/SKILL.md
RENAMED
|
File without changes
|
{sourcecode-0.47.0 → sourcecode-0.49.0}/.agents/skills/source-command-gsd-workstreams/SKILL.md
RENAMED
|
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
|
{sourcecode-0.47.0 → sourcecode-0.49.0}/tests/fixtures/pnpm_monorepo/packages/api/pyproject.toml
RENAMED
|
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
|