sourcecode 1.31.25__tar.gz → 1.31.27__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.31.27/.continue-here.md +73 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/PKG-INFO +3 -3
- {sourcecode-1.31.25 → sourcecode-1.31.27}/README.md +2 -2
- {sourcecode-1.31.25 → sourcecode-1.31.27}/pyproject.toml +1 -1
- {sourcecode-1.31.25 → sourcecode-1.31.27}/src/sourcecode/__init__.py +1 -1
- {sourcecode-1.31.25 → sourcecode-1.31.27}/src/sourcecode/canonical_ir.py +2 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/src/sourcecode/cli.py +7 -1
- {sourcecode-1.31.25 → sourcecode-1.31.27}/src/sourcecode/mcp/server.py +225 -71
- {sourcecode-1.31.25 → sourcecode-1.31.27}/src/sourcecode/repository_ir.py +71 -2
- {sourcecode-1.31.25 → sourcecode-1.31.27}/tests/test_enterprise_benchmarks.py +2 -2
- sourcecode-1.31.25/.continue-here.md +0 -99
- {sourcecode-1.31.25 → sourcecode-1.31.27}/.agents/skills/source-command-gsd-join-discord/SKILL.md +0 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/.agents/skills/source-command-gsd-review-backlog/SKILL.md +0 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/.agents/skills/source-command-gsd-workstreams/SKILL.md +0 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/.github/workflows/build-windows.yml +0 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/.gitignore +0 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/.ruff.toml +0 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/.sourcecode-cache/snapshot-3b5997a-fa5c742c.json +0 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/AUDIT_REAL_REPOS.md +0 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/AUDIT_v1.31.23.md +0 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/CHANGELOG.md +0 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/CONTRIBUTING.md +0 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/LICENSE +0 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/SECURITY.md +0 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/docs/PRODUCT_TIERS.md +0 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/docs/privacy.md +0 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/docs/schema.md +0 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/raw +0 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/run_cli.py +0 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/src/sourcecode/adaptive_scanner.py +0 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/src/sourcecode/architecture_analyzer.py +0 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/src/sourcecode/architecture_summary.py +0 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/src/sourcecode/ast_extractor.py +0 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/src/sourcecode/cache.py +0 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/src/sourcecode/classifier.py +0 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/src/sourcecode/code_notes_analyzer.py +0 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/src/sourcecode/confidence_analyzer.py +0 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/src/sourcecode/context_scorer.py +0 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/src/sourcecode/context_summarizer.py +0 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/src/sourcecode/contract_model.py +0 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/src/sourcecode/contract_pipeline.py +0 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/src/sourcecode/coverage_parser.py +0 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/src/sourcecode/dependency_analyzer.py +0 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/src/sourcecode/detectors/__init__.py +0 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/src/sourcecode/detectors/base.py +0 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/src/sourcecode/detectors/csproj_parser.py +0 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/src/sourcecode/detectors/dart.py +0 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/src/sourcecode/detectors/dotnet.py +0 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/src/sourcecode/detectors/elixir.py +0 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/src/sourcecode/detectors/go.py +0 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/src/sourcecode/detectors/heuristic.py +0 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/src/sourcecode/detectors/hybrid.py +0 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/src/sourcecode/detectors/java.py +0 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/src/sourcecode/detectors/jvm_ext.py +0 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/src/sourcecode/detectors/nodejs.py +0 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/src/sourcecode/detectors/parsers.py +0 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/src/sourcecode/detectors/php.py +0 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/src/sourcecode/detectors/project.py +0 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/src/sourcecode/detectors/python.py +0 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/src/sourcecode/detectors/ruby.py +0 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/src/sourcecode/detectors/rust.py +0 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/src/sourcecode/detectors/systems.py +0 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/src/sourcecode/detectors/terraform.py +0 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/src/sourcecode/detectors/tooling.py +0 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/src/sourcecode/doc_analyzer.py +0 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/src/sourcecode/entrypoint_classifier.py +0 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/src/sourcecode/env_analyzer.py +0 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/src/sourcecode/file_classifier.py +0 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/src/sourcecode/flow_analyzer.py +0 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/src/sourcecode/git_analyzer.py +0 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/src/sourcecode/graph_analyzer.py +0 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/src/sourcecode/mcp/__init__.py +0 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/src/sourcecode/mcp/onboarding/__init__.py +0 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/src/sourcecode/mcp/onboarding/applier.py +0 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/src/sourcecode/mcp/onboarding/backup.py +0 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/src/sourcecode/mcp/onboarding/detector.py +0 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/src/sourcecode/mcp/onboarding/planner.py +0 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/src/sourcecode/mcp/runner.py +0 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/src/sourcecode/metrics_analyzer.py +0 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/src/sourcecode/output_budget.py +0 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/src/sourcecode/path_filters.py +0 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/src/sourcecode/pr_comment_renderer.py +0 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/src/sourcecode/prepare_context.py +0 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/src/sourcecode/progress.py +0 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/src/sourcecode/ranking_engine.py +0 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/src/sourcecode/redactor.py +0 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/src/sourcecode/relevance_scorer.py +0 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/src/sourcecode/repo_classifier.py +0 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/src/sourcecode/runtime_classifier.py +0 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/src/sourcecode/scanner.py +0 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/src/sourcecode/schema.py +0 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/src/sourcecode/semantic_analyzer.py +0 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/src/sourcecode/serializer.py +0 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/src/sourcecode/summarizer.py +0 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/src/sourcecode/telemetry/__init__.py +0 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/src/sourcecode/telemetry/config.py +0 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/src/sourcecode/telemetry/consent.py +0 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/src/sourcecode/telemetry/events.py +0 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/src/sourcecode/telemetry/filters.py +0 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/src/sourcecode/telemetry/transport.py +0 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/src/sourcecode/tree_utils.py +0 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/src/sourcecode/workspace.py +0 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/tests/__init__.py +0 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/tests/conftest.py +0 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/tests/fixtures/coverage.xml +0 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/tests/fixtures/fastapi_app/pyproject.toml +0 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/tests/fixtures/fastapi_app/src/main.py +0 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/tests/fixtures/go_service/cmd/api/main.go +0 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/tests/fixtures/go_service/go.mod +0 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/tests/fixtures/jacoco.xml +0 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/tests/fixtures/latin1_sample.java +0 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/tests/fixtures/latin1_sample_iso.java +0 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/tests/fixtures/lcov.info +0 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/tests/fixtures/nextjs_app/app/page.tsx +0 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/tests/fixtures/nextjs_app/package.json +0 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/tests/fixtures/nextjs_app/pnpm-lock.yaml +0 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/tests/fixtures/pnpm_monorepo/apps/web/app/page.tsx +0 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/tests/fixtures/pnpm_monorepo/apps/web/package.json +0 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/tests/fixtures/pnpm_monorepo/packages/api/main.py +0 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/tests/fixtures/pnpm_monorepo/packages/api/pyproject.toml +0 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/tests/fixtures/pnpm_monorepo/pnpm-workspace.yaml +0 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/tests/fixtures/spring_boot_minimal/pom.xml +0 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/ausente/application/service/FindAusenteService.java +0 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/ausente/domain/entities/Ausente.java +0 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/ausente/infrastructure/rest/AusenteRestController.java +0 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/autocoberturas/application/service/FindAutocoberturasService.java +0 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/autocoberturas/domain/entities/Autocoberturas.java +0 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/autocoberturas/infrastructure/rest/AutocoberturasRestController.java +0 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/calendarioTrabajador/application/service/FindCalendarioTrabajadorService.java +0 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/calendarioTrabajador/domain/entities/CalendarioTrabajador.java +0 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/calendarioTrabajador/infrastructure/rest/CalendarioTrabajadorRestController.java +0 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/departamento/application/service/FindDepartamentoService.java +0 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/departamento/domain/entities/Departamento.java +0 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/departamento/infrastructure/rest/DepartamentoRestController.java +0 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/empleado/application/service/FindEmpleadoService.java +0 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/empleado/domain/entities/Empleado.java +0 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/empleado/infrastructure/rest/EmpleadoRestController.java +0 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/demo/DemoApplication.java +0 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/demo/config/FilterConfig.java +0 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/demo/domain/Health.java +0 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/demo/mapper/HealthMapper.java +0 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/demo/repository/HealthRepository.java +0 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/demo/service/HealthService.java +0 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/demo/web/HealthRestController.java +0 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/demo/web/NominaRestController.java +0 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/tests/fixtures/spring_boot_minimal/src/main/resources/application-dev.yml +0 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/tests/fixtures/spring_boot_minimal/src/main/resources/application.yml +0 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/tests/fixtures/spring_boot_minimal/src/main/resources/mapper/HealthMapper.xml +0 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/tests/test_architecture_analyzer.py +0 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/tests/test_architecture_summary.py +0 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/tests/test_ast_extractor.py +0 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/tests/test_audit_fixes.py +0 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/tests/test_audit_sas_v2.py +0 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/tests/test_block1_reliability.py +0 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/tests/test_block2_coverage.py +0 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/tests/test_block5_quality.py +0 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/tests/test_broadleaf_fixes.py +0 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/tests/test_bug_fixes_v1302.py +0 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/tests/test_bug_fixes_v13115.py +0 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/tests/test_bug_fixes_v1312.py +0 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/tests/test_bug_fixes_v13122.py +0 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/tests/test_bug_fixes_v1313.py +0 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/tests/test_bug_fixes_v1321.py +0 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/tests/test_bug_fixes_v16.py +0 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/tests/test_bug_fixes_v2.py +0 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/tests/test_cache.py +0 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/tests/test_canonical_ir.py +0 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/tests/test_classifier.py +0 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/tests/test_cli.py +0 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/tests/test_code_notes_analyzer.py +0 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/tests/test_context_scorer.py +0 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/tests/test_contract_pipeline.py +0 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/tests/test_coverage_parser.py +0 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/tests/test_cross_consistency.py +0 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/tests/test_dependency_analyzer_node_python.py +0 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/tests/test_dependency_analyzer_polyglot.py +0 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/tests/test_dependency_schema.py +0 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/tests/test_detector_dotnet.py +0 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/tests/test_detector_go_rust_java.py +0 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/tests/test_detector_nodejs.py +0 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/tests/test_detector_php_ruby_dart.py +0 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/tests/test_detector_python.py +0 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/tests/test_detector_universal_managed.py +0 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/tests/test_detector_universal_systems.py +0 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/tests/test_detectors_base.py +0 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/tests/test_doc_analyzer_jsdom.py +0 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/tests/test_doc_analyzer_python.py +0 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/tests/test_encoding_regression.py +0 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/tests/test_graph_analyzer_polyglot.py +0 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/tests/test_graph_analyzer_python_node.py +0 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/tests/test_graph_schema.py +0 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/tests/test_hybrid_inference.py +0 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/tests/test_integration.py +0 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/tests/test_integration_dependencies.py +0 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/tests/test_integration_detection.py +0 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/tests/test_integration_docs.py +0 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/tests/test_integration_graph_modules.py +0 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/tests/test_integration_lqn.py +0 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/tests/test_integration_metrics.py +0 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/tests/test_integration_multistack.py +0 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/tests/test_integration_semantics.py +0 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/tests/test_integration_universal.py +0 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/tests/test_java_spring_integration.py +0 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/tests/test_mcp_runner.py +0 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/tests/test_mcp_serve.py +0 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/tests/test_mcp_tools.py +0 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/tests/test_metrics_analyzer.py +0 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/tests/test_output_ux.py +0 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/tests/test_packaging.py +0 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/tests/test_phase1_improvements.py +0 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/tests/test_pipeline_integrity.py +0 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/tests/test_real_projects.py +0 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/tests/test_redactor.py +0 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/tests/test_repository_ir.py +0 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/tests/test_scanner.py +0 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/tests/test_schema.py +0 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/tests/test_schema_normalization.py +0 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/tests/test_scoring_calibration.py +0 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/tests/test_semantic_analyzer_node.py +0 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/tests/test_semantic_analyzer_python.py +0 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/tests/test_semantic_import_resolution.py +0 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/tests/test_semantic_schema.py +0 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/tests/test_signal_hierarchy.py +0 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/tests/test_summarizer.py +0 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/tests/test_surface_honesty.py +0 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/tests/test_task_differentiation.py +0 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/tests/test_telemetry.py +0 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/tests/test_v131_improvements.py +0 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/tests/test_v1_10_regressions.py +0 -0
- {sourcecode-1.31.25 → sourcecode-1.31.27}/tests/test_workspace_analyzer.py +0 -0
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
# Handoff — Sesión 31 (2026-05-26)
|
|
2
|
+
|
|
3
|
+
## Position
|
|
4
|
+
|
|
5
|
+
**Project:** sourcecode (atlas-cli)
|
|
6
|
+
**Activity:** Post-audit bug fixing — AUDIT_v1.31.23.md / P0 blockers
|
|
7
|
+
**Branch:** master
|
|
8
|
+
**Last commit:** e0fab96 — fix(mcp,cli): three P0 blockers — exit codes, Windows paths, timeout
|
|
9
|
+
**Tests:** 1590 passed, 3 skipped ✅
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
## Work Done This Session
|
|
14
|
+
|
|
15
|
+
### Session 31 (this session)
|
|
16
|
+
**Three P0 blockers fixed:**
|
|
17
|
+
|
|
18
|
+
**P0-1: Exit codes** (`cli.py`)
|
|
19
|
+
- `--compact --full` now exits 1 (was 2); all controlled errors → exit 1
|
|
20
|
+
- Updated `test_enterprise_benchmarks.py::test_compact_full_conflict_is_error` assertion 2→1
|
|
21
|
+
|
|
22
|
+
**P0-2: MCP Windows paths** (`mcp/server.py`)
|
|
23
|
+
- `_normalize_repo_path()`: MINGW `/c/Users/...` → `C:/Users/...`, backslash → forward slash
|
|
24
|
+
- Applied to all 13 tools that accept `repo_path`
|
|
25
|
+
- Each tool wrapped in `try/except Exception` → never exposes uncaught exception to stdio transport
|
|
26
|
+
- Forward-slash note added to `mcp status` and `mcp init` output
|
|
27
|
+
|
|
28
|
+
**P0-3: generate_tests_context timeout** (`mcp/server.py`)
|
|
29
|
+
- Bounded by `SOURCECODE_TESTS_TIMEOUT_MS` env var (default: 15 000 ms)
|
|
30
|
+
- Uses `concurrent.futures.wait([future], timeout=timeout_s)` for wall-clock limit
|
|
31
|
+
- Returns `{truncated: true, truncated_reason: "timeout_15s", files_analyzed: 0, results: []}` on timeout
|
|
32
|
+
- Normal repos complete well within limit (0.8s on atlas-cli itself)
|
|
33
|
+
|
|
34
|
+
---
|
|
35
|
+
|
|
36
|
+
## Remaining from AUDIT_v1.31.23.md
|
|
37
|
+
|
|
38
|
+
### P2 unfixed (section 13, items 6–18)
|
|
39
|
+
| # | Issue | File | Effort |
|
|
40
|
+
|---|---|---|---|
|
|
41
|
+
| P2-06 | `subsystem_summary.member_count` always 0 | cli.py modernize_cmd | Medium |
|
|
42
|
+
| P2-07 | `no_security_signal` → detect filter-based security → `security_model: "filter_based"` | repository_ir.py | Medium |
|
|
43
|
+
| P2-10 | `architecture.confidence` inconsistent between `--compact` and `--agent` | serializer.py | Low |
|
|
44
|
+
| P2-13 | `--no-cache` flag inconsistent across subcommands | cli.py | Medium |
|
|
45
|
+
| P2-14 | URLs in code_notes truncated (missing `https://bugs.` prefix) | code_notes_analyzer.py | Low (needs repro) |
|
|
46
|
+
| P2-16 | `entry_points.controllers.methods` mismatches `endpoints` count | cli.py | Medium |
|
|
47
|
+
| P2-17 | `--compact --help` token claim outdated | cli.py | Trivial |
|
|
48
|
+
| P2-18 | `impact` via file path: resolve to FQN before IR lookup | repository_ir.py | Low |
|
|
49
|
+
|
|
50
|
+
---
|
|
51
|
+
|
|
52
|
+
## Key Files Modified (this session)
|
|
53
|
+
|
|
54
|
+
```
|
|
55
|
+
src/sourcecode/cli.py — exit code 2→1 for --compact --full; forward-slash notes
|
|
56
|
+
src/sourcecode/mcp/server.py — _normalize_repo_path, try/except all tools, timeout P0-3
|
|
57
|
+
tests/test_enterprise_benchmarks.py — assertion exit_code 2→1
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
---
|
|
61
|
+
|
|
62
|
+
## Next Session
|
|
63
|
+
|
|
64
|
+
**Recommended start:** Fix `subsystem_summary.member_count` (P2-06).
|
|
65
|
+
|
|
66
|
+
Root cause: `_detect_subsystems()` in `repository_ir.py` builds subsystems without populating
|
|
67
|
+
`members` list. `modernize_cmd` reads `len(s.get("members") or [])` → always 0.
|
|
68
|
+
|
|
69
|
+
Then: `--no-cache` flag consistency audit (P2-13).
|
|
70
|
+
|
|
71
|
+
**Resume command:** `/gsd:resume-work`
|
|
72
|
+
|
|
73
|
+
**Test baseline:** `python3 -m pytest tests/ → 1590 passed, 3 skipped`
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: sourcecode
|
|
3
|
-
Version: 1.31.
|
|
3
|
+
Version: 1.31.27
|
|
4
4
|
Summary: Deterministic codebase context for AI coding agents
|
|
5
5
|
License: Apache License
|
|
6
6
|
Version 2.0, January 2004
|
|
@@ -225,7 +225,7 @@ Description-Content-Type: text/markdown
|
|
|
225
225
|
|
|
226
226
|
**AI-ready change intelligence for Java/Spring enterprise monoliths.**
|
|
227
227
|
|
|
228
|
-

|
|
229
229
|

|
|
230
230
|
|
|
231
231
|
---
|
|
@@ -263,7 +263,7 @@ pipx install sourcecode
|
|
|
263
263
|
|
|
264
264
|
```bash
|
|
265
265
|
sourcecode version
|
|
266
|
-
# sourcecode 1.31.
|
|
266
|
+
# sourcecode 1.31.27
|
|
267
267
|
```
|
|
268
268
|
|
|
269
269
|
---
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
**AI-ready change intelligence for Java/Spring enterprise monoliths.**
|
|
4
4
|
|
|
5
|
-

|
|
6
6
|

|
|
7
7
|
|
|
8
8
|
---
|
|
@@ -40,7 +40,7 @@ pipx install sourcecode
|
|
|
40
40
|
|
|
41
41
|
```bash
|
|
42
42
|
sourcecode version
|
|
43
|
-
# sourcecode 1.31.
|
|
43
|
+
# sourcecode 1.31.27
|
|
44
44
|
```
|
|
45
45
|
|
|
46
46
|
---
|
|
@@ -332,6 +332,7 @@ def ir_dict_to_canonical(
|
|
|
332
332
|
"spring_events": ir.get("spring_events") or {},
|
|
333
333
|
"score_basis": (ir.get("impact") or {}).get("score_basis", "none"),
|
|
334
334
|
"reverse_graph_size": len(ir.get("reverse_graph") or {}),
|
|
335
|
+
"security_model": ir.get("security_model", "unknown"),
|
|
335
336
|
}
|
|
336
337
|
|
|
337
338
|
cir_hash = _compute_cir_hash(
|
|
@@ -452,6 +453,7 @@ def project_endpoint_surface(cir: CanonicalRepositoryIR) -> dict:
|
|
|
452
453
|
"endpoints": endpoints,
|
|
453
454
|
"total": len(endpoints),
|
|
454
455
|
"no_security_signal": no_security_signal,
|
|
456
|
+
"security_model": cir.metadata.get("security_model", "unknown"),
|
|
455
457
|
# Legacy field alias — same count, kept for backward compat
|
|
456
458
|
"undocumented": no_security_signal,
|
|
457
459
|
}
|
|
@@ -745,7 +745,7 @@ def main(
|
|
|
745
745
|
"is meant for --agent mode. Use --agent --full for expanded output.",
|
|
746
746
|
err=True,
|
|
747
747
|
)
|
|
748
|
-
raise typer.Exit(code=
|
|
748
|
+
raise typer.Exit(code=1)
|
|
749
749
|
|
|
750
750
|
# P0-2 FIX: --full without --compact or --agent has no effect in contract/raw mode.
|
|
751
751
|
# Warn so the user knows the flag is not doing anything.
|
|
@@ -1127,10 +1127,14 @@ def main(
|
|
|
1127
1127
|
|
|
1128
1128
|
# --compact implicitly enables lightweight analysis passes so that
|
|
1129
1129
|
# dependency_summary, env_summary and code_notes_summary are never null.
|
|
1130
|
+
# architecture=True is also enabled so that architecture.confidence is
|
|
1131
|
+
# consistent with --agent (which auto-enables architecture). The
|
|
1132
|
+
# ArchitectureAnalyzer is path-based and adds negligible latency.
|
|
1130
1133
|
if compact:
|
|
1131
1134
|
dependencies = True
|
|
1132
1135
|
env_map = True
|
|
1133
1136
|
code_notes = True
|
|
1137
|
+
architecture = True
|
|
1134
1138
|
|
|
1135
1139
|
dependency_analyzer = DependencyAnalyzer() if dependencies else None
|
|
1136
1140
|
graph_analyzer = GraphAnalyzer() if graph_modules else None
|
|
@@ -3549,6 +3553,7 @@ def mcp_init(
|
|
|
3549
3553
|
raise typer.Exit(code=1)
|
|
3550
3554
|
|
|
3551
3555
|
typer.echo("MCP integration active.")
|
|
3556
|
+
typer.echo(" Note: repo_path debe usar forward slashes: C:/Users/... o /ruta/unix")
|
|
3552
3557
|
typer.echo("")
|
|
3553
3558
|
|
|
3554
3559
|
# Post-write: validate config and warn if client not running
|
|
@@ -3696,6 +3701,7 @@ def mcp_status() -> None:
|
|
|
3696
3701
|
typer.echo(sep)
|
|
3697
3702
|
typer.echo(" Note: 'configured' and 'running' are checked independently.")
|
|
3698
3703
|
typer.echo(" A running app still needs restart after first-time config.")
|
|
3704
|
+
typer.echo(" Path: repo_path debe usar forward slashes: C:/Users/... o /ruta/unix")
|
|
3699
3705
|
typer.echo(" Setup: sourcecode mcp init")
|
|
3700
3706
|
typer.echo(" Remove: sourcecode mcp remove")
|
|
3701
3707
|
|
|
@@ -10,8 +10,10 @@ data is the parsed JSON object from the CLI output, not a shell string.
|
|
|
10
10
|
"""
|
|
11
11
|
from __future__ import annotations
|
|
12
12
|
|
|
13
|
+
import concurrent.futures
|
|
13
14
|
import json
|
|
14
15
|
import os
|
|
16
|
+
import re
|
|
15
17
|
from typing import Any
|
|
16
18
|
|
|
17
19
|
from mcp.server.fastmcp import FastMCP
|
|
@@ -63,6 +65,29 @@ def _execute(args: list[str]) -> dict | CallToolResult:
|
|
|
63
65
|
return _ok(result)
|
|
64
66
|
|
|
65
67
|
|
|
68
|
+
_DEFAULT_TESTS_TIMEOUT_MS = 15_000
|
|
69
|
+
|
|
70
|
+
# Regex for MINGW paths: /c/some/path → C:/some/path
|
|
71
|
+
_MINGW_PATH_RE = re.compile(r"^/([a-zA-Z])(/.*)?$")
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
def _normalize_repo_path(path: str) -> str:
|
|
75
|
+
"""Normalize repo_path for cross-platform compatibility (P0-2).
|
|
76
|
+
|
|
77
|
+
Handles two Windows-specific formats:
|
|
78
|
+
- MINGW/Git-Bash: /c/Users/... → C:/Users/...
|
|
79
|
+
- Backslash: C:\\Users\\... → C:/Users/...
|
|
80
|
+
Forward-slash paths (C:/Users/... or /unix/path) pass through unchanged.
|
|
81
|
+
"""
|
|
82
|
+
m = _MINGW_PATH_RE.match(path)
|
|
83
|
+
if m:
|
|
84
|
+
drive = m.group(1).upper()
|
|
85
|
+
rest = m.group(2) or "/"
|
|
86
|
+
path = f"{drive}:{rest}"
|
|
87
|
+
path = path.replace("\\", "/")
|
|
88
|
+
return path
|
|
89
|
+
|
|
90
|
+
|
|
66
91
|
@mcp.tool()
|
|
67
92
|
def get_compact_context(repo_path: str = ".", git_context: bool = False) -> dict:
|
|
68
93
|
"""Compact human/LLM summary of a repository (~1000-3000 tokens). USE THIS FIRST.
|
|
@@ -76,14 +101,22 @@ def get_compact_context(repo_path: str = ".", git_context: bool = False) -> dict
|
|
|
76
101
|
repo_path: absolute path to the repository (default: current working directory).
|
|
77
102
|
git_context: include git log and branch context in the analysis.
|
|
78
103
|
"""
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
104
|
+
_raw = repo_path
|
|
105
|
+
try:
|
|
106
|
+
if not isinstance(repo_path, str):
|
|
107
|
+
return _err("repo_path must be a string", "INVALID_ARGUMENT")
|
|
108
|
+
if not isinstance(git_context, bool):
|
|
109
|
+
return _err("git_context must be boolean", "INVALID_ARGUMENT")
|
|
110
|
+
repo_path = _normalize_repo_path(repo_path)
|
|
111
|
+
args = [repo_path, "--compact"]
|
|
112
|
+
if git_context:
|
|
113
|
+
args.append("--git-context")
|
|
114
|
+
return _execute(args)
|
|
115
|
+
except Exception as exc:
|
|
116
|
+
return _err(
|
|
117
|
+
f"Internal error: {type(exc).__name__}: {exc} — repo_path recibido: {_raw}",
|
|
118
|
+
"INTERNAL_ERROR",
|
|
119
|
+
)
|
|
87
120
|
|
|
88
121
|
|
|
89
122
|
@mcp.tool()
|
|
@@ -99,14 +132,22 @@ def get_agent_context(repo_path: str = ".", git_context: bool = False) -> dict:
|
|
|
99
132
|
repo_path: absolute path to the repository (default: current working directory).
|
|
100
133
|
git_context: include git log and branch context in the analysis.
|
|
101
134
|
"""
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
135
|
+
_raw = repo_path
|
|
136
|
+
try:
|
|
137
|
+
if not isinstance(repo_path, str):
|
|
138
|
+
return _err("repo_path must be a string", "INVALID_ARGUMENT")
|
|
139
|
+
if not isinstance(git_context, bool):
|
|
140
|
+
return _err("git_context must be boolean", "INVALID_ARGUMENT")
|
|
141
|
+
repo_path = _normalize_repo_path(repo_path)
|
|
142
|
+
args = [repo_path, "--agent"]
|
|
143
|
+
if git_context:
|
|
144
|
+
args.append("--git-context")
|
|
145
|
+
return _execute(args)
|
|
146
|
+
except Exception as exc:
|
|
147
|
+
return _err(
|
|
148
|
+
f"Internal error: {type(exc).__name__}: {exc} — repo_path recibido: {_raw}",
|
|
149
|
+
"INTERNAL_ERROR",
|
|
150
|
+
)
|
|
110
151
|
|
|
111
152
|
|
|
112
153
|
@mcp.tool()
|
|
@@ -117,17 +158,28 @@ def get_endpoints(repo_path: str = ".") -> dict:
|
|
|
117
158
|
Returns: endpoints list with method, path, controller, handler fields;
|
|
118
159
|
security dict when authorization annotations are present
|
|
119
160
|
(policy: roles_allowed|permit_all|deny_all|authenticated|...);
|
|
120
|
-
total (int)
|
|
121
|
-
no_security_signal counts endpoints with no recognized auth annotation
|
|
122
|
-
|
|
161
|
+
total (int), no_security_signal (int), and security_model (str) fields.
|
|
162
|
+
no_security_signal counts endpoints with no recognized auth annotation.
|
|
163
|
+
security_model values: "filter_based" (centralized Spring Security config —
|
|
164
|
+
high no_security_signal is expected and does NOT mean endpoints are unprotected),
|
|
165
|
+
"annotation_based" (per-endpoint annotations only), "mixed" (both),
|
|
166
|
+
"unknown" (no security signals detected).
|
|
123
167
|
Supports Spring MVC (@GetMapping etc.) and JAX-RS (@GET/@POST etc.).
|
|
124
168
|
Security annotations detected: @RolesAllowed, @PermitAll, @DenyAll,
|
|
125
169
|
@Authenticated, @PreAuthorize, @Secured, @SecurityRequirement, @M3FiltroSeguridad.
|
|
126
170
|
repo_path: absolute path to the repository (default: current working directory).
|
|
127
171
|
"""
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
172
|
+
_raw = repo_path
|
|
173
|
+
try:
|
|
174
|
+
if not isinstance(repo_path, str):
|
|
175
|
+
return _err("repo_path must be a string", "INVALID_ARGUMENT")
|
|
176
|
+
repo_path = _normalize_repo_path(repo_path)
|
|
177
|
+
return _execute(["endpoints", repo_path])
|
|
178
|
+
except Exception as exc:
|
|
179
|
+
return _err(
|
|
180
|
+
f"Internal error: {type(exc).__name__}: {exc} — repo_path recibido: {_raw}",
|
|
181
|
+
"INTERNAL_ERROR",
|
|
182
|
+
)
|
|
131
183
|
|
|
132
184
|
|
|
133
185
|
@mcp.tool()
|
|
@@ -138,12 +190,20 @@ def get_module_context(repo_path: str = ".", module: str = "") -> dict:
|
|
|
138
190
|
repo_path: absolute path to the repository root.
|
|
139
191
|
module: subdirectory name relative to repo_path (e.g. 'src/auth', 'api', 'core').
|
|
140
192
|
"""
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
193
|
+
_raw = repo_path
|
|
194
|
+
try:
|
|
195
|
+
if not isinstance(repo_path, str):
|
|
196
|
+
return _err("repo_path must be a string", "INVALID_ARGUMENT")
|
|
197
|
+
if not isinstance(module, str) or not module.strip():
|
|
198
|
+
return _err("module must be a non-empty string", "INVALID_ARGUMENT")
|
|
199
|
+
repo_path = _normalize_repo_path(repo_path)
|
|
200
|
+
module_path = repo_path.rstrip("/") + "/" + module.strip("/")
|
|
201
|
+
return _execute([module_path, "--compact"])
|
|
202
|
+
except Exception as exc:
|
|
203
|
+
return _err(
|
|
204
|
+
f"Internal error: {type(exc).__name__}: {exc} — repo_path recibido: {_raw}",
|
|
205
|
+
"INTERNAL_ERROR",
|
|
206
|
+
)
|
|
147
207
|
|
|
148
208
|
|
|
149
209
|
@mcp.tool()
|
|
@@ -154,11 +214,19 @@ def get_delta(repo_path: str = ".", since: str = "HEAD~1") -> dict:
|
|
|
154
214
|
repo_path: absolute path to the repository (default: current working directory).
|
|
155
215
|
since: git ref to diff against (e.g. HEAD~3, main, origin/main).
|
|
156
216
|
"""
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
217
|
+
_raw = repo_path
|
|
218
|
+
try:
|
|
219
|
+
if not isinstance(repo_path, str):
|
|
220
|
+
return _err("repo_path must be a string", "INVALID_ARGUMENT")
|
|
221
|
+
if not isinstance(since, str) or not since.strip():
|
|
222
|
+
return _err("since must be a non-empty git ref", "INVALID_ARGUMENT")
|
|
223
|
+
repo_path = _normalize_repo_path(repo_path)
|
|
224
|
+
return _execute(["prepare-context", "delta", repo_path, "--since", since])
|
|
225
|
+
except Exception as exc:
|
|
226
|
+
return _err(
|
|
227
|
+
f"Internal error: {type(exc).__name__}: {exc} — repo_path recibido: {_raw}",
|
|
228
|
+
"INTERNAL_ERROR",
|
|
229
|
+
)
|
|
162
230
|
|
|
163
231
|
|
|
164
232
|
@mcp.tool()
|
|
@@ -175,9 +243,17 @@ def get_ir_summary(repo_path: str = ".") -> dict:
|
|
|
175
243
|
|
|
176
244
|
repo_path: absolute path to the Java repository (default: current working directory).
|
|
177
245
|
"""
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
246
|
+
_raw = repo_path
|
|
247
|
+
try:
|
|
248
|
+
if not isinstance(repo_path, str):
|
|
249
|
+
return _err("repo_path must be a string", "INVALID_ARGUMENT")
|
|
250
|
+
repo_path = _normalize_repo_path(repo_path)
|
|
251
|
+
return _execute(["repo-ir", repo_path, "--summary-only"])
|
|
252
|
+
except Exception as exc:
|
|
253
|
+
return _err(
|
|
254
|
+
f"Internal error: {type(exc).__name__}: {exc} — repo_path recibido: {_raw}",
|
|
255
|
+
"INTERNAL_ERROR",
|
|
256
|
+
)
|
|
181
257
|
|
|
182
258
|
|
|
183
259
|
@mcp.tool()
|
|
@@ -190,12 +266,20 @@ def fix_bug_context(repo_path: str = ".", symptom: str = "") -> dict:
|
|
|
190
266
|
symptom: optional error message or class name to focus the file ranking
|
|
191
267
|
(e.g. "NullPointerException in EstructuraRrHhRestController").
|
|
192
268
|
"""
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
269
|
+
_raw = repo_path
|
|
270
|
+
try:
|
|
271
|
+
if not isinstance(repo_path, str):
|
|
272
|
+
return _err("repo_path must be a string", "INVALID_ARGUMENT")
|
|
273
|
+
repo_path = _normalize_repo_path(repo_path)
|
|
274
|
+
args = ["prepare-context", "fix-bug", repo_path]
|
|
275
|
+
if symptom and isinstance(symptom, str) and symptom.strip():
|
|
276
|
+
args.extend(["--symptom", symptom.strip()])
|
|
277
|
+
return _execute(args)
|
|
278
|
+
except Exception as exc:
|
|
279
|
+
return _err(
|
|
280
|
+
f"Internal error: {type(exc).__name__}: {exc} — repo_path recibido: {_raw}",
|
|
281
|
+
"INTERNAL_ERROR",
|
|
282
|
+
)
|
|
199
283
|
|
|
200
284
|
|
|
201
285
|
@mcp.tool()
|
|
@@ -208,12 +292,20 @@ def review_pr_context(repo_path: str = ".", since: str = "") -> dict:
|
|
|
208
292
|
since: git ref to diff against (e.g. HEAD~3, main, origin/main).
|
|
209
293
|
If omitted, diffs against uncommitted changes or HEAD~1 fallback.
|
|
210
294
|
"""
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
295
|
+
_raw = repo_path
|
|
296
|
+
try:
|
|
297
|
+
if not isinstance(repo_path, str):
|
|
298
|
+
return _err("repo_path must be a string", "INVALID_ARGUMENT")
|
|
299
|
+
repo_path = _normalize_repo_path(repo_path)
|
|
300
|
+
args = ["prepare-context", "review-pr", repo_path]
|
|
301
|
+
if since and isinstance(since, str) and since.strip():
|
|
302
|
+
args.extend(["--since", since.strip()])
|
|
303
|
+
return _execute(args)
|
|
304
|
+
except Exception as exc:
|
|
305
|
+
return _err(
|
|
306
|
+
f"Internal error: {type(exc).__name__}: {exc} — repo_path recibido: {_raw}",
|
|
307
|
+
"INTERNAL_ERROR",
|
|
308
|
+
)
|
|
217
309
|
|
|
218
310
|
|
|
219
311
|
@mcp.tool()
|
|
@@ -223,9 +315,17 @@ def onboard_context(repo_path: str = ".") -> dict:
|
|
|
223
315
|
Maps to: sourcecode prepare-context onboard <repo_path>
|
|
224
316
|
repo_path: absolute path to the repository (default: current working directory).
|
|
225
317
|
"""
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
318
|
+
_raw = repo_path
|
|
319
|
+
try:
|
|
320
|
+
if not isinstance(repo_path, str):
|
|
321
|
+
return _err("repo_path must be a string", "INVALID_ARGUMENT")
|
|
322
|
+
repo_path = _normalize_repo_path(repo_path)
|
|
323
|
+
return _execute(["prepare-context", "onboard", repo_path])
|
|
324
|
+
except Exception as exc:
|
|
325
|
+
return _err(
|
|
326
|
+
f"Internal error: {type(exc).__name__}: {exc} — repo_path recibido: {_raw}",
|
|
327
|
+
"INTERNAL_ERROR",
|
|
328
|
+
)
|
|
229
329
|
|
|
230
330
|
|
|
231
331
|
@mcp.tool()
|
|
@@ -236,9 +336,17 @@ def explain_context(repo_path: str = ".") -> dict:
|
|
|
236
336
|
Returns: project summary, architecture, entry points, key dependencies.
|
|
237
337
|
repo_path: absolute path to the repository (default: current working directory).
|
|
238
338
|
"""
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
339
|
+
_raw = repo_path
|
|
340
|
+
try:
|
|
341
|
+
if not isinstance(repo_path, str):
|
|
342
|
+
return _err("repo_path must be a string", "INVALID_ARGUMENT")
|
|
343
|
+
repo_path = _normalize_repo_path(repo_path)
|
|
344
|
+
return _execute(["prepare-context", "explain", repo_path])
|
|
345
|
+
except Exception as exc:
|
|
346
|
+
return _err(
|
|
347
|
+
f"Internal error: {type(exc).__name__}: {exc} — repo_path recibido: {_raw}",
|
|
348
|
+
"INTERNAL_ERROR",
|
|
349
|
+
)
|
|
242
350
|
|
|
243
351
|
|
|
244
352
|
@mcp.tool()
|
|
@@ -249,9 +357,17 @@ def refactor_context(repo_path: str = ".") -> dict:
|
|
|
249
357
|
Returns: structural issues, coupling hotspots, improvement opportunities.
|
|
250
358
|
repo_path: absolute path to the repository (default: current working directory).
|
|
251
359
|
"""
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
360
|
+
_raw = repo_path
|
|
361
|
+
try:
|
|
362
|
+
if not isinstance(repo_path, str):
|
|
363
|
+
return _err("repo_path must be a string", "INVALID_ARGUMENT")
|
|
364
|
+
repo_path = _normalize_repo_path(repo_path)
|
|
365
|
+
return _execute(["prepare-context", "refactor", repo_path])
|
|
366
|
+
except Exception as exc:
|
|
367
|
+
return _err(
|
|
368
|
+
f"Internal error: {type(exc).__name__}: {exc} — repo_path recibido: {_raw}",
|
|
369
|
+
"INTERNAL_ERROR",
|
|
370
|
+
)
|
|
255
371
|
|
|
256
372
|
|
|
257
373
|
@mcp.tool()
|
|
@@ -260,15 +376,45 @@ def generate_tests_context(repo_path: str = ".", include_all: bool = False) -> d
|
|
|
260
376
|
|
|
261
377
|
Maps to: sourcecode prepare-context generate-tests <repo_path> [--all]
|
|
262
378
|
Returns: test_gaps list of untested files ranked by risk.
|
|
379
|
+
On large repos (>2000 classes) analysis is bounded by SOURCECODE_TESTS_TIMEOUT_MS
|
|
380
|
+
(default: 15000 ms). If timeout elapses, returns truncated=true with partial results.
|
|
263
381
|
repo_path: absolute path to the repository (default: current working directory).
|
|
264
382
|
include_all: return full test_gaps list without truncating to top 20.
|
|
265
383
|
"""
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
384
|
+
_raw = repo_path
|
|
385
|
+
try:
|
|
386
|
+
if not isinstance(repo_path, str):
|
|
387
|
+
return _err("repo_path must be a string", "INVALID_ARGUMENT")
|
|
388
|
+
if not isinstance(include_all, bool):
|
|
389
|
+
return _err("include_all must be boolean", "INVALID_ARGUMENT")
|
|
390
|
+
repo_path = _normalize_repo_path(repo_path)
|
|
391
|
+
args = ["prepare-context", "generate-tests", repo_path]
|
|
392
|
+
if include_all:
|
|
393
|
+
args.append("--all")
|
|
394
|
+
|
|
395
|
+
# P0-3: timeout guard — large repos can stall the stdio transport indefinitely.
|
|
396
|
+
timeout_ms = int(os.environ.get("SOURCECODE_TESTS_TIMEOUT_MS", str(_DEFAULT_TESTS_TIMEOUT_MS)))
|
|
397
|
+
timeout_s = timeout_ms / 1000.0
|
|
398
|
+
|
|
399
|
+
executor = concurrent.futures.ThreadPoolExecutor(max_workers=1)
|
|
400
|
+
future = executor.submit(_execute, args)
|
|
401
|
+
done, _not_done = concurrent.futures.wait([future], timeout=timeout_s)
|
|
402
|
+
if _not_done:
|
|
403
|
+
executor.shutdown(wait=False)
|
|
404
|
+
return _ok({
|
|
405
|
+
"truncated": True,
|
|
406
|
+
"truncated_reason": f"timeout_{timeout_ms // 1000}s" if timeout_ms >= 1000 else f"timeout_{timeout_ms}ms",
|
|
407
|
+
"files_analyzed": 0,
|
|
408
|
+
"results": [],
|
|
409
|
+
})
|
|
410
|
+
executor.shutdown(wait=False)
|
|
411
|
+
return future.result()
|
|
412
|
+
|
|
413
|
+
except Exception as exc:
|
|
414
|
+
return _err(
|
|
415
|
+
f"Internal error: {type(exc).__name__}: {exc} — repo_path recibido: {_raw}",
|
|
416
|
+
"INTERNAL_ERROR",
|
|
417
|
+
)
|
|
272
418
|
|
|
273
419
|
|
|
274
420
|
@mcp.tool()
|
|
@@ -289,14 +435,22 @@ def get_impact_context(repo_path: str = ".", target: str = "", depth: int = 4) -
|
|
|
289
435
|
repo_path: absolute path to the Java repository (default: current working directory).
|
|
290
436
|
depth: BFS depth for indirect caller traversal (1–8, default: 4).
|
|
291
437
|
"""
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
438
|
+
_raw = repo_path
|
|
439
|
+
try:
|
|
440
|
+
if not isinstance(repo_path, str):
|
|
441
|
+
return _err("repo_path must be a string", "INVALID_ARGUMENT")
|
|
442
|
+
if not isinstance(target, str) or not target.strip():
|
|
443
|
+
return _err("target must be a non-empty class name or FQN", "INVALID_ARGUMENT")
|
|
444
|
+
if not isinstance(depth, int) or depth < 1 or depth > 8:
|
|
445
|
+
return _err("depth must be an integer between 1 and 8", "INVALID_ARGUMENT")
|
|
446
|
+
repo_path = _normalize_repo_path(repo_path)
|
|
447
|
+
args = ["impact", target.strip(), repo_path, "--depth", str(depth)]
|
|
448
|
+
return _execute(args)
|
|
449
|
+
except Exception as exc:
|
|
450
|
+
return _err(
|
|
451
|
+
f"Internal error: {type(exc).__name__}: {exc} — repo_path recibido: {_raw}",
|
|
452
|
+
"INTERNAL_ERROR",
|
|
453
|
+
)
|
|
300
454
|
|
|
301
455
|
|
|
302
456
|
_TELEMETRY_ACTIONS = frozenset({"status", "enable", "disable"})
|