sourcecode 1.9.0__tar.gz → 1.11.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-1.9.0 → sourcecode-1.11.0}/PKG-INFO +1 -3
- {sourcecode-1.9.0 → sourcecode-1.11.0}/README.md +0 -2
- {sourcecode-1.9.0 → sourcecode-1.11.0}/pyproject.toml +1 -1
- {sourcecode-1.9.0 → sourcecode-1.11.0}/src/sourcecode/__init__.py +1 -1
- {sourcecode-1.9.0 → sourcecode-1.11.0}/src/sourcecode/cli.py +4 -0
- {sourcecode-1.9.0 → sourcecode-1.11.0}/src/sourcecode/prepare_context.py +19 -0
- {sourcecode-1.9.0 → sourcecode-1.11.0}/src/sourcecode/serializer.py +323 -40
- sourcecode-1.11.0/tests/fixtures/spring_boot_minimal/src/main/java/com/example/demo/config/FilterConfig.java +17 -0
- sourcecode-1.11.0/tests/fixtures/spring_boot_minimal/src/main/java/com/example/demo/web/NominaRestController.java +16 -0
- sourcecode-1.11.0/tests/fixtures/spring_boot_minimal/src/main/resources/mapper/HealthMapper.xml +8 -0
- sourcecode-1.11.0/tests/test_v1_10_regressions.py +560 -0
- {sourcecode-1.9.0 → sourcecode-1.11.0}/.agents/skills/source-command-gsd-join-discord/SKILL.md +0 -0
- {sourcecode-1.9.0 → sourcecode-1.11.0}/.agents/skills/source-command-gsd-review-backlog/SKILL.md +0 -0
- {sourcecode-1.9.0 → sourcecode-1.11.0}/.agents/skills/source-command-gsd-workstreams/SKILL.md +0 -0
- {sourcecode-1.9.0 → sourcecode-1.11.0}/.continue-here.md +0 -0
- {sourcecode-1.9.0 → sourcecode-1.11.0}/.github/workflows/build-windows.yml +0 -0
- {sourcecode-1.9.0 → sourcecode-1.11.0}/.gitignore +0 -0
- {sourcecode-1.9.0 → sourcecode-1.11.0}/.ruff.toml +0 -0
- {sourcecode-1.9.0 → sourcecode-1.11.0}/CONTRIBUTING.md +0 -0
- {sourcecode-1.9.0 → sourcecode-1.11.0}/LICENSE +0 -0
- {sourcecode-1.9.0 → sourcecode-1.11.0}/SECURITY.md +0 -0
- {sourcecode-1.9.0 → sourcecode-1.11.0}/docs/privacy.md +0 -0
- {sourcecode-1.9.0 → sourcecode-1.11.0}/docs/schema.md +0 -0
- {sourcecode-1.9.0 → sourcecode-1.11.0}/raw +0 -0
- {sourcecode-1.9.0 → sourcecode-1.11.0}/run_cli.py +0 -0
- {sourcecode-1.9.0 → sourcecode-1.11.0}/src/sourcecode/adaptive_scanner.py +0 -0
- {sourcecode-1.9.0 → sourcecode-1.11.0}/src/sourcecode/architecture_analyzer.py +0 -0
- {sourcecode-1.9.0 → sourcecode-1.11.0}/src/sourcecode/architecture_summary.py +0 -0
- {sourcecode-1.9.0 → sourcecode-1.11.0}/src/sourcecode/ast_extractor.py +0 -0
- {sourcecode-1.9.0 → sourcecode-1.11.0}/src/sourcecode/classifier.py +0 -0
- {sourcecode-1.9.0 → sourcecode-1.11.0}/src/sourcecode/code_notes_analyzer.py +0 -0
- {sourcecode-1.9.0 → sourcecode-1.11.0}/src/sourcecode/confidence_analyzer.py +0 -0
- {sourcecode-1.9.0 → sourcecode-1.11.0}/src/sourcecode/context_scorer.py +0 -0
- {sourcecode-1.9.0 → sourcecode-1.11.0}/src/sourcecode/context_summarizer.py +0 -0
- {sourcecode-1.9.0 → sourcecode-1.11.0}/src/sourcecode/contract_model.py +0 -0
- {sourcecode-1.9.0 → sourcecode-1.11.0}/src/sourcecode/contract_pipeline.py +0 -0
- {sourcecode-1.9.0 → sourcecode-1.11.0}/src/sourcecode/coverage_parser.py +0 -0
- {sourcecode-1.9.0 → sourcecode-1.11.0}/src/sourcecode/dependency_analyzer.py +0 -0
- {sourcecode-1.9.0 → sourcecode-1.11.0}/src/sourcecode/detectors/__init__.py +0 -0
- {sourcecode-1.9.0 → sourcecode-1.11.0}/src/sourcecode/detectors/base.py +0 -0
- {sourcecode-1.9.0 → sourcecode-1.11.0}/src/sourcecode/detectors/csproj_parser.py +0 -0
- {sourcecode-1.9.0 → sourcecode-1.11.0}/src/sourcecode/detectors/dart.py +0 -0
- {sourcecode-1.9.0 → sourcecode-1.11.0}/src/sourcecode/detectors/dotnet.py +0 -0
- {sourcecode-1.9.0 → sourcecode-1.11.0}/src/sourcecode/detectors/elixir.py +0 -0
- {sourcecode-1.9.0 → sourcecode-1.11.0}/src/sourcecode/detectors/go.py +0 -0
- {sourcecode-1.9.0 → sourcecode-1.11.0}/src/sourcecode/detectors/heuristic.py +0 -0
- {sourcecode-1.9.0 → sourcecode-1.11.0}/src/sourcecode/detectors/hybrid.py +0 -0
- {sourcecode-1.9.0 → sourcecode-1.11.0}/src/sourcecode/detectors/java.py +0 -0
- {sourcecode-1.9.0 → sourcecode-1.11.0}/src/sourcecode/detectors/jvm_ext.py +0 -0
- {sourcecode-1.9.0 → sourcecode-1.11.0}/src/sourcecode/detectors/nodejs.py +0 -0
- {sourcecode-1.9.0 → sourcecode-1.11.0}/src/sourcecode/detectors/parsers.py +0 -0
- {sourcecode-1.9.0 → sourcecode-1.11.0}/src/sourcecode/detectors/php.py +0 -0
- {sourcecode-1.9.0 → sourcecode-1.11.0}/src/sourcecode/detectors/project.py +0 -0
- {sourcecode-1.9.0 → sourcecode-1.11.0}/src/sourcecode/detectors/python.py +0 -0
- {sourcecode-1.9.0 → sourcecode-1.11.0}/src/sourcecode/detectors/ruby.py +0 -0
- {sourcecode-1.9.0 → sourcecode-1.11.0}/src/sourcecode/detectors/rust.py +0 -0
- {sourcecode-1.9.0 → sourcecode-1.11.0}/src/sourcecode/detectors/systems.py +0 -0
- {sourcecode-1.9.0 → sourcecode-1.11.0}/src/sourcecode/detectors/terraform.py +0 -0
- {sourcecode-1.9.0 → sourcecode-1.11.0}/src/sourcecode/detectors/tooling.py +0 -0
- {sourcecode-1.9.0 → sourcecode-1.11.0}/src/sourcecode/doc_analyzer.py +0 -0
- {sourcecode-1.9.0 → sourcecode-1.11.0}/src/sourcecode/entrypoint_classifier.py +0 -0
- {sourcecode-1.9.0 → sourcecode-1.11.0}/src/sourcecode/env_analyzer.py +0 -0
- {sourcecode-1.9.0 → sourcecode-1.11.0}/src/sourcecode/file_classifier.py +0 -0
- {sourcecode-1.9.0 → sourcecode-1.11.0}/src/sourcecode/git_analyzer.py +0 -0
- {sourcecode-1.9.0 → sourcecode-1.11.0}/src/sourcecode/graph_analyzer.py +0 -0
- {sourcecode-1.9.0 → sourcecode-1.11.0}/src/sourcecode/metrics_analyzer.py +0 -0
- {sourcecode-1.9.0 → sourcecode-1.11.0}/src/sourcecode/progress.py +0 -0
- {sourcecode-1.9.0 → sourcecode-1.11.0}/src/sourcecode/ranking_engine.py +0 -0
- {sourcecode-1.9.0 → sourcecode-1.11.0}/src/sourcecode/redactor.py +0 -0
- {sourcecode-1.9.0 → sourcecode-1.11.0}/src/sourcecode/relevance_scorer.py +0 -0
- {sourcecode-1.9.0 → sourcecode-1.11.0}/src/sourcecode/repo_classifier.py +0 -0
- {sourcecode-1.9.0 → sourcecode-1.11.0}/src/sourcecode/runtime_classifier.py +0 -0
- {sourcecode-1.9.0 → sourcecode-1.11.0}/src/sourcecode/scanner.py +0 -0
- {sourcecode-1.9.0 → sourcecode-1.11.0}/src/sourcecode/schema.py +0 -0
- {sourcecode-1.9.0 → sourcecode-1.11.0}/src/sourcecode/semantic_analyzer.py +0 -0
- {sourcecode-1.9.0 → sourcecode-1.11.0}/src/sourcecode/summarizer.py +0 -0
- {sourcecode-1.9.0 → sourcecode-1.11.0}/src/sourcecode/telemetry/__init__.py +0 -0
- {sourcecode-1.9.0 → sourcecode-1.11.0}/src/sourcecode/telemetry/config.py +0 -0
- {sourcecode-1.9.0 → sourcecode-1.11.0}/src/sourcecode/telemetry/consent.py +0 -0
- {sourcecode-1.9.0 → sourcecode-1.11.0}/src/sourcecode/telemetry/events.py +0 -0
- {sourcecode-1.9.0 → sourcecode-1.11.0}/src/sourcecode/telemetry/filters.py +0 -0
- {sourcecode-1.9.0 → sourcecode-1.11.0}/src/sourcecode/telemetry/transport.py +0 -0
- {sourcecode-1.9.0 → sourcecode-1.11.0}/src/sourcecode/tree_utils.py +0 -0
- {sourcecode-1.9.0 → sourcecode-1.11.0}/src/sourcecode/workspace.py +0 -0
- {sourcecode-1.9.0 → sourcecode-1.11.0}/tests/__init__.py +0 -0
- {sourcecode-1.9.0 → sourcecode-1.11.0}/tests/conftest.py +0 -0
- {sourcecode-1.9.0 → sourcecode-1.11.0}/tests/fixtures/coverage.xml +0 -0
- {sourcecode-1.9.0 → sourcecode-1.11.0}/tests/fixtures/fastapi_app/pyproject.toml +0 -0
- {sourcecode-1.9.0 → sourcecode-1.11.0}/tests/fixtures/fastapi_app/src/main.py +0 -0
- {sourcecode-1.9.0 → sourcecode-1.11.0}/tests/fixtures/go_service/cmd/api/main.go +0 -0
- {sourcecode-1.9.0 → sourcecode-1.11.0}/tests/fixtures/go_service/go.mod +0 -0
- {sourcecode-1.9.0 → sourcecode-1.11.0}/tests/fixtures/jacoco.xml +0 -0
- {sourcecode-1.9.0 → sourcecode-1.11.0}/tests/fixtures/lcov.info +0 -0
- {sourcecode-1.9.0 → sourcecode-1.11.0}/tests/fixtures/nextjs_app/app/page.tsx +0 -0
- {sourcecode-1.9.0 → sourcecode-1.11.0}/tests/fixtures/nextjs_app/package.json +0 -0
- {sourcecode-1.9.0 → sourcecode-1.11.0}/tests/fixtures/nextjs_app/pnpm-lock.yaml +0 -0
- {sourcecode-1.9.0 → sourcecode-1.11.0}/tests/fixtures/pnpm_monorepo/apps/web/app/page.tsx +0 -0
- {sourcecode-1.9.0 → sourcecode-1.11.0}/tests/fixtures/pnpm_monorepo/apps/web/package.json +0 -0
- {sourcecode-1.9.0 → sourcecode-1.11.0}/tests/fixtures/pnpm_monorepo/packages/api/main.py +0 -0
- {sourcecode-1.9.0 → sourcecode-1.11.0}/tests/fixtures/pnpm_monorepo/packages/api/pyproject.toml +0 -0
- {sourcecode-1.9.0 → sourcecode-1.11.0}/tests/fixtures/pnpm_monorepo/pnpm-workspace.yaml +0 -0
- {sourcecode-1.9.0 → sourcecode-1.11.0}/tests/fixtures/spring_boot_minimal/pom.xml +0 -0
- {sourcecode-1.9.0 → sourcecode-1.11.0}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/ausente/application/service/FindAusenteService.java +0 -0
- {sourcecode-1.9.0 → sourcecode-1.11.0}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/ausente/domain/entities/Ausente.java +0 -0
- {sourcecode-1.9.0 → sourcecode-1.11.0}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/ausente/infrastructure/rest/AusenteRestController.java +0 -0
- {sourcecode-1.9.0 → sourcecode-1.11.0}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/autocoberturas/application/service/FindAutocoberturasService.java +0 -0
- {sourcecode-1.9.0 → sourcecode-1.11.0}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/autocoberturas/domain/entities/Autocoberturas.java +0 -0
- {sourcecode-1.9.0 → sourcecode-1.11.0}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/autocoberturas/infrastructure/rest/AutocoberturasRestController.java +0 -0
- {sourcecode-1.9.0 → sourcecode-1.11.0}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/calendarioTrabajador/application/service/FindCalendarioTrabajadorService.java +0 -0
- {sourcecode-1.9.0 → sourcecode-1.11.0}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/calendarioTrabajador/domain/entities/CalendarioTrabajador.java +0 -0
- {sourcecode-1.9.0 → sourcecode-1.11.0}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/calendarioTrabajador/infrastructure/rest/CalendarioTrabajadorRestController.java +0 -0
- {sourcecode-1.9.0 → sourcecode-1.11.0}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/departamento/application/service/FindDepartamentoService.java +0 -0
- {sourcecode-1.9.0 → sourcecode-1.11.0}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/departamento/domain/entities/Departamento.java +0 -0
- {sourcecode-1.9.0 → sourcecode-1.11.0}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/departamento/infrastructure/rest/DepartamentoRestController.java +0 -0
- {sourcecode-1.9.0 → sourcecode-1.11.0}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/empleado/application/service/FindEmpleadoService.java +0 -0
- {sourcecode-1.9.0 → sourcecode-1.11.0}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/empleado/domain/entities/Empleado.java +0 -0
- {sourcecode-1.9.0 → sourcecode-1.11.0}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/empleado/infrastructure/rest/EmpleadoRestController.java +0 -0
- {sourcecode-1.9.0 → sourcecode-1.11.0}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/demo/DemoApplication.java +0 -0
- {sourcecode-1.9.0 → sourcecode-1.11.0}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/demo/domain/Health.java +0 -0
- {sourcecode-1.9.0 → sourcecode-1.11.0}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/demo/mapper/HealthMapper.java +0 -0
- {sourcecode-1.9.0 → sourcecode-1.11.0}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/demo/repository/HealthRepository.java +0 -0
- {sourcecode-1.9.0 → sourcecode-1.11.0}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/demo/service/HealthService.java +0 -0
- {sourcecode-1.9.0 → sourcecode-1.11.0}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/demo/web/HealthRestController.java +0 -0
- {sourcecode-1.9.0 → sourcecode-1.11.0}/tests/fixtures/spring_boot_minimal/src/main/resources/application-dev.yml +0 -0
- {sourcecode-1.9.0 → sourcecode-1.11.0}/tests/fixtures/spring_boot_minimal/src/main/resources/application.yml +0 -0
- {sourcecode-1.9.0 → sourcecode-1.11.0}/tests/test_architecture_analyzer.py +0 -0
- {sourcecode-1.9.0 → sourcecode-1.11.0}/tests/test_architecture_summary.py +0 -0
- {sourcecode-1.9.0 → sourcecode-1.11.0}/tests/test_ast_extractor.py +0 -0
- {sourcecode-1.9.0 → sourcecode-1.11.0}/tests/test_block1_reliability.py +0 -0
- {sourcecode-1.9.0 → sourcecode-1.11.0}/tests/test_block2_coverage.py +0 -0
- {sourcecode-1.9.0 → sourcecode-1.11.0}/tests/test_block5_quality.py +0 -0
- {sourcecode-1.9.0 → sourcecode-1.11.0}/tests/test_bug_fixes_v16.py +0 -0
- {sourcecode-1.9.0 → sourcecode-1.11.0}/tests/test_classifier.py +0 -0
- {sourcecode-1.9.0 → sourcecode-1.11.0}/tests/test_cli.py +0 -0
- {sourcecode-1.9.0 → sourcecode-1.11.0}/tests/test_code_notes_analyzer.py +0 -0
- {sourcecode-1.9.0 → sourcecode-1.11.0}/tests/test_context_scorer.py +0 -0
- {sourcecode-1.9.0 → sourcecode-1.11.0}/tests/test_contract_pipeline.py +0 -0
- {sourcecode-1.9.0 → sourcecode-1.11.0}/tests/test_coverage_parser.py +0 -0
- {sourcecode-1.9.0 → sourcecode-1.11.0}/tests/test_cross_consistency.py +0 -0
- {sourcecode-1.9.0 → sourcecode-1.11.0}/tests/test_dependency_analyzer_node_python.py +0 -0
- {sourcecode-1.9.0 → sourcecode-1.11.0}/tests/test_dependency_analyzer_polyglot.py +0 -0
- {sourcecode-1.9.0 → sourcecode-1.11.0}/tests/test_dependency_schema.py +0 -0
- {sourcecode-1.9.0 → sourcecode-1.11.0}/tests/test_detector_dotnet.py +0 -0
- {sourcecode-1.9.0 → sourcecode-1.11.0}/tests/test_detector_go_rust_java.py +0 -0
- {sourcecode-1.9.0 → sourcecode-1.11.0}/tests/test_detector_nodejs.py +0 -0
- {sourcecode-1.9.0 → sourcecode-1.11.0}/tests/test_detector_php_ruby_dart.py +0 -0
- {sourcecode-1.9.0 → sourcecode-1.11.0}/tests/test_detector_python.py +0 -0
- {sourcecode-1.9.0 → sourcecode-1.11.0}/tests/test_detector_universal_managed.py +0 -0
- {sourcecode-1.9.0 → sourcecode-1.11.0}/tests/test_detector_universal_systems.py +0 -0
- {sourcecode-1.9.0 → sourcecode-1.11.0}/tests/test_detectors_base.py +0 -0
- {sourcecode-1.9.0 → sourcecode-1.11.0}/tests/test_doc_analyzer_jsdom.py +0 -0
- {sourcecode-1.9.0 → sourcecode-1.11.0}/tests/test_doc_analyzer_python.py +0 -0
- {sourcecode-1.9.0 → sourcecode-1.11.0}/tests/test_graph_analyzer_polyglot.py +0 -0
- {sourcecode-1.9.0 → sourcecode-1.11.0}/tests/test_graph_analyzer_python_node.py +0 -0
- {sourcecode-1.9.0 → sourcecode-1.11.0}/tests/test_graph_schema.py +0 -0
- {sourcecode-1.9.0 → sourcecode-1.11.0}/tests/test_hybrid_inference.py +0 -0
- {sourcecode-1.9.0 → sourcecode-1.11.0}/tests/test_integration.py +0 -0
- {sourcecode-1.9.0 → sourcecode-1.11.0}/tests/test_integration_dependencies.py +0 -0
- {sourcecode-1.9.0 → sourcecode-1.11.0}/tests/test_integration_detection.py +0 -0
- {sourcecode-1.9.0 → sourcecode-1.11.0}/tests/test_integration_docs.py +0 -0
- {sourcecode-1.9.0 → sourcecode-1.11.0}/tests/test_integration_graph_modules.py +0 -0
- {sourcecode-1.9.0 → sourcecode-1.11.0}/tests/test_integration_lqn.py +0 -0
- {sourcecode-1.9.0 → sourcecode-1.11.0}/tests/test_integration_metrics.py +0 -0
- {sourcecode-1.9.0 → sourcecode-1.11.0}/tests/test_integration_multistack.py +0 -0
- {sourcecode-1.9.0 → sourcecode-1.11.0}/tests/test_integration_semantics.py +0 -0
- {sourcecode-1.9.0 → sourcecode-1.11.0}/tests/test_integration_universal.py +0 -0
- {sourcecode-1.9.0 → sourcecode-1.11.0}/tests/test_java_spring_integration.py +0 -0
- {sourcecode-1.9.0 → sourcecode-1.11.0}/tests/test_metrics_analyzer.py +0 -0
- {sourcecode-1.9.0 → sourcecode-1.11.0}/tests/test_packaging.py +0 -0
- {sourcecode-1.9.0 → sourcecode-1.11.0}/tests/test_phase1_improvements.py +0 -0
- {sourcecode-1.9.0 → sourcecode-1.11.0}/tests/test_pipeline_integrity.py +0 -0
- {sourcecode-1.9.0 → sourcecode-1.11.0}/tests/test_real_projects.py +0 -0
- {sourcecode-1.9.0 → sourcecode-1.11.0}/tests/test_redactor.py +0 -0
- {sourcecode-1.9.0 → sourcecode-1.11.0}/tests/test_scanner.py +0 -0
- {sourcecode-1.9.0 → sourcecode-1.11.0}/tests/test_schema.py +0 -0
- {sourcecode-1.9.0 → sourcecode-1.11.0}/tests/test_schema_normalization.py +0 -0
- {sourcecode-1.9.0 → sourcecode-1.11.0}/tests/test_semantic_analyzer_node.py +0 -0
- {sourcecode-1.9.0 → sourcecode-1.11.0}/tests/test_semantic_analyzer_python.py +0 -0
- {sourcecode-1.9.0 → sourcecode-1.11.0}/tests/test_semantic_import_resolution.py +0 -0
- {sourcecode-1.9.0 → sourcecode-1.11.0}/tests/test_semantic_schema.py +0 -0
- {sourcecode-1.9.0 → sourcecode-1.11.0}/tests/test_signal_hierarchy.py +0 -0
- {sourcecode-1.9.0 → sourcecode-1.11.0}/tests/test_summarizer.py +0 -0
- {sourcecode-1.9.0 → sourcecode-1.11.0}/tests/test_telemetry.py +0 -0
- {sourcecode-1.9.0 → sourcecode-1.11.0}/tests/test_workspace_analyzer.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: sourcecode
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.11.0
|
|
4
4
|
Summary: Deterministic codebase context for AI coding agents
|
|
5
5
|
License: Apache License
|
|
6
6
|
Version 2.0, January 2004
|
|
@@ -357,5 +357,3 @@ Generates task-specific context for AI agents.
|
|
|
357
357
|
| `refactor` | Structural problems, improvement opportunities | 🧪 EXP |
|
|
358
358
|
| `generate-tests` | Files without tests, coverage gap analysis | 🧪 EXP |
|
|
359
359
|
| `review-pr` | Changed files + architectural impact | 🧪 EXP |
|
|
360
|
-
|
|
361
|
-
...
|
|
@@ -138,5 +138,3 @@ Generates task-specific context for AI agents.
|
|
|
138
138
|
| `refactor` | Structural problems, improvement opportunities | 🧪 EXP |
|
|
139
139
|
| `generate-tests` | Files without tests, coverage gap analysis | 🧪 EXP |
|
|
140
140
|
| `review-pr` | Changed files + architectural impact | 🧪 EXP |
|
|
141
|
-
|
|
142
|
-
...
|
|
@@ -629,6 +629,10 @@ def main(
|
|
|
629
629
|
)
|
|
630
630
|
raise typer.Exit(code=1)
|
|
631
631
|
|
|
632
|
+
if symbol is not None and not symbol.strip():
|
|
633
|
+
typer.echo("symbol query cannot be empty", err=True)
|
|
634
|
+
raise typer.Exit(code=2)
|
|
635
|
+
|
|
632
636
|
if symbol and mode not in ("contract", "standard"):
|
|
633
637
|
typer.echo(
|
|
634
638
|
f"Error: --symbol requires --mode contract or standard (got '{mode}'). "
|
|
@@ -563,6 +563,25 @@ class TaskContextBuilder:
|
|
|
563
563
|
except Exception:
|
|
564
564
|
pass
|
|
565
565
|
|
|
566
|
+
# ── 5c. review-pr suspected_areas (needs git uncommitted_files) ──────
|
|
567
|
+
if task_name == "review-pr" and spec.enable_code_notes:
|
|
568
|
+
pr_areas: dict[str, int] = {}
|
|
569
|
+
for path in uncommitted_files:
|
|
570
|
+
pr_areas[path] = pr_areas.get(path, 0) + 10
|
|
571
|
+
review_kinds = {"FIXME", "TODO", "BUG", "HACK"}
|
|
572
|
+
for note in cn_notes_for_ranking:
|
|
573
|
+
if note.kind in review_kinds:
|
|
574
|
+
pr_areas[note.path] = pr_areas.get(note.path, 0) + 1
|
|
575
|
+
_BOOST_STEMS = ("Controller", "Service", "Repository", "Mapper", "Filter", "Security")
|
|
576
|
+
for path in all_paths:
|
|
577
|
+
stem = Path(path).stem
|
|
578
|
+
if any(k in stem for k in _BOOST_STEMS):
|
|
579
|
+
pr_areas[path] = pr_areas.get(path, 0) + 2
|
|
580
|
+
suspected_areas = [
|
|
581
|
+
p for p, _ in sorted(pr_areas.items(), key=lambda x: -x[1])[:8]
|
|
582
|
+
if not self._is_test(p)
|
|
583
|
+
]
|
|
584
|
+
|
|
566
585
|
# ── 6. Rank files ──────────────────────────────────────────────────
|
|
567
586
|
entry_set = {ep.path for ep in entry_points}
|
|
568
587
|
test_set = {p for p in all_paths if self._is_test(p)}
|
|
@@ -38,6 +38,19 @@ _MONOREPO_PKGS_CAP = 8 # max workspace/runtime packages shown
|
|
|
38
38
|
_KEY_DEPS_CAP = 50 # max key dependencies shown
|
|
39
39
|
_CODE_NOTES_CAP = 15 # max code notes in default output
|
|
40
40
|
_ENV_MAP_CAP = 15 # max env var entries in default output
|
|
41
|
+
_MAX_DEFAULT_CONTRACTS = 20 # max contracts in default/standard contract output
|
|
42
|
+
_MAX_HARD_SIGNALS_DEFAULT = 20 # max hard_signals entries in default output
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
def _cap_contracts_for_output(
|
|
46
|
+
contracts: list[Any],
|
|
47
|
+
max_count: int = _MAX_DEFAULT_CONTRACTS,
|
|
48
|
+
) -> tuple[list[Any], dict[str, Any]]:
|
|
49
|
+
"""Sort contracts by relevance_score desc, cap to max_count, return (sampled, meta)."""
|
|
50
|
+
total = len(contracts)
|
|
51
|
+
sampled = sorted(contracts, key=lambda c: getattr(c, "relevance_score", 0.0), reverse=True)[:max_count]
|
|
52
|
+
meta: dict[str, Any] = {"total": total, "shown": len(sampled), "truncated": total > max_count}
|
|
53
|
+
return sampled, meta
|
|
41
54
|
|
|
42
55
|
|
|
43
56
|
def to_json(sm: SourceMap | dict[str, Any], indent: int = 2) -> str:
|
|
@@ -191,6 +204,178 @@ def _dep_import_key(name: str) -> str:
|
|
|
191
204
|
return lowered.split("/")[0].replace("_", "-")
|
|
192
205
|
|
|
193
206
|
|
|
207
|
+
# ---------------------------------------------------------------------------
|
|
208
|
+
# Java/Spring compact-mode helpers (v1.10.0)
|
|
209
|
+
# ---------------------------------------------------------------------------
|
|
210
|
+
|
|
211
|
+
def _compact_git_context(sm: "SourceMap") -> "Optional[dict[str, Any]]":
|
|
212
|
+
"""Lightweight git_context for compact/agent output. Top-5 hotspots only."""
|
|
213
|
+
gc = sm.git_context
|
|
214
|
+
if gc is None or not gc.requested:
|
|
215
|
+
return None
|
|
216
|
+
_bad = {"no_git_repo", "git_not_found", "git_timeout"}
|
|
217
|
+
if _bad & set(gc.limitations):
|
|
218
|
+
return None
|
|
219
|
+
ctx: dict[str, Any] = {}
|
|
220
|
+
if gc.branch:
|
|
221
|
+
ctx["branch"] = gc.branch
|
|
222
|
+
if gc.uncommitted_changes is not None:
|
|
223
|
+
uc = gc.uncommitted_changes
|
|
224
|
+
ctx["uncommitted_files"] = len(uc.staged) + len(uc.unstaged) + len(uc.untracked)
|
|
225
|
+
if gc.change_hotspots:
|
|
226
|
+
ctx["top_hotspots"] = [
|
|
227
|
+
{"file": h.file, "commits": h.commit_count}
|
|
228
|
+
for h in gc.change_hotspots[:5]
|
|
229
|
+
]
|
|
230
|
+
return ctx if ctx else None
|
|
231
|
+
|
|
232
|
+
|
|
233
|
+
def _dep_risk_flags(name: str, version: "Optional[str]") -> list[str]:
|
|
234
|
+
"""Static heuristic risk flags for a single dependency. No external lookups."""
|
|
235
|
+
flags: list[str] = []
|
|
236
|
+
nl = name.lower()
|
|
237
|
+
if "spring-boot" in nl or "spring.boot" in nl:
|
|
238
|
+
if version and version.startswith("2."):
|
|
239
|
+
flags.append("spring-boot-2.x-eol")
|
|
240
|
+
if nl.startswith("javax.") or nl == "javax":
|
|
241
|
+
flags.append("javax-to-jakarta-migration-risk")
|
|
242
|
+
if "ojdbc" in nl or nl in {"com.oracle.database.jdbc", "oracle.jdbc.driver.oracledriver"}:
|
|
243
|
+
flags.append("oracle-vendor-lock")
|
|
244
|
+
return flags
|
|
245
|
+
|
|
246
|
+
|
|
247
|
+
def _project_deployment_risks(sm: "SourceMap") -> list[str]:
|
|
248
|
+
"""Project-level deployment risk flags derived from Java version and app server."""
|
|
249
|
+
risks: list[str] = []
|
|
250
|
+
lv = sm.language_version or ""
|
|
251
|
+
if lv in ("1.8", "8", "1.7", "7"):
|
|
252
|
+
risks.append("legacy-java-runtime")
|
|
253
|
+
if getattr(sm, "app_server_hint", None) == "weblogic" and getattr(sm, "packaging", None) == "war":
|
|
254
|
+
risks.append("legacy-app-server-deployment")
|
|
255
|
+
return risks
|
|
256
|
+
|
|
257
|
+
|
|
258
|
+
def _mybatis_pairing(sm: "SourceMap") -> "Optional[dict[str, Any]]":
|
|
259
|
+
"""Lightweight MyBatis mapper interface <-> XML file pairing from file_paths."""
|
|
260
|
+
from pathlib import Path as _Path
|
|
261
|
+
has_mybatis = any(
|
|
262
|
+
any(f.name.lower() == "mybatis" for f in s.frameworks)
|
|
263
|
+
for s in sm.stacks
|
|
264
|
+
)
|
|
265
|
+
if not has_mybatis:
|
|
266
|
+
return None
|
|
267
|
+
non_test = [p for p in sm.file_paths if "/test/" not in p and "/tests/" not in p]
|
|
268
|
+
mapper_interfaces = [p for p in non_test if p.endswith("Mapper.java")]
|
|
269
|
+
xml_files = [p for p in sm.file_paths if p.endswith("Mapper.xml")]
|
|
270
|
+
interface_index = {_Path(p).stem: p for p in mapper_interfaces}
|
|
271
|
+
xml_index = {_Path(p).stem: p for p in xml_files}
|
|
272
|
+
orphan_xml = [xml_index[s] for s in xml_index if s not in interface_index]
|
|
273
|
+
missing_xml = [s for s in interface_index if s not in xml_index]
|
|
274
|
+
result: dict[str, Any] = {
|
|
275
|
+
"mapper_interfaces": len(mapper_interfaces),
|
|
276
|
+
"xml_files": len(xml_files),
|
|
277
|
+
}
|
|
278
|
+
if orphan_xml:
|
|
279
|
+
result["orphan_xml"] = orphan_xml[:5]
|
|
280
|
+
if missing_xml:
|
|
281
|
+
result["missing_xml"] = missing_xml[:5]
|
|
282
|
+
return result
|
|
283
|
+
|
|
284
|
+
|
|
285
|
+
def _security_surface_from_eps(eps: list) -> "Optional[dict[str, Any]]":
|
|
286
|
+
"""Extract @M3FiltroSeguridad resource names from entry point evidence strings."""
|
|
287
|
+
import re as _re
|
|
288
|
+
_NOMBRE_RE = _re.compile(r"nombreRecurso=[\"']([^\"']+)[\"']")
|
|
289
|
+
resource_names: list[str] = []
|
|
290
|
+
seen: set[str] = set()
|
|
291
|
+
for ep in eps:
|
|
292
|
+
evidence = getattr(ep, "evidence", None)
|
|
293
|
+
if not evidence:
|
|
294
|
+
continue
|
|
295
|
+
for m in _NOMBRE_RE.finditer(evidence):
|
|
296
|
+
nm = m.group(1)
|
|
297
|
+
if nm and nm not in seen:
|
|
298
|
+
seen.add(nm)
|
|
299
|
+
resource_names.append(nm)
|
|
300
|
+
return {"resource_names": resource_names} if resource_names else None
|
|
301
|
+
|
|
302
|
+
|
|
303
|
+
def _bootstrap_structured(eps: list) -> "Optional[dict[str, Any]]":
|
|
304
|
+
"""Separate Java entry points into bootstrap / security / controllers groups."""
|
|
305
|
+
from pathlib import Path as _Path
|
|
306
|
+
bootstrap: list[str] = []
|
|
307
|
+
security: list[str] = []
|
|
308
|
+
controllers: list[dict] = []
|
|
309
|
+
seen_b: set[str] = set()
|
|
310
|
+
seen_s: set[str] = set()
|
|
311
|
+
seen_c: set[str] = set()
|
|
312
|
+
|
|
313
|
+
for ep in eps:
|
|
314
|
+
path = getattr(ep, "path", "")
|
|
315
|
+
kind = getattr(ep, "kind", "")
|
|
316
|
+
stem = _Path(path).stem
|
|
317
|
+
|
|
318
|
+
if kind == "application" or any(k in stem for k in ("Application", "Main", "Initializer", "Bootstrap")):
|
|
319
|
+
if path not in seen_b:
|
|
320
|
+
seen_b.add(path)
|
|
321
|
+
bootstrap.append(path)
|
|
322
|
+
elif kind == "filter" or any(k in stem for k in ("Filter", "Security", "Auth", "Jwt", "WebSecurity")):
|
|
323
|
+
if path not in seen_s:
|
|
324
|
+
seen_s.add(path)
|
|
325
|
+
security.append(path)
|
|
326
|
+
elif kind in ("rest_controller", "mvc_controller"):
|
|
327
|
+
if path not in seen_c:
|
|
328
|
+
seen_c.add(path)
|
|
329
|
+
item: dict[str, Any] = {"path": path}
|
|
330
|
+
http_path = getattr(ep, "http_path", None)
|
|
331
|
+
if http_path:
|
|
332
|
+
item["http_path"] = http_path
|
|
333
|
+
controllers.append(item)
|
|
334
|
+
|
|
335
|
+
if not bootstrap and not security:
|
|
336
|
+
return None
|
|
337
|
+
|
|
338
|
+
result: dict[str, Any] = {}
|
|
339
|
+
if bootstrap:
|
|
340
|
+
result["bootstrap"] = bootstrap
|
|
341
|
+
if security:
|
|
342
|
+
result["security"] = security
|
|
343
|
+
if controllers:
|
|
344
|
+
result["controllers"] = {
|
|
345
|
+
"count": len(controllers),
|
|
346
|
+
"sample": [{"path": c["path"]} for c in controllers[:5]],
|
|
347
|
+
}
|
|
348
|
+
return result
|
|
349
|
+
|
|
350
|
+
|
|
351
|
+
def _lightweight_arch_pattern(sm: "SourceMap") -> "Optional[dict[str, Any]]":
|
|
352
|
+
"""Heuristic architecture pattern from directory names alone."""
|
|
353
|
+
if not sm.file_paths:
|
|
354
|
+
return None
|
|
355
|
+
dir_names: set[str] = set()
|
|
356
|
+
for p in sm.file_paths:
|
|
357
|
+
for part in p.replace("\\", "/").split("/")[:-1]:
|
|
358
|
+
dir_names.add(part.lower())
|
|
359
|
+
|
|
360
|
+
has_controller = bool({"controller", "controllers", "api", "rest", "web", "handler", "handlers"} & dir_names)
|
|
361
|
+
has_service = bool({"service", "services", "usecase", "usecases", "application"} & dir_names)
|
|
362
|
+
has_repository = bool({"repository", "repositories", "repo", "repos", "dao", "persistence"} & dir_names)
|
|
363
|
+
has_domain = bool({"domain", "domains", "core", "model", "models", "entity", "entities"} & dir_names)
|
|
364
|
+
has_infra = bool({"infrastructure", "infra", "adapter", "adapters"} & dir_names)
|
|
365
|
+
|
|
366
|
+
if has_controller and has_service and has_repository and has_domain:
|
|
367
|
+
return {"pattern": "ddd-layered", "confidence": 0.72 if has_infra else 0.55}
|
|
368
|
+
if bool({"ports", "port"} & dir_names) and bool({"adapter", "adapters"} & dir_names):
|
|
369
|
+
return {"pattern": "hexagonal-like", "confidence": 0.65}
|
|
370
|
+
if has_controller and bool({"model", "models", "entity", "entities"} & dir_names):
|
|
371
|
+
return {"pattern": "mvc", "confidence": 0.55}
|
|
372
|
+
if has_controller and has_service and has_repository:
|
|
373
|
+
return {"pattern": "layered", "confidence": 0.70}
|
|
374
|
+
if has_controller and has_service:
|
|
375
|
+
return {"pattern": "layered", "confidence": 0.42}
|
|
376
|
+
return None
|
|
377
|
+
|
|
378
|
+
|
|
194
379
|
def _file_relevance(sm: SourceMap, *, limit: int = _FILE_RELEVANCE_LIMIT) -> list[dict[str, Any]]:
|
|
195
380
|
from sourcecode.ranking_engine import RankingEngine
|
|
196
381
|
|
|
@@ -300,7 +485,20 @@ def _architecture_context(sm: SourceMap) -> dict[str, Any]:
|
|
|
300
485
|
arch = sm.architecture
|
|
301
486
|
if arch is not None and arch.requested:
|
|
302
487
|
pattern = arch.pattern if arch.pattern not in (None, "unknown", "flat") else None
|
|
303
|
-
|
|
488
|
+
if not pattern:
|
|
489
|
+
_hint = _lightweight_arch_pattern(sm)
|
|
490
|
+
if _hint:
|
|
491
|
+
ctx: dict[str, Any] = {
|
|
492
|
+
"summary": sm.architecture_summary,
|
|
493
|
+
"pattern": _hint["pattern"],
|
|
494
|
+
"confidence": arch.confidence,
|
|
495
|
+
"pattern_confidence": _hint["confidence"],
|
|
496
|
+
"method": arch.method,
|
|
497
|
+
}
|
|
498
|
+
if arch.limitations:
|
|
499
|
+
ctx["limitations"] = arch.limitations
|
|
500
|
+
return ctx
|
|
501
|
+
ctx = {
|
|
304
502
|
"summary": sm.architecture_summary,
|
|
305
503
|
"pattern": pattern or "insufficient_evidence",
|
|
306
504
|
"confidence": arch.confidence,
|
|
@@ -326,6 +524,18 @@ def _architecture_context(sm: SourceMap) -> dict[str, Any]:
|
|
|
326
524
|
if arch.limitations:
|
|
327
525
|
ctx["limitations"] = arch.limitations
|
|
328
526
|
return ctx
|
|
527
|
+
_hint = _lightweight_arch_pattern(sm)
|
|
528
|
+
if _hint:
|
|
529
|
+
return {
|
|
530
|
+
"summary": sm.architecture_summary,
|
|
531
|
+
"pattern": _hint["pattern"],
|
|
532
|
+
"pattern_confidence": _hint["confidence"],
|
|
533
|
+
"confidence": "low",
|
|
534
|
+
"method": "filesystem_heuristic",
|
|
535
|
+
"limitations": [
|
|
536
|
+
"architecture analyzer not requested; pattern inferred from directory names only"
|
|
537
|
+
],
|
|
538
|
+
}
|
|
329
539
|
return {
|
|
330
540
|
"summary": sm.architecture_summary,
|
|
331
541
|
"pattern": "insufficient_evidence",
|
|
@@ -382,18 +592,23 @@ def compact_view(sm: SourceMap, *, no_tree: bool = False) -> dict[str, Any]:
|
|
|
382
592
|
|
|
383
593
|
Excludes: file_tree, raw dependency lists, docs, module_graph, verbose metadata.
|
|
384
594
|
"""
|
|
385
|
-
# Key dependencies — name + version + role
|
|
595
|
+
# Key dependencies — name + version + role + risk_flags
|
|
386
596
|
key_deps: Any = None
|
|
387
597
|
if sm.dependency_summary is not None and sm.dependency_summary.requested:
|
|
388
|
-
key_deps = [
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
if
|
|
396
|
-
|
|
598
|
+
key_deps = []
|
|
599
|
+
for d in sm.key_dependencies:
|
|
600
|
+
if (d.role or "unknown") not in _PRODUCTION_DEP_ROLES or d.scope in {"dev"}:
|
|
601
|
+
continue
|
|
602
|
+
entry: dict[str, Any] = {"name": d.name}
|
|
603
|
+
if d.declared_version:
|
|
604
|
+
entry["version"] = d.declared_version
|
|
605
|
+
if d.role and d.role != "runtime":
|
|
606
|
+
entry["role"] = d.role
|
|
607
|
+
flags = _dep_risk_flags(d.name, d.declared_version)
|
|
608
|
+
if flags:
|
|
609
|
+
entry["risk_flags"] = flags
|
|
610
|
+
key_deps.append(entry)
|
|
611
|
+
key_deps = key_deps[:_KEY_DEPS_CAP]
|
|
397
612
|
|
|
398
613
|
# Dependency summary — requested flag + count + source only
|
|
399
614
|
dep_summary_dict: Any = None
|
|
@@ -452,16 +667,20 @@ def compact_view(sm: SourceMap, *, no_tree: bool = False) -> dict[str, Any]:
|
|
|
452
667
|
for n in _sorted_notes[:_CODE_NOTES_CAP]
|
|
453
668
|
]
|
|
454
669
|
|
|
455
|
-
# Entry points —
|
|
670
|
+
# Entry points — bootstrap-prioritized; structured when bootstrap classes detected
|
|
456
671
|
ep_groups = _entry_point_groups(sm.entry_points)
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
672
|
+
_bootstrap_struct = _bootstrap_structured(sm.entry_points)
|
|
673
|
+
if _bootstrap_struct:
|
|
674
|
+
entry_points_compact: Any = _bootstrap_struct
|
|
675
|
+
else:
|
|
676
|
+
entry_points_compact = [
|
|
677
|
+
{
|
|
678
|
+
"path": ep["path"],
|
|
679
|
+
**({"kind": ep["kind"]} if ep.get("kind") else {}),
|
|
680
|
+
**({"confidence": ep["confidence"]} if ep.get("confidence") else {}),
|
|
681
|
+
}
|
|
682
|
+
for ep in ep_groups["production"][:_EP_PRODUCTION_CAP]
|
|
683
|
+
]
|
|
465
684
|
|
|
466
685
|
# Stacks — name + method + confidence + frameworks (names only)
|
|
467
686
|
stacks_compact = [
|
|
@@ -492,6 +711,22 @@ def compact_view(sm: SourceMap, *, no_tree: bool = False) -> dict[str, Any]:
|
|
|
492
711
|
for g in sm.analysis_gaps
|
|
493
712
|
]
|
|
494
713
|
|
|
714
|
+
# Java/Spring operational context
|
|
715
|
+
_language_version = getattr(sm, "language_version", None)
|
|
716
|
+
_packaging = getattr(sm, "packaging", None)
|
|
717
|
+
_app_server = getattr(sm, "app_server_hint", None)
|
|
718
|
+
_deployment: Any = None
|
|
719
|
+
if _packaging or _app_server:
|
|
720
|
+
_deployment = {}
|
|
721
|
+
if _packaging:
|
|
722
|
+
_deployment["packaging"] = _packaging
|
|
723
|
+
if _app_server:
|
|
724
|
+
_deployment["app_server_hint"] = _app_server
|
|
725
|
+
_deploy_risks = _project_deployment_risks(sm)
|
|
726
|
+
_security_surface = _security_surface_from_eps(sm.entry_points)
|
|
727
|
+
_mybatis = _mybatis_pairing(sm)
|
|
728
|
+
_git_ctx = _compact_git_context(sm)
|
|
729
|
+
|
|
495
730
|
result: dict[str, Any] = {
|
|
496
731
|
"schema_version": sm.metadata.schema_version,
|
|
497
732
|
"project_type": sm.project_type,
|
|
@@ -508,6 +743,18 @@ def compact_view(sm: SourceMap, *, no_tree: bool = False) -> dict[str, Any]:
|
|
|
508
743
|
"confidence_summary": conf_dict,
|
|
509
744
|
"analysis_gaps": gaps_list,
|
|
510
745
|
}
|
|
746
|
+
if _language_version:
|
|
747
|
+
result["language_version"] = _language_version
|
|
748
|
+
if _deployment:
|
|
749
|
+
result["deployment"] = _deployment
|
|
750
|
+
if _deploy_risks:
|
|
751
|
+
result["deployment_risks"] = _deploy_risks
|
|
752
|
+
if _security_surface:
|
|
753
|
+
result["security_surface"] = _security_surface
|
|
754
|
+
if _mybatis:
|
|
755
|
+
result["mybatis"] = _mybatis
|
|
756
|
+
if _git_ctx:
|
|
757
|
+
result["git_context"] = _git_ctx
|
|
511
758
|
_always_include = {"project_type", "project_summary", "architecture_summary", "dependency_summary"}
|
|
512
759
|
return {k: v for k, v in result.items() if v is not None or k in _always_include}
|
|
513
760
|
|
|
@@ -825,15 +1072,34 @@ def agent_view(sm: SourceMap) -> dict[str, Any]:
|
|
|
825
1072
|
if secondary:
|
|
826
1073
|
project["secondary_stacks"] = sorted({s.stack for s in secondary})
|
|
827
1074
|
|
|
1075
|
+
# Java operational context in project block
|
|
1076
|
+
_lv = getattr(sm, "language_version", None)
|
|
1077
|
+
_pkg = getattr(sm, "packaging", None)
|
|
1078
|
+
_app_srv = getattr(sm, "app_server_hint", None)
|
|
1079
|
+
if _lv:
|
|
1080
|
+
project["language_version"] = _lv
|
|
1081
|
+
if _pkg or _app_srv:
|
|
1082
|
+
_depl: dict[str, Any] = {}
|
|
1083
|
+
if _pkg:
|
|
1084
|
+
_depl["packaging"] = _pkg
|
|
1085
|
+
if _app_srv:
|
|
1086
|
+
_depl["app_server_hint"] = _app_srv
|
|
1087
|
+
project["deployment"] = _depl
|
|
1088
|
+
_proj_risks = _project_deployment_risks(sm)
|
|
1089
|
+
if _proj_risks:
|
|
1090
|
+
project["deployment_risks"] = _proj_risks
|
|
1091
|
+
|
|
828
1092
|
result: dict[str, Any] = {"project": project}
|
|
829
1093
|
|
|
830
|
-
# ── 2. Entry points:
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
result["
|
|
1094
|
+
# ── 2. Entry points: bootstrap-prioritized, then production ─────────────
|
|
1095
|
+
_bs = _bootstrap_structured(sm.entry_points)
|
|
1096
|
+
if _bs:
|
|
1097
|
+
result["entry_points"] = _bs
|
|
1098
|
+
else:
|
|
1099
|
+
ep_groups = _entry_point_groups(sm.entry_points)
|
|
1100
|
+
result["entry_points"] = ep_groups["production"][:_EP_PRODUCTION_CAP]
|
|
1101
|
+
if ep_groups["development"]:
|
|
1102
|
+
result["development_entry_points"] = ep_groups["development"][:_EP_DEV_CAP]
|
|
837
1103
|
|
|
838
1104
|
# ── 3. Architecture ───────────────────────────────────────────────────────
|
|
839
1105
|
result["architecture"] = _architecture_context(sm)
|
|
@@ -863,17 +1129,21 @@ def agent_view(sm: SourceMap) -> dict[str, Any]:
|
|
|
863
1129
|
if dep_groups[dep_key]:
|
|
864
1130
|
result[dep_key] = dep_groups[dep_key][:_SECONDARY_DEPS_CAP]
|
|
865
1131
|
|
|
866
|
-
# Backward-compatible compact list, now production-only.
|
|
1132
|
+
# Backward-compatible compact list, now production-only, with risk_flags.
|
|
867
1133
|
production_key_deps = [
|
|
868
1134
|
d for d in sm.key_dependencies
|
|
869
1135
|
if (d.role or "unknown") in _PRODUCTION_DEP_ROLES and d.scope not in {"dev"}
|
|
870
1136
|
]
|
|
871
1137
|
if sm.dependency_summary and sm.dependency_summary.requested and production_key_deps:
|
|
872
1138
|
_dep_skip = {"parent", "manifest_path", "workspace", "source", "ecosystem"}
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
for d in
|
|
876
|
-
|
|
1139
|
+
_kd_list = []
|
|
1140
|
+
for d in production_key_deps[:_KEY_DEPS_CAP]:
|
|
1141
|
+
item = {k: v for k, v in asdict(d).items() if v is not None and k not in _dep_skip}
|
|
1142
|
+
flags = _dep_risk_flags(d.name, d.declared_version)
|
|
1143
|
+
if flags:
|
|
1144
|
+
item["risk_flags"] = flags
|
|
1145
|
+
_kd_list.append(item)
|
|
1146
|
+
result["key_dependencies"] = _kd_list
|
|
877
1147
|
|
|
878
1148
|
# ── 5. Signals — compact operational context ─────────────────────────────
|
|
879
1149
|
signals: dict[str, Any] = {}
|
|
@@ -945,9 +1215,22 @@ def agent_view(sm: SourceMap) -> dict[str, Any]:
|
|
|
945
1215
|
sem_info["hotspots"] = sem.hotspots[:10]
|
|
946
1216
|
signals["semantic_graph"] = sem_info
|
|
947
1217
|
|
|
1218
|
+
# Java/Spring: security surface and ORM structure
|
|
1219
|
+
_sec_surf = _security_surface_from_eps(sm.entry_points)
|
|
1220
|
+
if _sec_surf:
|
|
1221
|
+
signals["security_surface"] = _sec_surf
|
|
1222
|
+
_mb = _mybatis_pairing(sm)
|
|
1223
|
+
if _mb:
|
|
1224
|
+
signals["mybatis"] = _mb
|
|
1225
|
+
|
|
948
1226
|
if signals:
|
|
949
1227
|
result["signals"] = signals
|
|
950
1228
|
|
|
1229
|
+
# Git context — lightweight (top-5 hotspots, branch, uncommitted count)
|
|
1230
|
+
_gc = _compact_git_context(sm)
|
|
1231
|
+
if _gc:
|
|
1232
|
+
result["git_context"] = _gc
|
|
1233
|
+
|
|
951
1234
|
# ── 6. Confidence summary ─────────────────────────────────────────────────
|
|
952
1235
|
if sm.confidence_summary is not None:
|
|
953
1236
|
cs = sm.confidence_summary
|
|
@@ -1230,13 +1513,11 @@ def _contract_view_minimal(
|
|
|
1230
1513
|
if getattr(sm, "app_server_hint", None):
|
|
1231
1514
|
result["app_server_hint"] = sm.app_server_hint
|
|
1232
1515
|
|
|
1233
|
-
# Per-file contracts
|
|
1516
|
+
# Per-file contracts — capped to avoid token bloat on large projects
|
|
1234
1517
|
if contracts:
|
|
1235
|
-
|
|
1236
|
-
for c in
|
|
1237
|
-
|
|
1238
|
-
serialized.append(item)
|
|
1239
|
-
result["contracts"] = serialized
|
|
1518
|
+
_capped, _meta = _cap_contracts_for_output(contracts)
|
|
1519
|
+
result["contracts"] = [_serialize_contract_minimal(c) for c in _capped]
|
|
1520
|
+
result["contracts_meta"] = _meta
|
|
1240
1521
|
|
|
1241
1522
|
# Optional analysis sections — included when the analyzer explicitly ran
|
|
1242
1523
|
# (user passed --dependencies, --env-map, --code-notes, --git-context)
|
|
@@ -1587,10 +1868,11 @@ def _contract_view_standard(
|
|
|
1587
1868
|
"stack": sm.confidence_summary.stack_confidence,
|
|
1588
1869
|
}
|
|
1589
1870
|
|
|
1590
|
-
# Per-file contracts (full detail)
|
|
1871
|
+
# Per-file contracts (full detail) — capped to avoid token bloat on large projects
|
|
1591
1872
|
if contracts:
|
|
1873
|
+
_capped, _meta = _cap_contracts_for_output(contracts)
|
|
1592
1874
|
serialized: list[dict[str, Any]] = []
|
|
1593
|
-
for c in
|
|
1875
|
+
for c in _capped:
|
|
1594
1876
|
if getattr(c, "language", None) == "mybatis-xml":
|
|
1595
1877
|
item = _serialize_contract_mybatis_xml(c)
|
|
1596
1878
|
item["relevance_score"] = round(c.relevance_score, 3)
|
|
@@ -1646,6 +1928,7 @@ def _contract_view_standard(
|
|
|
1646
1928
|
item["method"] = c.extraction_method
|
|
1647
1929
|
serialized.append(item)
|
|
1648
1930
|
result["contracts"] = serialized
|
|
1931
|
+
result["contracts_meta"] = _meta
|
|
1649
1932
|
|
|
1650
1933
|
# Optional analysis sections (deep mode or when analyzers ran)
|
|
1651
1934
|
if include_optional:
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
package com.example.demo.config;
|
|
2
|
+
|
|
3
|
+
import org.springframework.boot.web.servlet.FilterRegistrationBean;
|
|
4
|
+
import org.springframework.context.annotation.Bean;
|
|
5
|
+
import org.springframework.context.annotation.Configuration;
|
|
6
|
+
|
|
7
|
+
@Configuration
|
|
8
|
+
public class FilterConfig {
|
|
9
|
+
|
|
10
|
+
@Bean
|
|
11
|
+
public FilterRegistrationBean<SecurityFilter> securityFilter() {
|
|
12
|
+
FilterRegistrationBean<SecurityFilter> bean = new FilterRegistrationBean<>();
|
|
13
|
+
bean.setFilter(new SecurityFilter());
|
|
14
|
+
bean.addUrlPatterns("/*");
|
|
15
|
+
return bean;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
package com.example.demo.web;
|
|
2
|
+
|
|
3
|
+
import org.springframework.web.bind.annotation.GetMapping;
|
|
4
|
+
import org.springframework.web.bind.annotation.RequestMapping;
|
|
5
|
+
import org.springframework.web.bind.annotation.RestController;
|
|
6
|
+
|
|
7
|
+
@RestController
|
|
8
|
+
@RequestMapping("/nominas")
|
|
9
|
+
@M3FiltroSeguridad(nombreRecurso = "nominas")
|
|
10
|
+
public class NominaRestController {
|
|
11
|
+
|
|
12
|
+
@GetMapping
|
|
13
|
+
public String list() {
|
|
14
|
+
return "[]";
|
|
15
|
+
}
|
|
16
|
+
}
|
sourcecode-1.11.0/tests/fixtures/spring_boot_minimal/src/main/resources/mapper/HealthMapper.xml
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
|
+
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
|
3
|
+
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
|
4
|
+
<mapper namespace="com.example.demo.mapper.HealthMapper">
|
|
5
|
+
<select id="findStatus" parameterType="long" resultType="String">
|
|
6
|
+
SELECT status FROM health WHERE id = #{id}
|
|
7
|
+
</select>
|
|
8
|
+
</mapper>
|