sourcecode 1.30.20__tar.gz → 1.30.22__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.30.20 → sourcecode-1.30.22}/PKG-INFO +3 -3
- {sourcecode-1.30.20 → sourcecode-1.30.22}/README.md +2 -2
- {sourcecode-1.30.20 → sourcecode-1.30.22}/pyproject.toml +1 -1
- {sourcecode-1.30.20 → sourcecode-1.30.22}/src/sourcecode/__init__.py +1 -1
- {sourcecode-1.30.20 → sourcecode-1.30.22}/src/sourcecode/cli.py +119 -8
- {sourcecode-1.30.20 → sourcecode-1.30.22}/src/sourcecode/prepare_context.py +79 -51
- sourcecode-1.30.22/tests/test_output_ux.py +235 -0
- {sourcecode-1.30.20 → sourcecode-1.30.22}/.agents/skills/source-command-gsd-join-discord/SKILL.md +0 -0
- {sourcecode-1.30.20 → sourcecode-1.30.22}/.agents/skills/source-command-gsd-review-backlog/SKILL.md +0 -0
- {sourcecode-1.30.20 → sourcecode-1.30.22}/.agents/skills/source-command-gsd-workstreams/SKILL.md +0 -0
- {sourcecode-1.30.20 → sourcecode-1.30.22}/.continue-here.md +0 -0
- {sourcecode-1.30.20 → sourcecode-1.30.22}/.github/workflows/build-windows.yml +0 -0
- {sourcecode-1.30.20 → sourcecode-1.30.22}/.gitignore +0 -0
- {sourcecode-1.30.20 → sourcecode-1.30.22}/.ruff.toml +0 -0
- {sourcecode-1.30.20 → sourcecode-1.30.22}/CONTRIBUTING.md +0 -0
- {sourcecode-1.30.20 → sourcecode-1.30.22}/LICENSE +0 -0
- {sourcecode-1.30.20 → sourcecode-1.30.22}/SECURITY.md +0 -0
- {sourcecode-1.30.20 → sourcecode-1.30.22}/docs/privacy.md +0 -0
- {sourcecode-1.30.20 → sourcecode-1.30.22}/docs/schema.md +0 -0
- {sourcecode-1.30.20 → sourcecode-1.30.22}/raw +0 -0
- {sourcecode-1.30.20 → sourcecode-1.30.22}/run_cli.py +0 -0
- {sourcecode-1.30.20 → sourcecode-1.30.22}/src/sourcecode/adaptive_scanner.py +0 -0
- {sourcecode-1.30.20 → sourcecode-1.30.22}/src/sourcecode/architecture_analyzer.py +0 -0
- {sourcecode-1.30.20 → sourcecode-1.30.22}/src/sourcecode/architecture_summary.py +0 -0
- {sourcecode-1.30.20 → sourcecode-1.30.22}/src/sourcecode/ast_extractor.py +0 -0
- {sourcecode-1.30.20 → sourcecode-1.30.22}/src/sourcecode/classifier.py +0 -0
- {sourcecode-1.30.20 → sourcecode-1.30.22}/src/sourcecode/code_notes_analyzer.py +0 -0
- {sourcecode-1.30.20 → sourcecode-1.30.22}/src/sourcecode/confidence_analyzer.py +0 -0
- {sourcecode-1.30.20 → sourcecode-1.30.22}/src/sourcecode/context_scorer.py +0 -0
- {sourcecode-1.30.20 → sourcecode-1.30.22}/src/sourcecode/context_summarizer.py +0 -0
- {sourcecode-1.30.20 → sourcecode-1.30.22}/src/sourcecode/contract_model.py +0 -0
- {sourcecode-1.30.20 → sourcecode-1.30.22}/src/sourcecode/contract_pipeline.py +0 -0
- {sourcecode-1.30.20 → sourcecode-1.30.22}/src/sourcecode/coverage_parser.py +0 -0
- {sourcecode-1.30.20 → sourcecode-1.30.22}/src/sourcecode/dependency_analyzer.py +0 -0
- {sourcecode-1.30.20 → sourcecode-1.30.22}/src/sourcecode/detectors/__init__.py +0 -0
- {sourcecode-1.30.20 → sourcecode-1.30.22}/src/sourcecode/detectors/base.py +0 -0
- {sourcecode-1.30.20 → sourcecode-1.30.22}/src/sourcecode/detectors/csproj_parser.py +0 -0
- {sourcecode-1.30.20 → sourcecode-1.30.22}/src/sourcecode/detectors/dart.py +0 -0
- {sourcecode-1.30.20 → sourcecode-1.30.22}/src/sourcecode/detectors/dotnet.py +0 -0
- {sourcecode-1.30.20 → sourcecode-1.30.22}/src/sourcecode/detectors/elixir.py +0 -0
- {sourcecode-1.30.20 → sourcecode-1.30.22}/src/sourcecode/detectors/go.py +0 -0
- {sourcecode-1.30.20 → sourcecode-1.30.22}/src/sourcecode/detectors/heuristic.py +0 -0
- {sourcecode-1.30.20 → sourcecode-1.30.22}/src/sourcecode/detectors/hybrid.py +0 -0
- {sourcecode-1.30.20 → sourcecode-1.30.22}/src/sourcecode/detectors/java.py +0 -0
- {sourcecode-1.30.20 → sourcecode-1.30.22}/src/sourcecode/detectors/jvm_ext.py +0 -0
- {sourcecode-1.30.20 → sourcecode-1.30.22}/src/sourcecode/detectors/nodejs.py +0 -0
- {sourcecode-1.30.20 → sourcecode-1.30.22}/src/sourcecode/detectors/parsers.py +0 -0
- {sourcecode-1.30.20 → sourcecode-1.30.22}/src/sourcecode/detectors/php.py +0 -0
- {sourcecode-1.30.20 → sourcecode-1.30.22}/src/sourcecode/detectors/project.py +0 -0
- {sourcecode-1.30.20 → sourcecode-1.30.22}/src/sourcecode/detectors/python.py +0 -0
- {sourcecode-1.30.20 → sourcecode-1.30.22}/src/sourcecode/detectors/ruby.py +0 -0
- {sourcecode-1.30.20 → sourcecode-1.30.22}/src/sourcecode/detectors/rust.py +0 -0
- {sourcecode-1.30.20 → sourcecode-1.30.22}/src/sourcecode/detectors/systems.py +0 -0
- {sourcecode-1.30.20 → sourcecode-1.30.22}/src/sourcecode/detectors/terraform.py +0 -0
- {sourcecode-1.30.20 → sourcecode-1.30.22}/src/sourcecode/detectors/tooling.py +0 -0
- {sourcecode-1.30.20 → sourcecode-1.30.22}/src/sourcecode/doc_analyzer.py +0 -0
- {sourcecode-1.30.20 → sourcecode-1.30.22}/src/sourcecode/entrypoint_classifier.py +0 -0
- {sourcecode-1.30.20 → sourcecode-1.30.22}/src/sourcecode/env_analyzer.py +0 -0
- {sourcecode-1.30.20 → sourcecode-1.30.22}/src/sourcecode/file_classifier.py +0 -0
- {sourcecode-1.30.20 → sourcecode-1.30.22}/src/sourcecode/flow_analyzer.py +0 -0
- {sourcecode-1.30.20 → sourcecode-1.30.22}/src/sourcecode/git_analyzer.py +0 -0
- {sourcecode-1.30.20 → sourcecode-1.30.22}/src/sourcecode/graph_analyzer.py +0 -0
- {sourcecode-1.30.20 → sourcecode-1.30.22}/src/sourcecode/metrics_analyzer.py +0 -0
- {sourcecode-1.30.20 → sourcecode-1.30.22}/src/sourcecode/pr_comment_renderer.py +0 -0
- {sourcecode-1.30.20 → sourcecode-1.30.22}/src/sourcecode/progress.py +0 -0
- {sourcecode-1.30.20 → sourcecode-1.30.22}/src/sourcecode/ranking_engine.py +0 -0
- {sourcecode-1.30.20 → sourcecode-1.30.22}/src/sourcecode/redactor.py +0 -0
- {sourcecode-1.30.20 → sourcecode-1.30.22}/src/sourcecode/relevance_scorer.py +0 -0
- {sourcecode-1.30.20 → sourcecode-1.30.22}/src/sourcecode/repo_classifier.py +0 -0
- {sourcecode-1.30.20 → sourcecode-1.30.22}/src/sourcecode/repository_ir.py +0 -0
- {sourcecode-1.30.20 → sourcecode-1.30.22}/src/sourcecode/runtime_classifier.py +0 -0
- {sourcecode-1.30.20 → sourcecode-1.30.22}/src/sourcecode/scanner.py +0 -0
- {sourcecode-1.30.20 → sourcecode-1.30.22}/src/sourcecode/schema.py +0 -0
- {sourcecode-1.30.20 → sourcecode-1.30.22}/src/sourcecode/semantic_analyzer.py +0 -0
- {sourcecode-1.30.20 → sourcecode-1.30.22}/src/sourcecode/serializer.py +0 -0
- {sourcecode-1.30.20 → sourcecode-1.30.22}/src/sourcecode/summarizer.py +0 -0
- {sourcecode-1.30.20 → sourcecode-1.30.22}/src/sourcecode/telemetry/__init__.py +0 -0
- {sourcecode-1.30.20 → sourcecode-1.30.22}/src/sourcecode/telemetry/config.py +0 -0
- {sourcecode-1.30.20 → sourcecode-1.30.22}/src/sourcecode/telemetry/consent.py +0 -0
- {sourcecode-1.30.20 → sourcecode-1.30.22}/src/sourcecode/telemetry/events.py +0 -0
- {sourcecode-1.30.20 → sourcecode-1.30.22}/src/sourcecode/telemetry/filters.py +0 -0
- {sourcecode-1.30.20 → sourcecode-1.30.22}/src/sourcecode/telemetry/transport.py +0 -0
- {sourcecode-1.30.20 → sourcecode-1.30.22}/src/sourcecode/tree_utils.py +0 -0
- {sourcecode-1.30.20 → sourcecode-1.30.22}/src/sourcecode/workspace.py +0 -0
- {sourcecode-1.30.20 → sourcecode-1.30.22}/tests/__init__.py +0 -0
- {sourcecode-1.30.20 → sourcecode-1.30.22}/tests/conftest.py +0 -0
- {sourcecode-1.30.20 → sourcecode-1.30.22}/tests/fixtures/coverage.xml +0 -0
- {sourcecode-1.30.20 → sourcecode-1.30.22}/tests/fixtures/fastapi_app/pyproject.toml +0 -0
- {sourcecode-1.30.20 → sourcecode-1.30.22}/tests/fixtures/fastapi_app/src/main.py +0 -0
- {sourcecode-1.30.20 → sourcecode-1.30.22}/tests/fixtures/go_service/cmd/api/main.go +0 -0
- {sourcecode-1.30.20 → sourcecode-1.30.22}/tests/fixtures/go_service/go.mod +0 -0
- {sourcecode-1.30.20 → sourcecode-1.30.22}/tests/fixtures/jacoco.xml +0 -0
- {sourcecode-1.30.20 → sourcecode-1.30.22}/tests/fixtures/latin1_sample.java +0 -0
- {sourcecode-1.30.20 → sourcecode-1.30.22}/tests/fixtures/latin1_sample_iso.java +0 -0
- {sourcecode-1.30.20 → sourcecode-1.30.22}/tests/fixtures/lcov.info +0 -0
- {sourcecode-1.30.20 → sourcecode-1.30.22}/tests/fixtures/nextjs_app/app/page.tsx +0 -0
- {sourcecode-1.30.20 → sourcecode-1.30.22}/tests/fixtures/nextjs_app/package.json +0 -0
- {sourcecode-1.30.20 → sourcecode-1.30.22}/tests/fixtures/nextjs_app/pnpm-lock.yaml +0 -0
- {sourcecode-1.30.20 → sourcecode-1.30.22}/tests/fixtures/pnpm_monorepo/apps/web/app/page.tsx +0 -0
- {sourcecode-1.30.20 → sourcecode-1.30.22}/tests/fixtures/pnpm_monorepo/apps/web/package.json +0 -0
- {sourcecode-1.30.20 → sourcecode-1.30.22}/tests/fixtures/pnpm_monorepo/packages/api/main.py +0 -0
- {sourcecode-1.30.20 → sourcecode-1.30.22}/tests/fixtures/pnpm_monorepo/packages/api/pyproject.toml +0 -0
- {sourcecode-1.30.20 → sourcecode-1.30.22}/tests/fixtures/pnpm_monorepo/pnpm-workspace.yaml +0 -0
- {sourcecode-1.30.20 → sourcecode-1.30.22}/tests/fixtures/spring_boot_minimal/pom.xml +0 -0
- {sourcecode-1.30.20 → sourcecode-1.30.22}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/ausente/application/service/FindAusenteService.java +0 -0
- {sourcecode-1.30.20 → sourcecode-1.30.22}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/ausente/domain/entities/Ausente.java +0 -0
- {sourcecode-1.30.20 → sourcecode-1.30.22}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/ausente/infrastructure/rest/AusenteRestController.java +0 -0
- {sourcecode-1.30.20 → sourcecode-1.30.22}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/autocoberturas/application/service/FindAutocoberturasService.java +0 -0
- {sourcecode-1.30.20 → sourcecode-1.30.22}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/autocoberturas/domain/entities/Autocoberturas.java +0 -0
- {sourcecode-1.30.20 → sourcecode-1.30.22}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/autocoberturas/infrastructure/rest/AutocoberturasRestController.java +0 -0
- {sourcecode-1.30.20 → sourcecode-1.30.22}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/calendarioTrabajador/application/service/FindCalendarioTrabajadorService.java +0 -0
- {sourcecode-1.30.20 → sourcecode-1.30.22}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/calendarioTrabajador/domain/entities/CalendarioTrabajador.java +0 -0
- {sourcecode-1.30.20 → sourcecode-1.30.22}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/calendarioTrabajador/infrastructure/rest/CalendarioTrabajadorRestController.java +0 -0
- {sourcecode-1.30.20 → sourcecode-1.30.22}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/departamento/application/service/FindDepartamentoService.java +0 -0
- {sourcecode-1.30.20 → sourcecode-1.30.22}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/departamento/domain/entities/Departamento.java +0 -0
- {sourcecode-1.30.20 → sourcecode-1.30.22}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/departamento/infrastructure/rest/DepartamentoRestController.java +0 -0
- {sourcecode-1.30.20 → sourcecode-1.30.22}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/empleado/application/service/FindEmpleadoService.java +0 -0
- {sourcecode-1.30.20 → sourcecode-1.30.22}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/empleado/domain/entities/Empleado.java +0 -0
- {sourcecode-1.30.20 → sourcecode-1.30.22}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/empleado/infrastructure/rest/EmpleadoRestController.java +0 -0
- {sourcecode-1.30.20 → sourcecode-1.30.22}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/demo/DemoApplication.java +0 -0
- {sourcecode-1.30.20 → sourcecode-1.30.22}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/demo/config/FilterConfig.java +0 -0
- {sourcecode-1.30.20 → sourcecode-1.30.22}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/demo/domain/Health.java +0 -0
- {sourcecode-1.30.20 → sourcecode-1.30.22}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/demo/mapper/HealthMapper.java +0 -0
- {sourcecode-1.30.20 → sourcecode-1.30.22}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/demo/repository/HealthRepository.java +0 -0
- {sourcecode-1.30.20 → sourcecode-1.30.22}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/demo/service/HealthService.java +0 -0
- {sourcecode-1.30.20 → sourcecode-1.30.22}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/demo/web/HealthRestController.java +0 -0
- {sourcecode-1.30.20 → sourcecode-1.30.22}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/demo/web/NominaRestController.java +0 -0
- {sourcecode-1.30.20 → sourcecode-1.30.22}/tests/fixtures/spring_boot_minimal/src/main/resources/application-dev.yml +0 -0
- {sourcecode-1.30.20 → sourcecode-1.30.22}/tests/fixtures/spring_boot_minimal/src/main/resources/application.yml +0 -0
- {sourcecode-1.30.20 → sourcecode-1.30.22}/tests/fixtures/spring_boot_minimal/src/main/resources/mapper/HealthMapper.xml +0 -0
- {sourcecode-1.30.20 → sourcecode-1.30.22}/tests/test_architecture_analyzer.py +0 -0
- {sourcecode-1.30.20 → sourcecode-1.30.22}/tests/test_architecture_summary.py +0 -0
- {sourcecode-1.30.20 → sourcecode-1.30.22}/tests/test_ast_extractor.py +0 -0
- {sourcecode-1.30.20 → sourcecode-1.30.22}/tests/test_block1_reliability.py +0 -0
- {sourcecode-1.30.20 → sourcecode-1.30.22}/tests/test_block2_coverage.py +0 -0
- {sourcecode-1.30.20 → sourcecode-1.30.22}/tests/test_block5_quality.py +0 -0
- {sourcecode-1.30.20 → sourcecode-1.30.22}/tests/test_bug_fixes_v16.py +0 -0
- {sourcecode-1.30.20 → sourcecode-1.30.22}/tests/test_classifier.py +0 -0
- {sourcecode-1.30.20 → sourcecode-1.30.22}/tests/test_cli.py +0 -0
- {sourcecode-1.30.20 → sourcecode-1.30.22}/tests/test_code_notes_analyzer.py +0 -0
- {sourcecode-1.30.20 → sourcecode-1.30.22}/tests/test_context_scorer.py +0 -0
- {sourcecode-1.30.20 → sourcecode-1.30.22}/tests/test_contract_pipeline.py +0 -0
- {sourcecode-1.30.20 → sourcecode-1.30.22}/tests/test_coverage_parser.py +0 -0
- {sourcecode-1.30.20 → sourcecode-1.30.22}/tests/test_cross_consistency.py +0 -0
- {sourcecode-1.30.20 → sourcecode-1.30.22}/tests/test_dependency_analyzer_node_python.py +0 -0
- {sourcecode-1.30.20 → sourcecode-1.30.22}/tests/test_dependency_analyzer_polyglot.py +0 -0
- {sourcecode-1.30.20 → sourcecode-1.30.22}/tests/test_dependency_schema.py +0 -0
- {sourcecode-1.30.20 → sourcecode-1.30.22}/tests/test_detector_dotnet.py +0 -0
- {sourcecode-1.30.20 → sourcecode-1.30.22}/tests/test_detector_go_rust_java.py +0 -0
- {sourcecode-1.30.20 → sourcecode-1.30.22}/tests/test_detector_nodejs.py +0 -0
- {sourcecode-1.30.20 → sourcecode-1.30.22}/tests/test_detector_php_ruby_dart.py +0 -0
- {sourcecode-1.30.20 → sourcecode-1.30.22}/tests/test_detector_python.py +0 -0
- {sourcecode-1.30.20 → sourcecode-1.30.22}/tests/test_detector_universal_managed.py +0 -0
- {sourcecode-1.30.20 → sourcecode-1.30.22}/tests/test_detector_universal_systems.py +0 -0
- {sourcecode-1.30.20 → sourcecode-1.30.22}/tests/test_detectors_base.py +0 -0
- {sourcecode-1.30.20 → sourcecode-1.30.22}/tests/test_doc_analyzer_jsdom.py +0 -0
- {sourcecode-1.30.20 → sourcecode-1.30.22}/tests/test_doc_analyzer_python.py +0 -0
- {sourcecode-1.30.20 → sourcecode-1.30.22}/tests/test_encoding_regression.py +0 -0
- {sourcecode-1.30.20 → sourcecode-1.30.22}/tests/test_graph_analyzer_polyglot.py +0 -0
- {sourcecode-1.30.20 → sourcecode-1.30.22}/tests/test_graph_analyzer_python_node.py +0 -0
- {sourcecode-1.30.20 → sourcecode-1.30.22}/tests/test_graph_schema.py +0 -0
- {sourcecode-1.30.20 → sourcecode-1.30.22}/tests/test_hybrid_inference.py +0 -0
- {sourcecode-1.30.20 → sourcecode-1.30.22}/tests/test_integration.py +0 -0
- {sourcecode-1.30.20 → sourcecode-1.30.22}/tests/test_integration_dependencies.py +0 -0
- {sourcecode-1.30.20 → sourcecode-1.30.22}/tests/test_integration_detection.py +0 -0
- {sourcecode-1.30.20 → sourcecode-1.30.22}/tests/test_integration_docs.py +0 -0
- {sourcecode-1.30.20 → sourcecode-1.30.22}/tests/test_integration_graph_modules.py +0 -0
- {sourcecode-1.30.20 → sourcecode-1.30.22}/tests/test_integration_lqn.py +0 -0
- {sourcecode-1.30.20 → sourcecode-1.30.22}/tests/test_integration_metrics.py +0 -0
- {sourcecode-1.30.20 → sourcecode-1.30.22}/tests/test_integration_multistack.py +0 -0
- {sourcecode-1.30.20 → sourcecode-1.30.22}/tests/test_integration_semantics.py +0 -0
- {sourcecode-1.30.20 → sourcecode-1.30.22}/tests/test_integration_universal.py +0 -0
- {sourcecode-1.30.20 → sourcecode-1.30.22}/tests/test_java_spring_integration.py +0 -0
- {sourcecode-1.30.20 → sourcecode-1.30.22}/tests/test_metrics_analyzer.py +0 -0
- {sourcecode-1.30.20 → sourcecode-1.30.22}/tests/test_packaging.py +0 -0
- {sourcecode-1.30.20 → sourcecode-1.30.22}/tests/test_phase1_improvements.py +0 -0
- {sourcecode-1.30.20 → sourcecode-1.30.22}/tests/test_pipeline_integrity.py +0 -0
- {sourcecode-1.30.20 → sourcecode-1.30.22}/tests/test_real_projects.py +0 -0
- {sourcecode-1.30.20 → sourcecode-1.30.22}/tests/test_redactor.py +0 -0
- {sourcecode-1.30.20 → sourcecode-1.30.22}/tests/test_repository_ir.py +0 -0
- {sourcecode-1.30.20 → sourcecode-1.30.22}/tests/test_scanner.py +0 -0
- {sourcecode-1.30.20 → sourcecode-1.30.22}/tests/test_schema.py +0 -0
- {sourcecode-1.30.20 → sourcecode-1.30.22}/tests/test_schema_normalization.py +0 -0
- {sourcecode-1.30.20 → sourcecode-1.30.22}/tests/test_semantic_analyzer_node.py +0 -0
- {sourcecode-1.30.20 → sourcecode-1.30.22}/tests/test_semantic_analyzer_python.py +0 -0
- {sourcecode-1.30.20 → sourcecode-1.30.22}/tests/test_semantic_import_resolution.py +0 -0
- {sourcecode-1.30.20 → sourcecode-1.30.22}/tests/test_semantic_schema.py +0 -0
- {sourcecode-1.30.20 → sourcecode-1.30.22}/tests/test_signal_hierarchy.py +0 -0
- {sourcecode-1.30.20 → sourcecode-1.30.22}/tests/test_summarizer.py +0 -0
- {sourcecode-1.30.20 → sourcecode-1.30.22}/tests/test_surface_honesty.py +0 -0
- {sourcecode-1.30.20 → sourcecode-1.30.22}/tests/test_task_differentiation.py +0 -0
- {sourcecode-1.30.20 → sourcecode-1.30.22}/tests/test_telemetry.py +0 -0
- {sourcecode-1.30.20 → sourcecode-1.30.22}/tests/test_v131_improvements.py +0 -0
- {sourcecode-1.30.20 → sourcecode-1.30.22}/tests/test_v1_10_regressions.py +0 -0
- {sourcecode-1.30.20 → sourcecode-1.30.22}/tests/test_workspace_analyzer.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: sourcecode
|
|
3
|
-
Version: 1.30.
|
|
3
|
+
Version: 1.30.22
|
|
4
4
|
Summary: Deterministic codebase context for AI coding agents
|
|
5
5
|
License: Apache License
|
|
6
6
|
Version 2.0, January 2004
|
|
@@ -221,7 +221,7 @@ Description-Content-Type: text/markdown
|
|
|
221
221
|
|
|
222
222
|
**Deterministic, behavior-aware codebase context for AI agents and PR review.**
|
|
223
223
|
|
|
224
|
-

