sourcecode 1.30.11__tar.gz → 1.30.12__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.12/.continue-here.md +166 -0
- {sourcecode-1.30.11 → sourcecode-1.30.12}/PKG-INFO +3 -3
- {sourcecode-1.30.11 → sourcecode-1.30.12}/README.md +2 -2
- {sourcecode-1.30.11 → sourcecode-1.30.12}/pyproject.toml +1 -1
- {sourcecode-1.30.11 → sourcecode-1.30.12}/src/sourcecode/__init__.py +1 -1
- {sourcecode-1.30.11 → sourcecode-1.30.12}/src/sourcecode/cli.py +83 -0
- {sourcecode-1.30.11 → sourcecode-1.30.12}/src/sourcecode/prepare_context.py +115 -65
- sourcecode-1.30.12/src/sourcecode/repository_ir.py +803 -0
- sourcecode-1.30.12/tests/test_repository_ir.py +451 -0
- sourcecode-1.30.11/.continue-here.md +0 -173
- {sourcecode-1.30.11 → sourcecode-1.30.12}/.agents/skills/source-command-gsd-join-discord/SKILL.md +0 -0
- {sourcecode-1.30.11 → sourcecode-1.30.12}/.agents/skills/source-command-gsd-review-backlog/SKILL.md +0 -0
- {sourcecode-1.30.11 → sourcecode-1.30.12}/.agents/skills/source-command-gsd-workstreams/SKILL.md +0 -0
- {sourcecode-1.30.11 → sourcecode-1.30.12}/.github/workflows/build-windows.yml +0 -0
- {sourcecode-1.30.11 → sourcecode-1.30.12}/.gitignore +0 -0
- {sourcecode-1.30.11 → sourcecode-1.30.12}/.ruff.toml +0 -0
- {sourcecode-1.30.11 → sourcecode-1.30.12}/CONTRIBUTING.md +0 -0
- {sourcecode-1.30.11 → sourcecode-1.30.12}/LICENSE +0 -0
- {sourcecode-1.30.11 → sourcecode-1.30.12}/SECURITY.md +0 -0
- {sourcecode-1.30.11 → sourcecode-1.30.12}/docs/privacy.md +0 -0
- {sourcecode-1.30.11 → sourcecode-1.30.12}/docs/schema.md +0 -0
- {sourcecode-1.30.11 → sourcecode-1.30.12}/raw +0 -0
- {sourcecode-1.30.11 → sourcecode-1.30.12}/run_cli.py +0 -0
- {sourcecode-1.30.11 → sourcecode-1.30.12}/src/sourcecode/adaptive_scanner.py +0 -0
- {sourcecode-1.30.11 → sourcecode-1.30.12}/src/sourcecode/architecture_analyzer.py +0 -0
- {sourcecode-1.30.11 → sourcecode-1.30.12}/src/sourcecode/architecture_summary.py +0 -0
- {sourcecode-1.30.11 → sourcecode-1.30.12}/src/sourcecode/ast_extractor.py +0 -0
- {sourcecode-1.30.11 → sourcecode-1.30.12}/src/sourcecode/classifier.py +0 -0
- {sourcecode-1.30.11 → sourcecode-1.30.12}/src/sourcecode/code_notes_analyzer.py +0 -0
- {sourcecode-1.30.11 → sourcecode-1.30.12}/src/sourcecode/confidence_analyzer.py +0 -0
- {sourcecode-1.30.11 → sourcecode-1.30.12}/src/sourcecode/context_scorer.py +0 -0
- {sourcecode-1.30.11 → sourcecode-1.30.12}/src/sourcecode/context_summarizer.py +0 -0
- {sourcecode-1.30.11 → sourcecode-1.30.12}/src/sourcecode/contract_model.py +0 -0
- {sourcecode-1.30.11 → sourcecode-1.30.12}/src/sourcecode/contract_pipeline.py +0 -0
- {sourcecode-1.30.11 → sourcecode-1.30.12}/src/sourcecode/coverage_parser.py +0 -0
- {sourcecode-1.30.11 → sourcecode-1.30.12}/src/sourcecode/dependency_analyzer.py +0 -0
- {sourcecode-1.30.11 → sourcecode-1.30.12}/src/sourcecode/detectors/__init__.py +0 -0
- {sourcecode-1.30.11 → sourcecode-1.30.12}/src/sourcecode/detectors/base.py +0 -0
- {sourcecode-1.30.11 → sourcecode-1.30.12}/src/sourcecode/detectors/csproj_parser.py +0 -0
- {sourcecode-1.30.11 → sourcecode-1.30.12}/src/sourcecode/detectors/dart.py +0 -0
- {sourcecode-1.30.11 → sourcecode-1.30.12}/src/sourcecode/detectors/dotnet.py +0 -0
- {sourcecode-1.30.11 → sourcecode-1.30.12}/src/sourcecode/detectors/elixir.py +0 -0
- {sourcecode-1.30.11 → sourcecode-1.30.12}/src/sourcecode/detectors/go.py +0 -0
- {sourcecode-1.30.11 → sourcecode-1.30.12}/src/sourcecode/detectors/heuristic.py +0 -0
- {sourcecode-1.30.11 → sourcecode-1.30.12}/src/sourcecode/detectors/hybrid.py +0 -0
- {sourcecode-1.30.11 → sourcecode-1.30.12}/src/sourcecode/detectors/java.py +0 -0
- {sourcecode-1.30.11 → sourcecode-1.30.12}/src/sourcecode/detectors/jvm_ext.py +0 -0
- {sourcecode-1.30.11 → sourcecode-1.30.12}/src/sourcecode/detectors/nodejs.py +0 -0
- {sourcecode-1.30.11 → sourcecode-1.30.12}/src/sourcecode/detectors/parsers.py +0 -0
- {sourcecode-1.30.11 → sourcecode-1.30.12}/src/sourcecode/detectors/php.py +0 -0
- {sourcecode-1.30.11 → sourcecode-1.30.12}/src/sourcecode/detectors/project.py +0 -0
- {sourcecode-1.30.11 → sourcecode-1.30.12}/src/sourcecode/detectors/python.py +0 -0
- {sourcecode-1.30.11 → sourcecode-1.30.12}/src/sourcecode/detectors/ruby.py +0 -0
- {sourcecode-1.30.11 → sourcecode-1.30.12}/src/sourcecode/detectors/rust.py +0 -0
- {sourcecode-1.30.11 → sourcecode-1.30.12}/src/sourcecode/detectors/systems.py +0 -0
- {sourcecode-1.30.11 → sourcecode-1.30.12}/src/sourcecode/detectors/terraform.py +0 -0
- {sourcecode-1.30.11 → sourcecode-1.30.12}/src/sourcecode/detectors/tooling.py +0 -0
- {sourcecode-1.30.11 → sourcecode-1.30.12}/src/sourcecode/doc_analyzer.py +0 -0
- {sourcecode-1.30.11 → sourcecode-1.30.12}/src/sourcecode/entrypoint_classifier.py +0 -0
- {sourcecode-1.30.11 → sourcecode-1.30.12}/src/sourcecode/env_analyzer.py +0 -0
- {sourcecode-1.30.11 → sourcecode-1.30.12}/src/sourcecode/file_classifier.py +0 -0
- {sourcecode-1.30.11 → sourcecode-1.30.12}/src/sourcecode/flow_analyzer.py +0 -0
- {sourcecode-1.30.11 → sourcecode-1.30.12}/src/sourcecode/git_analyzer.py +0 -0
- {sourcecode-1.30.11 → sourcecode-1.30.12}/src/sourcecode/graph_analyzer.py +0 -0
- {sourcecode-1.30.11 → sourcecode-1.30.12}/src/sourcecode/metrics_analyzer.py +0 -0
- {sourcecode-1.30.11 → sourcecode-1.30.12}/src/sourcecode/progress.py +0 -0
- {sourcecode-1.30.11 → sourcecode-1.30.12}/src/sourcecode/ranking_engine.py +0 -0
- {sourcecode-1.30.11 → sourcecode-1.30.12}/src/sourcecode/redactor.py +0 -0
- {sourcecode-1.30.11 → sourcecode-1.30.12}/src/sourcecode/relevance_scorer.py +0 -0
- {sourcecode-1.30.11 → sourcecode-1.30.12}/src/sourcecode/repo_classifier.py +0 -0
- {sourcecode-1.30.11 → sourcecode-1.30.12}/src/sourcecode/runtime_classifier.py +0 -0
- {sourcecode-1.30.11 → sourcecode-1.30.12}/src/sourcecode/scanner.py +0 -0
- {sourcecode-1.30.11 → sourcecode-1.30.12}/src/sourcecode/schema.py +0 -0
- {sourcecode-1.30.11 → sourcecode-1.30.12}/src/sourcecode/semantic_analyzer.py +0 -0
- {sourcecode-1.30.11 → sourcecode-1.30.12}/src/sourcecode/serializer.py +0 -0
- {sourcecode-1.30.11 → sourcecode-1.30.12}/src/sourcecode/summarizer.py +0 -0
- {sourcecode-1.30.11 → sourcecode-1.30.12}/src/sourcecode/telemetry/__init__.py +0 -0
- {sourcecode-1.30.11 → sourcecode-1.30.12}/src/sourcecode/telemetry/config.py +0 -0
- {sourcecode-1.30.11 → sourcecode-1.30.12}/src/sourcecode/telemetry/consent.py +0 -0
- {sourcecode-1.30.11 → sourcecode-1.30.12}/src/sourcecode/telemetry/events.py +0 -0
- {sourcecode-1.30.11 → sourcecode-1.30.12}/src/sourcecode/telemetry/filters.py +0 -0
- {sourcecode-1.30.11 → sourcecode-1.30.12}/src/sourcecode/telemetry/transport.py +0 -0
- {sourcecode-1.30.11 → sourcecode-1.30.12}/src/sourcecode/tree_utils.py +0 -0
- {sourcecode-1.30.11 → sourcecode-1.30.12}/src/sourcecode/workspace.py +0 -0
- {sourcecode-1.30.11 → sourcecode-1.30.12}/tests/__init__.py +0 -0
- {sourcecode-1.30.11 → sourcecode-1.30.12}/tests/conftest.py +0 -0
- {sourcecode-1.30.11 → sourcecode-1.30.12}/tests/fixtures/coverage.xml +0 -0
- {sourcecode-1.30.11 → sourcecode-1.30.12}/tests/fixtures/fastapi_app/pyproject.toml +0 -0
- {sourcecode-1.30.11 → sourcecode-1.30.12}/tests/fixtures/fastapi_app/src/main.py +0 -0
- {sourcecode-1.30.11 → sourcecode-1.30.12}/tests/fixtures/go_service/cmd/api/main.go +0 -0
- {sourcecode-1.30.11 → sourcecode-1.30.12}/tests/fixtures/go_service/go.mod +0 -0
- {sourcecode-1.30.11 → sourcecode-1.30.12}/tests/fixtures/jacoco.xml +0 -0
- {sourcecode-1.30.11 → sourcecode-1.30.12}/tests/fixtures/latin1_sample.java +0 -0
- {sourcecode-1.30.11 → sourcecode-1.30.12}/tests/fixtures/latin1_sample_iso.java +0 -0
- {sourcecode-1.30.11 → sourcecode-1.30.12}/tests/fixtures/lcov.info +0 -0
- {sourcecode-1.30.11 → sourcecode-1.30.12}/tests/fixtures/nextjs_app/app/page.tsx +0 -0
- {sourcecode-1.30.11 → sourcecode-1.30.12}/tests/fixtures/nextjs_app/package.json +0 -0
- {sourcecode-1.30.11 → sourcecode-1.30.12}/tests/fixtures/nextjs_app/pnpm-lock.yaml +0 -0
- {sourcecode-1.30.11 → sourcecode-1.30.12}/tests/fixtures/pnpm_monorepo/apps/web/app/page.tsx +0 -0
- {sourcecode-1.30.11 → sourcecode-1.30.12}/tests/fixtures/pnpm_monorepo/apps/web/package.json +0 -0
- {sourcecode-1.30.11 → sourcecode-1.30.12}/tests/fixtures/pnpm_monorepo/packages/api/main.py +0 -0
- {sourcecode-1.30.11 → sourcecode-1.30.12}/tests/fixtures/pnpm_monorepo/packages/api/pyproject.toml +0 -0
- {sourcecode-1.30.11 → sourcecode-1.30.12}/tests/fixtures/pnpm_monorepo/pnpm-workspace.yaml +0 -0
- {sourcecode-1.30.11 → sourcecode-1.30.12}/tests/fixtures/spring_boot_minimal/pom.xml +0 -0
- {sourcecode-1.30.11 → sourcecode-1.30.12}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/ausente/application/service/FindAusenteService.java +0 -0
- {sourcecode-1.30.11 → sourcecode-1.30.12}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/ausente/domain/entities/Ausente.java +0 -0
- {sourcecode-1.30.11 → sourcecode-1.30.12}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/ausente/infrastructure/rest/AusenteRestController.java +0 -0
- {sourcecode-1.30.11 → sourcecode-1.30.12}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/autocoberturas/application/service/FindAutocoberturasService.java +0 -0
- {sourcecode-1.30.11 → sourcecode-1.30.12}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/autocoberturas/domain/entities/Autocoberturas.java +0 -0
- {sourcecode-1.30.11 → sourcecode-1.30.12}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/autocoberturas/infrastructure/rest/AutocoberturasRestController.java +0 -0
- {sourcecode-1.30.11 → sourcecode-1.30.12}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/calendarioTrabajador/application/service/FindCalendarioTrabajadorService.java +0 -0
- {sourcecode-1.30.11 → sourcecode-1.30.12}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/calendarioTrabajador/domain/entities/CalendarioTrabajador.java +0 -0
- {sourcecode-1.30.11 → sourcecode-1.30.12}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/calendarioTrabajador/infrastructure/rest/CalendarioTrabajadorRestController.java +0 -0
- {sourcecode-1.30.11 → sourcecode-1.30.12}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/departamento/application/service/FindDepartamentoService.java +0 -0
- {sourcecode-1.30.11 → sourcecode-1.30.12}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/departamento/domain/entities/Departamento.java +0 -0
- {sourcecode-1.30.11 → sourcecode-1.30.12}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/departamento/infrastructure/rest/DepartamentoRestController.java +0 -0
- {sourcecode-1.30.11 → sourcecode-1.30.12}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/empleado/application/service/FindEmpleadoService.java +0 -0
- {sourcecode-1.30.11 → sourcecode-1.30.12}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/empleado/domain/entities/Empleado.java +0 -0
- {sourcecode-1.30.11 → sourcecode-1.30.12}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/empleado/infrastructure/rest/EmpleadoRestController.java +0 -0
- {sourcecode-1.30.11 → sourcecode-1.30.12}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/demo/DemoApplication.java +0 -0
- {sourcecode-1.30.11 → sourcecode-1.30.12}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/demo/config/FilterConfig.java +0 -0
- {sourcecode-1.30.11 → sourcecode-1.30.12}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/demo/domain/Health.java +0 -0
- {sourcecode-1.30.11 → sourcecode-1.30.12}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/demo/mapper/HealthMapper.java +0 -0
- {sourcecode-1.30.11 → sourcecode-1.30.12}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/demo/repository/HealthRepository.java +0 -0
- {sourcecode-1.30.11 → sourcecode-1.30.12}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/demo/service/HealthService.java +0 -0
- {sourcecode-1.30.11 → sourcecode-1.30.12}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/demo/web/HealthRestController.java +0 -0
- {sourcecode-1.30.11 → sourcecode-1.30.12}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/demo/web/NominaRestController.java +0 -0
- {sourcecode-1.30.11 → sourcecode-1.30.12}/tests/fixtures/spring_boot_minimal/src/main/resources/application-dev.yml +0 -0
- {sourcecode-1.30.11 → sourcecode-1.30.12}/tests/fixtures/spring_boot_minimal/src/main/resources/application.yml +0 -0
- {sourcecode-1.30.11 → sourcecode-1.30.12}/tests/fixtures/spring_boot_minimal/src/main/resources/mapper/HealthMapper.xml +0 -0
- {sourcecode-1.30.11 → sourcecode-1.30.12}/tests/test_architecture_analyzer.py +0 -0
- {sourcecode-1.30.11 → sourcecode-1.30.12}/tests/test_architecture_summary.py +0 -0
- {sourcecode-1.30.11 → sourcecode-1.30.12}/tests/test_ast_extractor.py +0 -0
- {sourcecode-1.30.11 → sourcecode-1.30.12}/tests/test_block1_reliability.py +0 -0
- {sourcecode-1.30.11 → sourcecode-1.30.12}/tests/test_block2_coverage.py +0 -0
- {sourcecode-1.30.11 → sourcecode-1.30.12}/tests/test_block5_quality.py +0 -0
- {sourcecode-1.30.11 → sourcecode-1.30.12}/tests/test_bug_fixes_v16.py +0 -0
- {sourcecode-1.30.11 → sourcecode-1.30.12}/tests/test_classifier.py +0 -0
- {sourcecode-1.30.11 → sourcecode-1.30.12}/tests/test_cli.py +0 -0
- {sourcecode-1.30.11 → sourcecode-1.30.12}/tests/test_code_notes_analyzer.py +0 -0
- {sourcecode-1.30.11 → sourcecode-1.30.12}/tests/test_context_scorer.py +0 -0
- {sourcecode-1.30.11 → sourcecode-1.30.12}/tests/test_contract_pipeline.py +0 -0
- {sourcecode-1.30.11 → sourcecode-1.30.12}/tests/test_coverage_parser.py +0 -0
- {sourcecode-1.30.11 → sourcecode-1.30.12}/tests/test_cross_consistency.py +0 -0
- {sourcecode-1.30.11 → sourcecode-1.30.12}/tests/test_dependency_analyzer_node_python.py +0 -0
- {sourcecode-1.30.11 → sourcecode-1.30.12}/tests/test_dependency_analyzer_polyglot.py +0 -0
- {sourcecode-1.30.11 → sourcecode-1.30.12}/tests/test_dependency_schema.py +0 -0
- {sourcecode-1.30.11 → sourcecode-1.30.12}/tests/test_detector_dotnet.py +0 -0
- {sourcecode-1.30.11 → sourcecode-1.30.12}/tests/test_detector_go_rust_java.py +0 -0
- {sourcecode-1.30.11 → sourcecode-1.30.12}/tests/test_detector_nodejs.py +0 -0
- {sourcecode-1.30.11 → sourcecode-1.30.12}/tests/test_detector_php_ruby_dart.py +0 -0
- {sourcecode-1.30.11 → sourcecode-1.30.12}/tests/test_detector_python.py +0 -0
- {sourcecode-1.30.11 → sourcecode-1.30.12}/tests/test_detector_universal_managed.py +0 -0
- {sourcecode-1.30.11 → sourcecode-1.30.12}/tests/test_detector_universal_systems.py +0 -0
- {sourcecode-1.30.11 → sourcecode-1.30.12}/tests/test_detectors_base.py +0 -0
- {sourcecode-1.30.11 → sourcecode-1.30.12}/tests/test_doc_analyzer_jsdom.py +0 -0
- {sourcecode-1.30.11 → sourcecode-1.30.12}/tests/test_doc_analyzer_python.py +0 -0
- {sourcecode-1.30.11 → sourcecode-1.30.12}/tests/test_encoding_regression.py +0 -0
- {sourcecode-1.30.11 → sourcecode-1.30.12}/tests/test_graph_analyzer_polyglot.py +0 -0
- {sourcecode-1.30.11 → sourcecode-1.30.12}/tests/test_graph_analyzer_python_node.py +0 -0
- {sourcecode-1.30.11 → sourcecode-1.30.12}/tests/test_graph_schema.py +0 -0
- {sourcecode-1.30.11 → sourcecode-1.30.12}/tests/test_hybrid_inference.py +0 -0
- {sourcecode-1.30.11 → sourcecode-1.30.12}/tests/test_integration.py +0 -0
- {sourcecode-1.30.11 → sourcecode-1.30.12}/tests/test_integration_dependencies.py +0 -0
- {sourcecode-1.30.11 → sourcecode-1.30.12}/tests/test_integration_detection.py +0 -0
- {sourcecode-1.30.11 → sourcecode-1.30.12}/tests/test_integration_docs.py +0 -0
- {sourcecode-1.30.11 → sourcecode-1.30.12}/tests/test_integration_graph_modules.py +0 -0
- {sourcecode-1.30.11 → sourcecode-1.30.12}/tests/test_integration_lqn.py +0 -0
- {sourcecode-1.30.11 → sourcecode-1.30.12}/tests/test_integration_metrics.py +0 -0
- {sourcecode-1.30.11 → sourcecode-1.30.12}/tests/test_integration_multistack.py +0 -0
- {sourcecode-1.30.11 → sourcecode-1.30.12}/tests/test_integration_semantics.py +0 -0
- {sourcecode-1.30.11 → sourcecode-1.30.12}/tests/test_integration_universal.py +0 -0
- {sourcecode-1.30.11 → sourcecode-1.30.12}/tests/test_java_spring_integration.py +0 -0
- {sourcecode-1.30.11 → sourcecode-1.30.12}/tests/test_metrics_analyzer.py +0 -0
- {sourcecode-1.30.11 → sourcecode-1.30.12}/tests/test_packaging.py +0 -0
- {sourcecode-1.30.11 → sourcecode-1.30.12}/tests/test_phase1_improvements.py +0 -0
- {sourcecode-1.30.11 → sourcecode-1.30.12}/tests/test_pipeline_integrity.py +0 -0
- {sourcecode-1.30.11 → sourcecode-1.30.12}/tests/test_real_projects.py +0 -0
- {sourcecode-1.30.11 → sourcecode-1.30.12}/tests/test_redactor.py +0 -0
- {sourcecode-1.30.11 → sourcecode-1.30.12}/tests/test_scanner.py +0 -0
- {sourcecode-1.30.11 → sourcecode-1.30.12}/tests/test_schema.py +0 -0
- {sourcecode-1.30.11 → sourcecode-1.30.12}/tests/test_schema_normalization.py +0 -0
- {sourcecode-1.30.11 → sourcecode-1.30.12}/tests/test_semantic_analyzer_node.py +0 -0
- {sourcecode-1.30.11 → sourcecode-1.30.12}/tests/test_semantic_analyzer_python.py +0 -0
- {sourcecode-1.30.11 → sourcecode-1.30.12}/tests/test_semantic_import_resolution.py +0 -0
- {sourcecode-1.30.11 → sourcecode-1.30.12}/tests/test_semantic_schema.py +0 -0
- {sourcecode-1.30.11 → sourcecode-1.30.12}/tests/test_signal_hierarchy.py +0 -0
- {sourcecode-1.30.11 → sourcecode-1.30.12}/tests/test_summarizer.py +0 -0
- {sourcecode-1.30.11 → sourcecode-1.30.12}/tests/test_surface_honesty.py +0 -0
- {sourcecode-1.30.11 → sourcecode-1.30.12}/tests/test_task_differentiation.py +0 -0
- {sourcecode-1.30.11 → sourcecode-1.30.12}/tests/test_telemetry.py +0 -0
- {sourcecode-1.30.11 → sourcecode-1.30.12}/tests/test_v1_10_regressions.py +0 -0
- {sourcecode-1.30.11 → sourcecode-1.30.12}/tests/test_workspace_analyzer.py +0 -0
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
# Continue Here — atlas-cli sesión 11
|
|
2
|
+
|
|
3
|
+
**Paused:** 2026-05-16 (sesión 11)
|
|
4
|
+
**Repo:** `/Users/user/Downloads/atlas-cli`
|
|
5
|
+
**Branch:** master
|
|
6
|
+
**Último commit:** `dc157fa` — (fix) mejorando honestidad prepare-context pr
|
|
7
|
+
**Working tree:** `prepare_context.py` modificado (semantic engine fixes — NO committed)
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
## Trabajo de esta sesión
|
|
12
|
+
|
|
13
|
+
### Bloque 1: Strict Diff Source Model
|
|
14
|
+
|
|
15
|
+
**Qué se hizo:**
|
|
16
|
+
- `DiffSourceType` enum añadido (`WORKTREE_UNSTAGED`, `WORKTREE_STAGED`, `GIT_SINCE_REF`, `GIT_RANGE`)
|
|
17
|
+
- `_get_pr_scope_files` reescrito → retorna 4-tuple `(all_files, scope_source, committed_files, uncommitted_files)`. Sin fallback a HEAD~1. Committed solo si `--since` explícito.
|
|
18
|
+
- `_get_git_changed_files` → sin default HEAD~1. Sin `--since`: WORKTREE_UNSTAGED (`git diff --name-only`). Con `--since`: GIT_SINCE_REF.
|
|
19
|
+
- `_FOLDER_TYPE_MAP` eliminado — path/folder no es evidencia.
|
|
20
|
+
- `TaskOutput` nuevos campos: `committed_changes`, `uncommitted_changes`, `analysis_scope`
|
|
21
|
+
- Cada entry `runtime_changes` incluye `diff_source` (GIT_RANGE vs WORKTREE_UNSTAGED)
|
|
22
|
+
- `changed-only` en cli.py: excluye untracked, solo staged+unstaged
|
|
23
|
+
- Tests `test_v1_10_regressions.py`: mocks actualizados a 4-tuple
|
|
24
|
+
|
|
25
|
+
**Committed en:** `dc157fa`
|
|
26
|
+
|
|
27
|
+
---
|
|
28
|
+
|
|
29
|
+
### Bloque 2: Evidence-Gated Semantic Engine (NO COMMITTED)
|
|
30
|
+
|
|
31
|
+
**Fichero con cambios:** `src/sourcecode/prepare_context.py` (unstaged)
|
|
32
|
+
|
|
33
|
+
**Qué se cambió:**
|
|
34
|
+
|
|
35
|
+
1. **`_ARTIFACT_CHANGE_TYPES["source"]` → `[]`**
|
|
36
|
+
- Antes: `["behavioral_change"]`. Ahora: ninguno.
|
|
37
|
+
- `behavioral_change` solo se emite si `diff_severities` devuelve `api_change` o `security_change`
|
|
38
|
+
|
|
39
|
+
2. **`_DIFF_SEVERITY_CHANGE_TYPES` nuevo dict**
|
|
40
|
+
- `api_change` → `["behavioral_change"]`
|
|
41
|
+
- `security_change` → `["behavioral_change", "security_change"]`
|
|
42
|
+
- `field_change` → `["structural_change"]`
|
|
43
|
+
- `unknown/trivial` → `[]`
|
|
44
|
+
|
|
45
|
+
3. **`_ATYPE_IMPACT_AREA["source"]` → `"application_layer"` (antes: `"transaction_boundary"`)**
|
|
46
|
+
- `"service"` también → `"application_layer"` (sin evidencia transaccional)
|
|
47
|
+
- `"transaction_boundary"` ya no se emite para archivos no clasificados
|
|
48
|
+
|
|
49
|
+
4. **`_role_in_system` default → `"unclassified"` (antes: `"core_service"`)**
|
|
50
|
+
- `"service"` anotado → `"service"` (no `"core_service"`)
|
|
51
|
+
|
|
52
|
+
5. **`_structured_why` evidence-gated**
|
|
53
|
+
- Solo emite `role_in_system`, `impact_area`, `propagation_risk` si tipo no es `source`/`unclassified`
|
|
54
|
+
- Añade `classification_confidence`
|
|
55
|
+
|
|
56
|
+
6. **`_score_to_confidence(score)` helper**
|
|
57
|
+
- `>= 0.60` → `"high"`, `>= 0.40` → `"medium"`, else → `"low"`
|
|
58
|
+
|
|
59
|
+
7. **`impact_score_per_file` ahora es dict estructurado**
|
|
60
|
+
```json
|
|
61
|
+
{
|
|
62
|
+
"score": 0.145,
|
|
63
|
+
"confidence": "low",
|
|
64
|
+
"score_breakdown": { "artifact_base": 0.125, ... },
|
|
65
|
+
"change_types": [],
|
|
66
|
+
"diff_severity": "trivial"
|
|
67
|
+
}
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
8. **`behavioral_changes`** — gateado en `diff_severities`, no en artifact type
|
|
71
|
+
|
|
72
|
+
9. **`changed_subsystems`** — excluye `source`/`unclassified`; eliminado `"transaction_layer"` del mapa
|
|
73
|
+
|
|
74
|
+
10. **`dependency_graph_summary.propagation_depth`** → `None` cuando no hay graph edges (no `0`)
|
|
75
|
+
|
|
76
|
+
11. **`_runtime_impact`** — eliminado mensaje de "verify transaction scope" para service sin evidencia anotacional
|
|
77
|
+
|
|
78
|
+
**Resultado verificado:**
|
|
79
|
+
```
|
|
80
|
+
changed_subsystems: []
|
|
81
|
+
behavioral_changes: []
|
|
82
|
+
role: unclassified
|
|
83
|
+
why: artifact_type: source | classification_confidence: low | change_effect: ...
|
|
84
|
+
# Sin: core_service, transaction_boundary, transaction_layer, propagation_risk
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
**Tests:** 765 passed, 3 skipped (sin nuevos fallos)
|
|
88
|
+
|
|
89
|
+
---
|
|
90
|
+
|
|
91
|
+
## Estado de tests
|
|
92
|
+
|
|
93
|
+
```
|
|
94
|
+
765 passed, 3 skipped
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
Pre-existing failures (no relacionados):
|
|
98
|
+
- `tests/test_block2_coverage.py` — DocRecord bug en `doc_analyzer.py`
|
|
99
|
+
- `tests/test_dependency_analyzer_node_python.py::test_python_requirements_without_lockfile_keeps_declared_versions`
|
|
100
|
+
|
|
101
|
+
---
|
|
102
|
+
|
|
103
|
+
## PENDIENTE (antes de próximo commit)
|
|
104
|
+
|
|
105
|
+
1. **Commit semantic engine fixes** en `prepare_context.py`
|
|
106
|
+
```bash
|
|
107
|
+
git add src/sourcecode/prepare_context.py
|
|
108
|
+
git commit -m "fix: evidence-gated semantic engine — remove unsupported behavioral/transaction claims"
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
2. **Smoke test en repo spring-boot real**
|
|
112
|
+
```bash
|
|
113
|
+
cd ~/Documents/workspace/spring-boot-realworld-example-app
|
|
114
|
+
sourcecode prepare-context delta --since HEAD~1 2>/dev/null | python3 -c "
|
|
115
|
+
import json, sys
|
|
116
|
+
d = json.load(sys.stdin)
|
|
117
|
+
si = d.get('system_impact', {})
|
|
118
|
+
print('subsystems:', si.get('changed_subsystems'))
|
|
119
|
+
print('behavioral:', si.get('behavioral_changes'))
|
|
120
|
+
for f, v in d.get('impact_score_per_file', {}).items():
|
|
121
|
+
print(f'{f}: conf={v[\"confidence\"]} sev={v[\"diff_severity\"]}')
|
|
122
|
+
"
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
3. **Smoke test behavioral_impact** (pendiente de sesión anterior):
|
|
126
|
+
```bash
|
|
127
|
+
cd ~/Documents/workspace/spring-boot-realworld-example-app
|
|
128
|
+
sourcecode prepare-context review-pr . 2>/dev/null | python3 -c "
|
|
129
|
+
import json, sys
|
|
130
|
+
d = json.load(sys.stdin)
|
|
131
|
+
for bi in d.get('behavioral_impact', []):
|
|
132
|
+
print('entry:', bi['entry_point'])
|
|
133
|
+
print('confidence:', bi['confidence'])
|
|
134
|
+
print('trace:', bi['trace'])
|
|
135
|
+
print()
|
|
136
|
+
"
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
4. **Tests unitarios para `_classify_diff_severity`** — aún sin cobertura
|
|
140
|
+
|
|
141
|
+
5. **`User.java` clasificado como `"source"` no `"domain_model"`** — fix opcional
|
|
142
|
+
|
|
143
|
+
6. **Evaluar si `execution_paths` sigue siendo útil** o si `behavioral_impact` lo reemplaza
|
|
144
|
+
|
|
145
|
+
---
|
|
146
|
+
|
|
147
|
+
## Para retomar
|
|
148
|
+
|
|
149
|
+
```bash
|
|
150
|
+
cd /Users/user/Downloads/atlas-cli
|
|
151
|
+
git status # debe mostrar: prepare_context.py modified
|
|
152
|
+
|
|
153
|
+
python3 -m pytest tests/ \
|
|
154
|
+
--ignore=tests/test_block2_coverage.py \
|
|
155
|
+
--ignore=tests/test_dependency_analyzer_node_python.py \
|
|
156
|
+
-q
|
|
157
|
+
# Expected: 765 passed, 3 skipped
|
|
158
|
+
|
|
159
|
+
# Luego commit el semantic engine:
|
|
160
|
+
git add src/sourcecode/prepare_context.py
|
|
161
|
+
git commit -m "fix: evidence-gated semantic engine — remove unsupported behavioral/transaction claims"
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
---
|
|
165
|
+
|
|
166
|
+
*Pausado 2026-05-16 sesión 11 — gsd:pause-work*
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: sourcecode
|
|
3
|
-
Version: 1.30.
|
|
3
|
+
Version: 1.30.12
|
|
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.12
|
|
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.12
|
|
42
42
|
```
|
|
43
43
|
|
|
44
44
|
---
|
|
@@ -1952,6 +1952,89 @@ def telemetry_disable() -> None:
|
|
|
1952
1952
|
typer.echo("Re-enable at any time: sourcecode telemetry enable")
|
|
1953
1953
|
|
|
1954
1954
|
|
|
1955
|
+
# ── repo-ir ───────────────────────────────────────────────────────────────────
|
|
1956
|
+
|
|
1957
|
+
@app.command("repo-ir")
|
|
1958
|
+
def repo_ir_cmd(
|
|
1959
|
+
path: Path = typer.Argument(
|
|
1960
|
+
Path("."),
|
|
1961
|
+
help="Repository root to analyze (default: current directory)",
|
|
1962
|
+
),
|
|
1963
|
+
since: Optional[str] = typer.Option(
|
|
1964
|
+
None,
|
|
1965
|
+
"--since",
|
|
1966
|
+
help="Git ref for symbol-level diff (e.g. HEAD~1, main)",
|
|
1967
|
+
),
|
|
1968
|
+
files: Optional[str] = typer.Option(
|
|
1969
|
+
None,
|
|
1970
|
+
"--files",
|
|
1971
|
+
help="Comma-separated list of Java files (relative to path) to analyze",
|
|
1972
|
+
),
|
|
1973
|
+
output_path: Optional[Path] = typer.Option(
|
|
1974
|
+
None,
|
|
1975
|
+
"--output",
|
|
1976
|
+
"-o",
|
|
1977
|
+
help="Write output to a file instead of stdout",
|
|
1978
|
+
),
|
|
1979
|
+
include_tests: bool = typer.Option(
|
|
1980
|
+
False,
|
|
1981
|
+
"--include-tests",
|
|
1982
|
+
help="Include test files in analysis (excluded by default)",
|
|
1983
|
+
),
|
|
1984
|
+
) -> None:
|
|
1985
|
+
"""Deterministic symbol-level IR for Java repositories.
|
|
1986
|
+
|
|
1987
|
+
\b
|
|
1988
|
+
Extracts symbols, relations, Spring roles, and (with --since) symbol-level diffs.
|
|
1989
|
+
Output is JSON: symbols[], relations[], changed_symbols[], spring_summary, graph_metadata.
|
|
1990
|
+
|
|
1991
|
+
\b
|
|
1992
|
+
Examples:
|
|
1993
|
+
sourcecode repo-ir
|
|
1994
|
+
sourcecode repo-ir /path/to/repo --since HEAD~1
|
|
1995
|
+
sourcecode repo-ir --files src/main/java/UserService.java
|
|
1996
|
+
sourcecode repo-ir --since main --output ir.json
|
|
1997
|
+
"""
|
|
1998
|
+
import json as _json
|
|
1999
|
+
import sys as _sys
|
|
2000
|
+
|
|
2001
|
+
from sourcecode.repository_ir import build_repo_ir, find_java_files
|
|
2002
|
+
|
|
2003
|
+
root = path.resolve()
|
|
2004
|
+
if not root.is_dir():
|
|
2005
|
+
typer.echo(f"Error: {root} is not a directory", err=True)
|
|
2006
|
+
raise typer.Exit(1)
|
|
2007
|
+
|
|
2008
|
+
if files:
|
|
2009
|
+
file_list = [f.strip() for f in files.split(",") if f.strip()]
|
|
2010
|
+
else:
|
|
2011
|
+
file_list = find_java_files(root)
|
|
2012
|
+
if not include_tests:
|
|
2013
|
+
file_list = [f for f in file_list if "/test/" not in f and "/tests/" not in f]
|
|
2014
|
+
|
|
2015
|
+
if not file_list:
|
|
2016
|
+
typer.echo(
|
|
2017
|
+
_json.dumps({
|
|
2018
|
+
"symbols": [],
|
|
2019
|
+
"relations": [],
|
|
2020
|
+
"changed_symbols": [],
|
|
2021
|
+
"spring_summary": {},
|
|
2022
|
+
"graph_metadata": {"node_count": 0, "edge_count": 0, "has_call_graph": False},
|
|
2023
|
+
}, indent=2)
|
|
2024
|
+
)
|
|
2025
|
+
return
|
|
2026
|
+
|
|
2027
|
+
ir = build_repo_ir(file_list, root, since=since)
|
|
2028
|
+
output = _json.dumps(ir, indent=2, ensure_ascii=False)
|
|
2029
|
+
|
|
2030
|
+
if output_path:
|
|
2031
|
+
output_path.write_text(output, encoding="utf-8")
|
|
2032
|
+
typer.echo(f"IR written to {output_path}", err=True)
|
|
2033
|
+
else:
|
|
2034
|
+
_sys.stdout.write(output)
|
|
2035
|
+
_sys.stdout.write("\n")
|
|
2036
|
+
|
|
2037
|
+
|
|
1955
2038
|
# ── version ───────────────────────────────────────────────────────────────────
|
|
1956
2039
|
|
|
1957
2040
|
@app.command("version")
|
|
@@ -1037,7 +1037,7 @@ class TaskContextBuilder:
|
|
|
1037
1037
|
_pr_review_hotspots = sorted(
|
|
1038
1038
|
[f for f, cls in _pr_changed_cls.items()
|
|
1039
1039
|
if not cls["is_noise"] and cls["artifact_type"] != "build_manifest"],
|
|
1040
|
-
key=lambda f: _delta_impact_score_per_file.get(f, 0.0),
|
|
1040
|
+
key=lambda f: (_delta_impact_score_per_file.get(f) or {}).get("score", 0.0),
|
|
1041
1041
|
reverse=True,
|
|
1042
1042
|
)[:8]
|
|
1043
1043
|
|
|
@@ -1130,9 +1130,9 @@ class TaskContextBuilder:
|
|
|
1130
1130
|
"basis": _role_basis,
|
|
1131
1131
|
}
|
|
1132
1132
|
|
|
1133
|
-
# File confidence:
|
|
1134
|
-
|
|
1135
|
-
_f_conf =
|
|
1133
|
+
# File confidence: from structured impact entry
|
|
1134
|
+
_impact_entry = _delta_impact_score_per_file.get(_f) or {}
|
|
1135
|
+
_f_conf = _impact_entry.get("confidence", "low")
|
|
1136
1136
|
_diff_source = (
|
|
1137
1137
|
DiffSourceType.GIT_RANGE.value if _f in _committed_set
|
|
1138
1138
|
else DiffSourceType.WORKTREE_UNSTAGED.value if _f in _uncommitted_set
|
|
@@ -2237,14 +2237,17 @@ class TaskContextBuilder:
|
|
|
2237
2237
|
# use module-level constant (single source of truth)
|
|
2238
2238
|
_CHANGE_EFFECT = _ARTIFACT_CHANGE_EFFECT
|
|
2239
2239
|
|
|
2240
|
-
# change_type taxonomy —
|
|
2240
|
+
# change_type taxonomy — evidence-gated.
|
|
2241
|
+
# "source" → no change_type: unclassified file has no confirmed executable role.
|
|
2242
|
+
# behavioral_change requires semantic diff evidence (api_change/security_change),
|
|
2243
|
+
# not just artifact type — gate applied in Step 3d using diff_severities.
|
|
2241
2244
|
_ARTIFACT_CHANGE_TYPES: dict[str, list[str]] = {
|
|
2242
|
-
"entrypoint": ["
|
|
2243
|
-
"security": ["
|
|
2244
|
-
"controller": ["
|
|
2245
|
-
"service": [
|
|
2246
|
-
"repository": [
|
|
2247
|
-
"mapper": [
|
|
2245
|
+
"entrypoint": ["structural_change"], # behavioral only if diff confirms
|
|
2246
|
+
"security": ["security_change"],
|
|
2247
|
+
"controller": ["structural_change"], # behavioral only if diff confirms
|
|
2248
|
+
"service": [], # behavioral only if @Transactional or diff confirms
|
|
2249
|
+
"repository": [], # behavioral only if query/ORM diff confirms
|
|
2250
|
+
"mapper": [],
|
|
2248
2251
|
"spring_config": ["configuration_change"],
|
|
2249
2252
|
"spring_profile": ["configuration_change"],
|
|
2250
2253
|
"config": ["configuration_change"],
|
|
@@ -2252,22 +2255,34 @@ class TaskContextBuilder:
|
|
|
2252
2255
|
"db_migration": ["structural_change"],
|
|
2253
2256
|
"domain_model": ["structural_change"],
|
|
2254
2257
|
"dto": ["structural_change"],
|
|
2255
|
-
"source": [
|
|
2258
|
+
"source": [], # no claim without content evidence
|
|
2256
2259
|
"test": [],
|
|
2257
2260
|
"documentation": [],
|
|
2258
2261
|
"ide_noise": [],
|
|
2259
2262
|
}
|
|
2260
2263
|
|
|
2264
|
+
# Semantic diff → change_type supplement (gated on actual diff content)
|
|
2265
|
+
# applied per-file in Step 3d alongside diff_severities
|
|
2266
|
+
_DIFF_SEVERITY_CHANGE_TYPES: dict[str, list[str]] = {
|
|
2267
|
+
"api_change": ["behavioral_change"],
|
|
2268
|
+
"security_change": ["behavioral_change", "security_change"],
|
|
2269
|
+
"field_change": ["structural_change"],
|
|
2270
|
+
"trivial": [],
|
|
2271
|
+
"unknown": [], # no claim — unknown diff content
|
|
2272
|
+
}
|
|
2273
|
+
|
|
2261
2274
|
_SEV_ORDER = ["noise", "low", "medium", "high", "critical"]
|
|
2262
2275
|
|
|
2263
|
-
#
|
|
2276
|
+
# impact_area taxonomy — evidence-gated.
|
|
2277
|
+
# "source" → "application_layer" (neutral). transaction_boundary only for
|
|
2278
|
+
# evidence-confirmed service/transactional artifacts.
|
|
2264
2279
|
_ATYPE_IMPACT_AREA: dict[str, str] = {
|
|
2265
2280
|
"entrypoint": "api_surface",
|
|
2266
2281
|
"controller": "api_surface",
|
|
2267
2282
|
"dto": "api_surface",
|
|
2268
2283
|
"security": "security_layer",
|
|
2269
2284
|
"spring_config": "dependency_injection",
|
|
2270
|
-
"service": "
|
|
2285
|
+
"service": "application_layer", # transaction_boundary only if @Transactional evidence
|
|
2271
2286
|
"repository": "persistence_layer",
|
|
2272
2287
|
"mapper": "persistence_layer",
|
|
2273
2288
|
"db_migration": "persistence_layer",
|
|
@@ -2275,7 +2290,7 @@ class TaskContextBuilder:
|
|
|
2275
2290
|
"config": "configuration",
|
|
2276
2291
|
"spring_profile": "configuration",
|
|
2277
2292
|
"build_manifest": "build_system",
|
|
2278
|
-
"source": "
|
|
2293
|
+
"source": "application_layer", # neutral — no transaction claim without evidence
|
|
2279
2294
|
"test": "configuration",
|
|
2280
2295
|
"documentation": "configuration",
|
|
2281
2296
|
"ide_noise": "configuration",
|
|
@@ -2287,18 +2302,18 @@ class TaskContextBuilder:
|
|
|
2287
2302
|
path_lower = path.lower()
|
|
2288
2303
|
suffix = Path(path).suffix.lower()
|
|
2289
2304
|
path_segs = set(path_lower.replace("\\", "/").split("/"))
|
|
2290
|
-
# UI layer: frontend file extensions or frontend directory segments
|
|
2291
2305
|
if suffix in (".tsx", ".jsx", ".vue") or (
|
|
2292
2306
|
suffix in (".ts", ".js") and bool(path_segs & _UI_PATH_SEGS)
|
|
2293
2307
|
):
|
|
2294
2308
|
return "ui_layer"
|
|
2295
|
-
# Integration layer: external service clients and adapters
|
|
2296
2309
|
stem_lower = Path(path).stem.lower()
|
|
2297
2310
|
if any(kw in stem_lower for kw in _INTEGRATION_STEMS):
|
|
2298
2311
|
return "integration_layer"
|
|
2299
|
-
return _ATYPE_IMPACT_AREA.get(atype, "
|
|
2312
|
+
return _ATYPE_IMPACT_AREA.get(atype, "application_layer")
|
|
2300
2313
|
|
|
2301
|
-
#
|
|
2314
|
+
# role_in_system — evidence-gated.
|
|
2315
|
+
# Default is "unclassified" not "core_service": unclassified source files
|
|
2316
|
+
# have no confirmed architectural role.
|
|
2302
2317
|
def _role_in_system(path: str, atype: str, in_ep_paths: bool) -> str:
|
|
2303
2318
|
if atype == "build_manifest":
|
|
2304
2319
|
return "build_artifact"
|
|
@@ -2317,19 +2332,30 @@ class TaskContextBuilder:
|
|
|
2317
2332
|
return "configuration"
|
|
2318
2333
|
if atype in ("repository", "mapper", "db_migration"):
|
|
2319
2334
|
return "data_access"
|
|
2320
|
-
|
|
2321
|
-
|
|
2322
|
-
|
|
2335
|
+
if atype == "service":
|
|
2336
|
+
return "service" # annotation-confirmed — not "core_service" (overclaim)
|
|
2337
|
+
return "unclassified" # no role claim without evidence
|
|
2338
|
+
|
|
2339
|
+
def _score_to_confidence(score: float) -> str:
|
|
2340
|
+
if score >= 0.60:
|
|
2341
|
+
return "high"
|
|
2342
|
+
if score >= 0.40:
|
|
2343
|
+
return "medium"
|
|
2344
|
+
return "low"
|
|
2345
|
+
|
|
2346
|
+
def _structured_why(path: str, atype: str, module: str, role: str, risk_areas: list[str], cls_confidence: str = "low") -> str:
|
|
2323
2347
|
area = _classify_impact_area(path, risk_areas, atype)
|
|
2324
|
-
prop = _PROPAGATION_RISK.get(atype, "low")
|
|
2325
|
-
effect = _CHANGE_EFFECT.get(atype, "
|
|
2326
|
-
parts = [
|
|
2327
|
-
|
|
2328
|
-
|
|
2329
|
-
f"
|
|
2330
|
-
|
|
2331
|
-
f"
|
|
2332
|
-
|
|
2348
|
+
prop = _PROPAGATION_RISK.get(atype, "low") if atype != "source" else "unknown"
|
|
2349
|
+
effect = _CHANGE_EFFECT.get(atype, "may modify application logic (role unconfirmed)")
|
|
2350
|
+
parts = [f"artifact_type: {atype}", f"classification_confidence: {cls_confidence}"]
|
|
2351
|
+
# Only emit role/area/propagation when there is confirmed evidence (not source/unclassified)
|
|
2352
|
+
if role not in ("unclassified",):
|
|
2353
|
+
parts.append(f"role_in_system: {role}")
|
|
2354
|
+
if area not in ("application_layer",):
|
|
2355
|
+
parts.append(f"impact_area: {area}")
|
|
2356
|
+
if atype not in ("source",) and prop != "unknown":
|
|
2357
|
+
parts.append(f"propagation_risk: {prop}")
|
|
2358
|
+
parts.append(f"change_effect: {effect}")
|
|
2333
2359
|
if module:
|
|
2334
2360
|
parts.append(f"module: {module}")
|
|
2335
2361
|
return " | ".join(parts)
|
|
@@ -2403,8 +2429,10 @@ class TaskContextBuilder:
|
|
|
2403
2429
|
|
|
2404
2430
|
in_ep = path in ep_paths
|
|
2405
2431
|
role = _role_in_system(path, atype, in_ep)
|
|
2406
|
-
|
|
2407
|
-
|
|
2432
|
+
cls_conf = cls.get("confidence", "low")
|
|
2433
|
+
why_str = _structured_why(path, atype, module, role, cls["risk_areas"], cls_conf)
|
|
2434
|
+
confidence = _score_to_confidence(score)
|
|
2435
|
+
reason = f"changed since {ref_label} | artifact: {atype} | confidence: {confidence}"
|
|
2408
2436
|
|
|
2409
2437
|
relevant.append(RelevantFile(path=path, role=role, score=round(score, 2), reason=reason, why=why_str))
|
|
2410
2438
|
why[path] = why_str
|
|
@@ -2453,15 +2481,11 @@ class TaskContextBuilder:
|
|
|
2453
2481
|
]
|
|
2454
2482
|
in_ep = path in ep_paths
|
|
2455
2483
|
role = _role_in_system(path, rel_atype, in_ep)
|
|
2456
|
-
|
|
2457
|
-
|
|
2458
|
-
|
|
2459
|
-
|
|
2460
|
-
|
|
2461
|
-
f" | pulled_by: type-aware expansion from {ctx_type} '{ctx_val}'"
|
|
2462
|
-
f" | triggered_by: {', '.join(triggers[:3])}"
|
|
2463
|
-
)
|
|
2464
|
-
reason = f"expansion: {ctx_type} '{ctx_val}' | artifact: {rel_atype} | score: {rel_score:.2f}"
|
|
2484
|
+
rel_conf = rel_cls.get("confidence", "low")
|
|
2485
|
+
why_str = _structured_why(path, rel_atype, _extract_ddd_domain(path), role, rel_cls["risk_areas"], rel_conf)
|
|
2486
|
+
why_str += f" | pulled_by: type-aware expansion from {ctx_type} '{ctx_val}'"
|
|
2487
|
+
why_str += f" | triggered_by: {', '.join(triggers[:3])}"
|
|
2488
|
+
reason = f"expansion: {ctx_type} '{ctx_val}' | artifact: {rel_atype} | confidence: {_score_to_confidence(rel_score)}"
|
|
2465
2489
|
related.append((rel_score, path, RelevantFile(
|
|
2466
2490
|
path=path, role=role, score=rel_score, reason=reason, why=why_str
|
|
2467
2491
|
)))
|
|
@@ -2563,16 +2587,15 @@ class TaskContextBuilder:
|
|
|
2563
2587
|
_dep_score = round(_dep_score_base * (0.70 ** _hop_num) * _cross_module_factor, 2)
|
|
2564
2588
|
_dep_role = _role_in_system(_dep_path, _dep_atype, _dep_path in ep_paths)
|
|
2565
2589
|
|
|
2566
|
-
|
|
2567
|
-
|
|
2568
|
-
|
|
2569
|
-
|
|
2570
|
-
f" | change_effect: {_CHANGE_EFFECT.get(_dep_atype, 'modifies application logic')}"
|
|
2571
|
-
f" | pulled_by: hop-{_hop_num} import from {Path(_seed_path).name}"
|
|
2590
|
+
_dep_conf = _dep_cls.get("confidence", "low")
|
|
2591
|
+
_why_str = _structured_why(
|
|
2592
|
+
_dep_path, _dep_atype, _dep_module, _dep_role,
|
|
2593
|
+
_dep_cls["risk_areas"], _dep_conf
|
|
2572
2594
|
)
|
|
2595
|
+
_why_str += f" | pulled_by: hop-{_hop_num} import from {Path(_seed_path).name}"
|
|
2573
2596
|
_reason = (
|
|
2574
2597
|
f"hop-{_hop_num} import-dependent of {Path(_seed_path).name}"
|
|
2575
|
-
f" ({_seed_atype}) |
|
|
2598
|
+
f" ({_seed_atype}) | confidence: {_score_to_confidence(_dep_score)}"
|
|
2576
2599
|
)
|
|
2577
2600
|
why[_dep_path] = _why_str
|
|
2578
2601
|
# Tests import production code but are not structural dependencies —
|
|
@@ -2621,13 +2644,18 @@ class TaskContextBuilder:
|
|
|
2621
2644
|
if _edge["from"] in _downstream_count:
|
|
2622
2645
|
_downstream_count[_edge["from"]] += 1
|
|
2623
2646
|
|
|
2624
|
-
impact_score_per_file: dict[str,
|
|
2647
|
+
impact_score_per_file: dict[str, Any] = {}
|
|
2625
2648
|
all_change_types: set[str] = set()
|
|
2626
2649
|
for _path in changed_files:
|
|
2627
2650
|
_cls = classifications[_path]
|
|
2628
2651
|
_atype = _cls["artifact_type"]
|
|
2629
|
-
|
|
2652
|
+
# Base change types from artifact classification
|
|
2653
|
+
_file_ctypes: set[str] = set(_ARTIFACT_CHANGE_TYPES.get(_atype, []))
|
|
2654
|
+
# Supplement with semantic diff evidence — behavioral_change ONLY from diff
|
|
2655
|
+
_diff_sev = diff_severities.get(_path, "unknown")
|
|
2656
|
+
_file_ctypes.update(_DIFF_SEVERITY_CHANGE_TYPES.get(_diff_sev, []))
|
|
2630
2657
|
all_change_types.update(_file_ctypes)
|
|
2658
|
+
|
|
2631
2659
|
_base = _ARTIFACT_SCORE.get(_atype, 0.45)
|
|
2632
2660
|
_sec_w = 0.20 if (_atype == "security" or "security" in _cls["risk_areas"]) else 0.0
|
|
2633
2661
|
_fw = (
|
|
@@ -2641,58 +2669,78 @@ class TaskContextBuilder:
|
|
|
2641
2669
|
0.05 if any(ct in ("structural_change", "dependency_change") for ct in _file_ctypes) else
|
|
2642
2670
|
0.02
|
|
2643
2671
|
)
|
|
2644
|
-
|
|
2672
|
+
_raw_score = round(min(1.0, _base * 0.50 + _sec_w + _fw + _fanout + _ctw), 3)
|
|
2673
|
+
impact_score_per_file[_path] = {
|
|
2674
|
+
"score": _raw_score,
|
|
2675
|
+
"confidence": _score_to_confidence(_raw_score),
|
|
2676
|
+
"score_breakdown": {
|
|
2677
|
+
"artifact_base": round(_base * 0.50, 3),
|
|
2678
|
+
"security_weight": _sec_w,
|
|
2679
|
+
"framework_weight": _fw,
|
|
2680
|
+
"fanout_weight": round(_fanout, 3),
|
|
2681
|
+
"change_type_weight": _ctw,
|
|
2682
|
+
},
|
|
2683
|
+
"change_types": sorted(_file_ctypes),
|
|
2684
|
+
"diff_severity": _diff_sev,
|
|
2685
|
+
}
|
|
2645
2686
|
|
|
2646
2687
|
_CT_ORDER = ["security_change", "behavioral_change", "structural_change",
|
|
2647
2688
|
"configuration_change", "dependency_change", "ui_change"]
|
|
2648
2689
|
aggregate_change_type = [ct for ct in _CT_ORDER if ct in all_change_types]
|
|
2649
2690
|
|
|
2650
|
-
# system_impact
|
|
2691
|
+
# system_impact: only evidence-backed subsystems.
|
|
2692
|
+
# application_layer → not emitted as subsystem (no architectural claim without evidence).
|
|
2693
|
+
# transaction_layer → removed: transaction_boundary no longer mapped to source/service.
|
|
2651
2694
|
_IMPACT_AREA_TO_SUBSYSTEM = {
|
|
2652
2695
|
"api_surface": "api_layer",
|
|
2653
2696
|
"security_layer": "security_layer",
|
|
2654
2697
|
"dependency_injection": "spring_di_layer",
|
|
2655
2698
|
"persistence_layer": "persistence_layer",
|
|
2656
|
-
"transaction_boundary": "transaction_layer",
|
|
2657
2699
|
"configuration": "configuration_layer",
|
|
2658
2700
|
"build_system": "build_system",
|
|
2659
2701
|
"ui_layer": "ui_layer",
|
|
2660
2702
|
"integration_layer": "integration_layer",
|
|
2703
|
+
# application_layer intentionally omitted — no subsystem claim for unclassified files
|
|
2661
2704
|
}
|
|
2662
2705
|
_seen_subsys: set[str] = set()
|
|
2663
2706
|
changed_subsystems: list[str] = []
|
|
2664
2707
|
for _p, _cls in classifications.items():
|
|
2665
|
-
|
|
2666
|
-
|
|
2708
|
+
_p_atype = _cls["artifact_type"]
|
|
2709
|
+
# Only emit subsystem for evidence-backed classifications (not source/unclassified)
|
|
2710
|
+
if not _cls["is_noise"] and _p_atype not in ("source", "ide_noise"):
|
|
2711
|
+
_area = _classify_impact_area(_p, _cls["risk_areas"], _p_atype)
|
|
2667
2712
|
_subsys = _IMPACT_AREA_TO_SUBSYSTEM.get(_area)
|
|
2668
2713
|
if _subsys and _subsys not in _seen_subsys:
|
|
2669
2714
|
changed_subsystems.append(_subsys)
|
|
2670
2715
|
_seen_subsys.add(_subsys)
|
|
2671
2716
|
|
|
2717
|
+
# behavioral_changes: gated on semantic diff evidence (api_change/security_change),
|
|
2718
|
+
# NOT on artifact type alone. Avoids false behavioral claims for validator/util files.
|
|
2672
2719
|
behavioral_changes: list[str] = [
|
|
2673
|
-
f"{Path(_p).name}: {_CHANGE_EFFECT
|
|
2720
|
+
f"{Path(_p).name}: {_CHANGE_EFFECT.get(_cls['artifact_type'], 'may modify application logic')}"
|
|
2674
2721
|
for _p, _cls in classifications.items()
|
|
2675
2722
|
if not _cls["is_noise"]
|
|
2676
|
-
and
|
|
2677
|
-
for ct in _ARTIFACT_CHANGE_TYPES.get(_cls["artifact_type"], []))
|
|
2723
|
+
and diff_severities.get(_p, "unknown") in ("api_change", "security_change")
|
|
2678
2724
|
]
|
|
2679
2725
|
|
|
2680
2726
|
def _runtime_impact(tc: dict[str, int]) -> list[str]:
|
|
2681
2727
|
_ri: list[str] = []
|
|
2728
|
+
# Only emit claims that are evidence-backed (annotation-confirmed roles)
|
|
2682
2729
|
if "entrypoint" in tc:
|
|
2683
|
-
_ri.append("Entrypoint-classified file modified — may require full context restart before deploy
|
|
2730
|
+
_ri.append("Entrypoint-classified file modified — may require full context restart before deploy")
|
|
2684
2731
|
if "spring_config" in tc:
|
|
2685
|
-
_ri.append("Spring config-classified file modified — wired beans may be rewired on restart
|
|
2732
|
+
_ri.append("Spring config-classified file modified — wired beans may be rewired on restart")
|
|
2686
2733
|
if "security" in tc:
|
|
2687
|
-
_ri.append("Security-classified file modified — secured endpoints may be affected after restart
|
|
2734
|
+
_ri.append("Security-classified file modified — secured endpoints may be affected after restart")
|
|
2688
2735
|
if "db_migration" in tc:
|
|
2689
2736
|
_ri.append("Database schema migration pending — execute before deploying application")
|
|
2737
|
+
# service transactional claim: only if @Service annotation confirmed (not source/unclassified)
|
|
2690
2738
|
_svc = tc.get("service", 0)
|
|
2691
2739
|
if _svc >= 2:
|
|
2692
|
-
_ri.append(f"{_svc}
|
|
2740
|
+
_ri.append(f"{_svc} @Service-annotated file(s) modified — verify business logic consistency")
|
|
2693
2741
|
_repo = tc.get("repository", 0) + tc.get("mapper", 0)
|
|
2694
2742
|
if _repo > 0:
|
|
2695
|
-
_ri.append(f"{_repo} persistence-classified component(s) modified — verify data access queries
|
|
2743
|
+
_ri.append(f"{_repo} persistence-classified component(s) modified — verify data access queries")
|
|
2696
2744
|
if "build_manifest" in tc:
|
|
2697
2745
|
_ri.append("Build manifest modified — dependency resolution required before compile")
|
|
2698
2746
|
return _ri
|
|
@@ -2700,7 +2748,9 @@ class TaskContextBuilder:
|
|
|
2700
2748
|
_max_hop = max((e["hop"] for e in graph_edges), default=0)
|
|
2701
2749
|
dependency_graph_summary: dict = {
|
|
2702
2750
|
"edges": graph_edges[:30],
|
|
2703
|
-
|
|
2751
|
+
# propagation_depth is unknown when no graph edges exist — not 0
|
|
2752
|
+
"propagation_depth": _max_hop if graph_edges else None,
|
|
2753
|
+
"has_graph_evidence": bool(graph_edges),
|
|
2704
2754
|
}
|
|
2705
2755
|
|
|
2706
2756
|
# ── Step 4: impact summary ─────────────────────────────────────────────
|