|
|
225
225
|

|
|
226
226
|
|
|
227
227
|
---
|
|
@@ -257,7 +257,7 @@ pipx install sourcecode
|
|
|
257
257
|
|
|
258
258
|
```bash
|
|
259
259
|
sourcecode version
|
|
260
|
-
# sourcecode 1.30.
|
|
260
|
+
# sourcecode 1.30.22
|
|
261
261
|
```
|
|
262
262
|
|
|
263
263
|
---
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
**Deterministic, behavior-aware codebase context for AI agents and PR review.**
|
|
4
4
|
|
|
5
|
-

|
|
6
6
|

|
|
7
7
|
|
|
8
8
|
---
|
|
@@ -38,7 +38,7 @@ pipx install sourcecode
|
|
|
38
38
|
|
|
39
39
|
```bash
|
|
40
40
|
sourcecode version
|
|
41
|
-
# sourcecode 1.30.
|
|
41
|
+
# sourcecode 1.30.22
|
|
42
42
|
```
|
|
43
43
|
|
|
44
44
|
---
|
|
@@ -1596,6 +1596,86 @@ def main(
|
|
|
1596
1596
|
typer.echo("✓ copied to clipboard", err=True)
|
|
1597
1597
|
|
|
1598
1598
|
|
|
1599
|
+
# ── prepare-context output helpers ────────────────────────────────────────────
|
|
1600
|
+
|
|
1601
|
+
def _make_explanation(reason: str, why: str) -> str:
|
|
1602
|
+
"""Merge reason+why into one human string. Drop internal pipe-format jargon."""
|
|
1603
|
+
if why and not why.startswith("artifact_type:"):
|
|
1604
|
+
return why
|
|
1605
|
+
return reason
|
|
1606
|
+
|
|
1607
|
+
|
|
1608
|
+
def _serialize_relevant_file(f: Any) -> dict:
|
|
1609
|
+
from dataclasses import asdict as _asdict
|
|
1610
|
+
d = {k: v for k, v in _asdict(f).items() if v != "" and v is not None}
|
|
1611
|
+
reason = d.pop("reason", "") or ""
|
|
1612
|
+
why = d.pop("why", "") or ""
|
|
1613
|
+
d.pop("score", None) # score removed from public output (internal ranking only)
|
|
1614
|
+
explanation = _make_explanation(reason, why)
|
|
1615
|
+
if explanation:
|
|
1616
|
+
d["explanation"] = explanation
|
|
1617
|
+
return d
|
|
1618
|
+
|
|
1619
|
+
|
|
1620
|
+
def _transform_impact_scores(scores: dict) -> dict:
|
|
1621
|
+
"""Convert internal impact_score_per_file to human-readable review signals."""
|
|
1622
|
+
_THRESHOLDS = [(0.60, "high"), (0.40, "medium")]
|
|
1623
|
+
_CT_LABELS: dict[str, str] = {
|
|
1624
|
+
"security_change": "security-sensitive change",
|
|
1625
|
+
"behavioral_change": "behavioral change",
|
|
1626
|
+
"structural_change": "structural modification",
|
|
1627
|
+
"configuration_change": "configuration change",
|
|
1628
|
+
"dependency_change": "dependency update",
|
|
1629
|
+
"ui_change": "UI change",
|
|
1630
|
+
}
|
|
1631
|
+
result: dict = {}
|
|
1632
|
+
for path, entry in scores.items():
|
|
1633
|
+
raw = entry.get("_rank_score", 0.0)
|
|
1634
|
+
priority = next((p for thresh, p in _THRESHOLDS if raw >= thresh), "low")
|
|
1635
|
+
signals: list[str] = [
|
|
1636
|
+
_CT_LABELS[ct] for ct in entry.get("change_types", []) if ct in _CT_LABELS
|
|
1637
|
+
]
|
|
1638
|
+
ev = entry.get("evidence", {})
|
|
1639
|
+
callers = ev.get("reverse_edge_count", 0)
|
|
1640
|
+
if callers:
|
|
1641
|
+
signals.append(f"imported by {callers} other file{'s' if callers > 1 else ''}")
|
|
1642
|
+
out_entry: dict = {"review_priority": priority}
|
|
1643
|
+
if signals:
|
|
1644
|
+
out_entry["signals"] = signals
|
|
1645
|
+
result[path] = out_entry
|
|
1646
|
+
return result
|
|
1647
|
+
|
|
1648
|
+
|
|
1649
|
+
def _clean_system_impact(si: dict) -> dict:
|
|
1650
|
+
"""Remove empty lists/dicts from system_impact — only emit positive signals."""
|
|
1651
|
+
return {k: v for k, v in si.items() if v}
|
|
1652
|
+
|
|
1653
|
+
|
|
1654
|
+
def _build_human_summary(output: Any) -> dict:
|
|
1655
|
+
"""Human-readable summary block for delta/review-pr output."""
|
|
1656
|
+
concerns: list[str] = []
|
|
1657
|
+
si = getattr(output, "system_impact", {}) or {}
|
|
1658
|
+
for ri in si.get("runtime_impact", []):
|
|
1659
|
+
sig = ri.get("signal", "")
|
|
1660
|
+
if sig:
|
|
1661
|
+
concerns.append(sig)
|
|
1662
|
+
for bc in si.get("behavioral_changes", []):
|
|
1663
|
+
stmt = bc.get("statement", "")
|
|
1664
|
+
if stmt:
|
|
1665
|
+
concerns.append(stmt)
|
|
1666
|
+
cov = getattr(output, "test_coverage_risk", {}) or {}
|
|
1667
|
+
missing = cov.get("changed_files_without_tests", [])
|
|
1668
|
+
if missing:
|
|
1669
|
+
concerns.append(f"{len(missing)} changed file(s) without test coverage detected")
|
|
1670
|
+
summary: dict = {}
|
|
1671
|
+
if getattr(output, "impact_summary", None):
|
|
1672
|
+
summary["description"] = output.impact_summary
|
|
1673
|
+
if concerns:
|
|
1674
|
+
summary["review_concerns"] = concerns[:6]
|
|
1675
|
+
summary["confidence"] = (getattr(output, "confidence", None) or "medium").upper()
|
|
1676
|
+
return summary
|
|
1677
|
+
|
|
1678
|
+
|
|
1599
1679
|
@app.command("prepare-context")
|
|
1600
1680
|
def prepare_context_cmd(
|
|
1601
1681
|
task: Optional[str] = typer.Argument(
|
|
@@ -1801,9 +1881,14 @@ def prepare_context_cmd(
|
|
|
1801
1881
|
def _task_include(field: str) -> bool:
|
|
1802
1882
|
return _content_filter.get(field, True)
|
|
1803
1883
|
|
|
1884
|
+
_run_id = hashlib.sha256(
|
|
1885
|
+
f"{task}:{target}:{since or ''}:{format or ''}:{symptom or ''}".encode()
|
|
1886
|
+
).hexdigest()[:16]
|
|
1887
|
+
|
|
1804
1888
|
out: dict[str, Any] = {
|
|
1805
1889
|
"task": output.task,
|
|
1806
1890
|
"goal": output.goal,
|
|
1891
|
+
"run_id": _run_id,
|
|
1807
1892
|
}
|
|
1808
1893
|
if _task_include("project_summary"):
|
|
1809
1894
|
out["project_summary"] = output.project_summary
|
|
@@ -1813,7 +1898,7 @@ def prepare_context_cmd(
|
|
|
1813
1898
|
out["confidence"] = output.confidence
|
|
1814
1899
|
if task != "review-pr" and _task_include("relevant_files"):
|
|
1815
1900
|
out["relevant_files"] = [
|
|
1816
|
-
|
|
1901
|
+
_serialize_relevant_file(f)
|
|
1817
1902
|
for f in output.relevant_files
|
|
1818
1903
|
]
|
|
1819
1904
|
if _task_include("key_dependencies") and output.key_dependencies:
|
|
@@ -1854,6 +1939,30 @@ def prepare_context_cmd(
|
|
|
1854
1939
|
_sys.stdout.buffer.write(b"\n")
|
|
1855
1940
|
_sys.stdout.buffer.flush()
|
|
1856
1941
|
raise typer.Exit(code=1)
|
|
1942
|
+
if output.ci_decision == "no_changes":
|
|
1943
|
+
# Early exit: no diff — emit minimal JSON without any analysis fields.
|
|
1944
|
+
# Prevents no_changes from ever being serialized alongside relevant_files > 0.
|
|
1945
|
+
_nc_out: dict[str, Any] = {
|
|
1946
|
+
"task": output.task,
|
|
1947
|
+
"ci_decision": "no_changes",
|
|
1948
|
+
"summary": "No changes detected",
|
|
1949
|
+
}
|
|
1950
|
+
if output.since:
|
|
1951
|
+
_nc_out["since"] = output.since
|
|
1952
|
+
if output.analysis_scope:
|
|
1953
|
+
_nc_out["analysis_scope"] = output.analysis_scope
|
|
1954
|
+
_nc_json = json.dumps(_nc_out, indent=2, ensure_ascii=False)
|
|
1955
|
+
if output_path is not None:
|
|
1956
|
+
output_path.write_text(_nc_json, encoding="utf-8")
|
|
1957
|
+
else:
|
|
1958
|
+
import sys as _sys
|
|
1959
|
+
_sys.stdout.buffer.write(_nc_json.encode("utf-8"))
|
|
1960
|
+
_sys.stdout.buffer.write(b"\n")
|
|
1961
|
+
_sys.stdout.buffer.flush()
|
|
1962
|
+
if copy:
|
|
1963
|
+
_copy_to_clipboard(_nc_json)
|
|
1964
|
+
typer.echo("✓ copied to clipboard", err=True)
|
|
1965
|
+
raise typer.Exit()
|
|
1857
1966
|
if output.ci_decision:
|
|
1858
1967
|
out["ci_decision"] = output.ci_decision
|
|
1859
1968
|
if output.since:
|
|
@@ -1864,16 +1973,19 @@ def prepare_context_cmd(
|
|
|
1864
1973
|
out["affected_modules"] = output.affected_modules
|
|
1865
1974
|
if output.risk_areas:
|
|
1866
1975
|
out["risk_areas"] = output.risk_areas
|
|
1867
|
-
if output.why_these_files:
|
|
1868
|
-
out["reasoning"] = output.why_these_files
|
|
1869
1976
|
if output.change_type:
|
|
1870
1977
|
out["change_type"] = output.change_type
|
|
1871
1978
|
if output.system_impact:
|
|
1872
|
-
|
|
1979
|
+
_si = _clean_system_impact(output.system_impact)
|
|
1980
|
+
if _si:
|
|
1981
|
+
out["system_impact"] = _si
|
|
1873
1982
|
if output.dependency_graph_summary:
|
|
1874
|
-
|
|
1983
|
+
_dgraph = {k: v for k, v in output.dependency_graph_summary.items() if v is not None}
|
|
1984
|
+
if _dgraph:
|
|
1985
|
+
out["dependency_graph_summary"] = _dgraph
|
|
1875
1986
|
if output.impact_score_per_file:
|
|
1876
|
-
out["impact_score_per_file"] = output.impact_score_per_file
|
|
1987
|
+
out["impact_score_per_file"] = _transform_impact_scores(output.impact_score_per_file)
|
|
1988
|
+
out["summary"] = _build_human_summary(output)
|
|
1877
1989
|
# review-pr specific fields
|
|
1878
1990
|
if task == "review-pr":
|
|
1879
1991
|
if output.error_code:
|
|
@@ -1928,8 +2040,7 @@ def prepare_context_cmd(
|
|
|
1928
2040
|
out["behavioral_impact"] = output.behavioral_impact
|
|
1929
2041
|
if output.impact_summary:
|
|
1930
2042
|
out["impact_summary"] = output.impact_summary
|
|
1931
|
-
|
|
1932
|
-
out["reasoning"] = output.why_these_files
|
|
2043
|
+
out["summary"] = _build_human_summary(output)
|
|
1933
2044
|
# git-first scope metadata
|
|
1934
2045
|
out["scope"] = {
|
|
1935
2046
|
"source": output.scope_source or "git_diff",
|
|
@@ -377,6 +377,25 @@ class TaskOutput:
|
|
|
377
377
|
analysis_scope: dict = field(default_factory=dict)
|
|
378
378
|
|
|
379
379
|
|
|
380
|
+
@dataclass
|
|
381
|
+
class CanonicalAnalysisIR:
|
|
382
|
+
"""Shared intermediate representation produced by _build_delta_impact.
|
|
383
|
+
|
|
384
|
+
Both delta and review-pr derive their task-specific output from this IR.
|
|
385
|
+
Never recalculate logic per command — render views from this single object.
|
|
386
|
+
"""
|
|
387
|
+
relevant_files: list[RelevantFile]
|
|
388
|
+
impact_summary: str
|
|
389
|
+
affected_modules: list[str]
|
|
390
|
+
risk_areas: list[dict]
|
|
391
|
+
why_these_files: dict[str, str]
|
|
392
|
+
analysis_gaps: list[str]
|
|
393
|
+
system_impact: dict
|
|
394
|
+
change_type: list[str]
|
|
395
|
+
dependency_graph_summary: dict
|
|
396
|
+
impact_score_per_file: dict
|
|
397
|
+
|
|
398
|
+
|
|
380
399
|
# ─────────────────────────────────────────────────────────────────────────────
|
|
381
400
|
# Builder
|
|
382
401
|
# ─────────────────────────────────────────────────────────────────────────────
|
|
@@ -556,7 +575,7 @@ _ARTIFACT_CHANGE_EFFECT: dict[str, str] = {
|
|
|
556
575
|
"test": "test file (no production code modified)",
|
|
557
576
|
"documentation": "documentation file (no runtime impact)",
|
|
558
577
|
"ide_noise": "IDE/tooling artifact (no application impact)",
|
|
559
|
-
"source": "application source (
|
|
578
|
+
"source": "application source file (role could not be confirmed from code signals)",
|
|
560
579
|
}
|
|
561
580
|
|
|
562
581
|
# Maps frontend symptom keywords → backend terms likely to contain the root cause.
|
|
@@ -934,7 +953,8 @@ class TaskContextBuilder:
|
|
|
934
953
|
test_set = {p for p in all_paths if self._is_test(p)}
|
|
935
954
|
source_set = {p for p in all_paths if not self._is_test(p) and self._is_source(p)}
|
|
936
955
|
|
|
937
|
-
# Delta
|
|
956
|
+
# Delta and review-pr share CanonicalAnalysisIR — computed once, rendered per task.
|
|
957
|
+
_ir: Optional[CanonicalAnalysisIR] = None
|
|
938
958
|
_delta_impact_summary: Optional[str] = None
|
|
939
959
|
_delta_affected_modules: list[str] = []
|
|
940
960
|
_delta_risk_areas: list[dict] = []
|
|
@@ -947,23 +967,22 @@ class TaskContextBuilder:
|
|
|
947
967
|
|
|
948
968
|
if task_name in ("delta", "review-pr"):
|
|
949
969
|
_delta_changed_list: list[str] = sorted(_delta_files) if _delta_files else []
|
|
950
|
-
(
|
|
951
|
-
relevant_files,
|
|
952
|
-
_delta_impact_summary,
|
|
953
|
-
_delta_affected_modules,
|
|
954
|
-
_delta_risk_areas,
|
|
955
|
-
_delta_why,
|
|
956
|
-
_delta_analysis_gaps,
|
|
957
|
-
_delta_system_impact,
|
|
958
|
-
_delta_change_type,
|
|
959
|
-
_delta_dep_graph_summary,
|
|
960
|
-
_delta_impact_score_per_file,
|
|
961
|
-
) = self._build_delta_impact(
|
|
970
|
+
_ir = self._build_delta_impact(
|
|
962
971
|
changed_files=_delta_changed_list,
|
|
963
972
|
all_paths=all_paths,
|
|
964
973
|
entry_points=entry_points,
|
|
965
974
|
since=since,
|
|
966
975
|
)
|
|
976
|
+
relevant_files = _ir.relevant_files
|
|
977
|
+
_delta_impact_summary = _ir.impact_summary
|
|
978
|
+
_delta_affected_modules = _ir.affected_modules
|
|
979
|
+
_delta_risk_areas = _ir.risk_areas
|
|
980
|
+
_delta_why = _ir.why_these_files
|
|
981
|
+
_delta_analysis_gaps = _ir.analysis_gaps
|
|
982
|
+
_delta_system_impact = _ir.system_impact
|
|
983
|
+
_delta_change_type = _ir.change_type
|
|
984
|
+
_delta_dep_graph_summary = _ir.dependency_graph_summary
|
|
985
|
+
_delta_impact_score_per_file = _ir.impact_score_per_file
|
|
967
986
|
else:
|
|
968
987
|
relevant_files = self._rank_files(
|
|
969
988
|
task_name, spec, all_paths, entry_set, test_set,
|
|
@@ -1156,22 +1175,24 @@ class TaskContextBuilder:
|
|
|
1156
1175
|
else "unknown"
|
|
1157
1176
|
)
|
|
1158
1177
|
_impact_entry = _delta_impact_score_per_file.get(_f) or {}
|
|
1159
|
-
|
|
1178
|
+
_ev_complete = {k: v for k, v in _impact_entry.get("evidence", {}).items() if v}
|
|
1179
|
+
_entry: dict = {
|
|
1160
1180
|
"path": _f,
|
|
1161
1181
|
"diff_source": _diff_source,
|
|
1162
1182
|
"role": _role_obj,
|
|
1163
1183
|
"artifact_type": _f_atype,
|
|
1164
1184
|
"evidence": _evidence,
|
|
1165
1185
|
"change_effect": {
|
|
1166
|
-
"statement": _ARTIFACT_CHANGE_EFFECT.get(_f_atype, "application source (
|
|
1186
|
+
"statement": _ARTIFACT_CHANGE_EFFECT.get(_f_atype, "application source file (role could not be confirmed)"),
|
|
1167
1187
|
"classification_method": _f_cls.get("confidence", "low"),
|
|
1168
1188
|
"epistemic_level": (
|
|
1169
1189
|
"STRUCTURAL SIGNAL" if _f_cls.get("confidence", "low") == "high"
|
|
1170
1190
|
else "INFERRED (LOW CONFIDENCE)"
|
|
1171
1191
|
),
|
|
1172
1192
|
},
|
|
1173
|
-
"evidence_completeness": _impact_entry.get("evidence", {}),
|
|
1174
1193
|
}
|
|
1194
|
+
if _ev_complete:
|
|
1195
|
+
_entry["evidence_completeness"] = _ev_complete
|
|
1175
1196
|
_pr_runtime_changes.append(_entry)
|
|
1176
1197
|
# Split committed vs uncommitted — never merged
|
|
1177
1198
|
if _f in _committed_set:
|
|
@@ -2295,13 +2316,10 @@ class TaskContextBuilder:
|
|
|
2295
2316
|
all_paths: list[str],
|
|
2296
2317
|
entry_points: list,
|
|
2297
2318
|
since: Optional[str],
|
|
2298
|
-
) ->
|
|
2319
|
+
) -> "CanonicalAnalysisIR":
|
|
2299
2320
|
"""Build incremental impact analysis for changed files.
|
|
2300
2321
|
|
|
2301
|
-
Returns
|
|
2302
|
-
(relevant_files, impact_summary, affected_modules, risk_areas,
|
|
2303
|
-
why_these_files, analysis_gaps)
|
|
2304
|
-
|
|
2322
|
+
Returns CanonicalAnalysisIR — the shared IR consumed by delta and review-pr views.
|
|
2305
2323
|
Changed files are always included in relevant_files (never dropped by score).
|
|
2306
2324
|
Related files are expanded type-aware: controller→service→repository→mapper chain.
|
|
2307
2325
|
Scoring is hierarchical by artifact_type, not by heuristic impact_level.
|
|
@@ -2469,6 +2487,18 @@ class TaskContextBuilder:
|
|
|
2469
2487
|
return "data_access"
|
|
2470
2488
|
if atype == "service":
|
|
2471
2489
|
return "service" # annotation-confirmed — not "core_service" (overclaim)
|
|
2490
|
+
# Name-pattern heuristics — only when atype alone gave no verdict.
|
|
2491
|
+
# These are INFERRED (LOW CONFIDENCE) — stem match, not annotation evidence.
|
|
2492
|
+
if any(kw in stem_lower for kw in ("validator", "validation")):
|
|
2493
|
+
return "validation_component"
|
|
2494
|
+
if any(kw in stem_lower for kw in ("controller", "resource", "endpoint", "rest")):
|
|
2495
|
+
return "external_interface"
|
|
2496
|
+
if any(kw in stem_lower for kw in ("service", "svc", "usecase", "facade")):
|
|
2497
|
+
return "service"
|
|
2498
|
+
if any(kw in stem_lower for kw in ("repository", "repo", "dao", "store")):
|
|
2499
|
+
return "data_access"
|
|
2500
|
+
if any(kw in stem_lower for kw in ("config", "configuration", "settings", "properties")):
|
|
2501
|
+
return "configuration"
|
|
2472
2502
|
return "unclassified" # no role claim without evidence
|
|
2473
2503
|
|
|
2474
2504
|
def _structured_why(path: str, atype: str, module: str, role: str, risk_areas: list[str], cls_confidence: str = "low") -> str:
|
|
@@ -2489,17 +2519,17 @@ class TaskContextBuilder:
|
|
|
2489
2519
|
return " | ".join(parts)
|
|
2490
2520
|
|
|
2491
2521
|
if not changed_files:
|
|
2492
|
-
return (
|
|
2493
|
-
[],
|
|
2494
|
-
"No changes detected — verify the git ref passed to --since",
|
|
2495
|
-
[],
|
|
2496
|
-
[],
|
|
2497
|
-
{},
|
|
2498
|
-
["No changed files found. Check that --since ref exists and the diff is non-empty."],
|
|
2499
|
-
{},
|
|
2500
|
-
[],
|
|
2501
|
-
{"edges": [], "propagation_depth": 0},
|
|
2502
|
-
{},
|
|
2522
|
+
return CanonicalAnalysisIR(
|
|
2523
|
+
relevant_files=[],
|
|
2524
|
+
impact_summary="No changes detected — verify the git ref passed to --since",
|
|
2525
|
+
affected_modules=[],
|
|
2526
|
+
risk_areas=[],
|
|
2527
|
+
why_these_files={},
|
|
2528
|
+
analysis_gaps=["No changed files found. Check that --since ref exists and the diff is non-empty."],
|
|
2529
|
+
system_impact={},
|
|
2530
|
+
change_type=[],
|
|
2531
|
+
dependency_graph_summary={"edges": [], "propagation_depth": 0},
|
|
2532
|
+
impact_score_per_file={},
|
|
2503
2533
|
)
|
|
2504
2534
|
|
|
2505
2535
|
ep_paths = {ep.path for ep in entry_points}
|
|
@@ -2992,12 +3022,12 @@ class TaskContextBuilder:
|
|
|
2992
3022
|
|
|
2993
3023
|
# ── Step 6: analysis gaps ──────────────────────────────────────────────
|
|
2994
3024
|
_bfs_note = (
|
|
2995
|
-
f"
|
|
3025
|
+
f"multi-hop import tracing performed (depth {_max_hop})"
|
|
2996
3026
|
if _max_hop >= 1
|
|
2997
|
-
else "no
|
|
3027
|
+
else "no downstream dependencies could be verified"
|
|
2998
3028
|
)
|
|
2999
3029
|
analysis_gaps: list[str] = [
|
|
3000
|
-
f"Related file expansion
|
|
3030
|
+
f"Related file expansion via import analysis and directory proximity ({_bfs_note})",
|
|
3001
3031
|
]
|
|
3002
3032
|
if _expansion_truncated:
|
|
3003
3033
|
analysis_gaps.insert(0,
|
|
@@ -3015,10 +3045,8 @@ class TaskContextBuilder:
|
|
|
3015
3045
|
low_confidence = [f for f, cls in classifications.items() if cls.get("confidence") == "low" and not cls["is_noise"]]
|
|
3016
3046
|
if low_confidence:
|
|
3017
3047
|
analysis_gaps.append(
|
|
3018
|
-
f"{len(low_confidence)} file(s)
|
|
3019
|
-
" (
|
|
3020
|
-
" — consider adding stem patterns to _classify_changed_file: "
|
|
3021
|
-
+ ", ".join(Path(f).name for f in low_confidence[:3])
|
|
3048
|
+
f"{len(low_confidence)} file(s) role inferred from filename only"
|
|
3049
|
+
f" (no code signal found): {', '.join(Path(f).name for f in low_confidence[:3])}"
|
|
3022
3050
|
)
|
|
3023
3051
|
if not affected_modules_set and any(not cls["is_noise"] for cls in classifications.values()):
|
|
3024
3052
|
analysis_gaps.append(
|
|
@@ -3026,17 +3054,17 @@ class TaskContextBuilder:
|
|
|
3026
3054
|
" — related file expansion uses directory proximity only"
|
|
3027
3055
|
)
|
|
3028
3056
|
|
|
3029
|
-
return (
|
|
3030
|
-
relevant,
|
|
3031
|
-
impact_summary,
|
|
3032
|
-
sorted(affected_modules_set),
|
|
3033
|
-
risk_areas_out,
|
|
3034
|
-
why,
|
|
3035
|
-
analysis_gaps,
|
|
3036
|
-
system_impact,
|
|
3037
|
-
aggregate_change_type,
|
|
3038
|
-
dependency_graph_summary,
|
|
3039
|
-
impact_score_per_file,
|
|
3057
|
+
return CanonicalAnalysisIR(
|
|
3058
|
+
relevant_files=relevant,
|
|
3059
|
+
impact_summary=impact_summary,
|
|
3060
|
+
affected_modules=sorted(affected_modules_set),
|
|
3061
|
+
risk_areas=risk_areas_out,
|
|
3062
|
+
why_these_files=why,
|
|
3063
|
+
analysis_gaps=analysis_gaps,
|
|
3064
|
+
system_impact=system_impact,
|
|
3065
|
+
change_type=aggregate_change_type,
|
|
3066
|
+
dependency_graph_summary=dependency_graph_summary,
|
|
3067
|
+
impact_score_per_file=impact_score_per_file,
|
|
3040
3068
|
)
|
|
3041
3069
|
|
|
3042
3070
|
def _resolve_git_baseline(self, since: Optional[str]) -> dict[str, Any]:
|