sourcecode 1.32.0__tar.gz → 1.32.2__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.32.2/.continue-here.md +106 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/PKG-INFO +1 -1
- {sourcecode-1.32.0 → sourcecode-1.32.2}/pyproject.toml +1 -1
- {sourcecode-1.32.0 → sourcecode-1.32.2}/src/sourcecode/__init__.py +1 -1
- {sourcecode-1.32.0 → sourcecode-1.32.2}/src/sourcecode/architecture_analyzer.py +64 -15
- {sourcecode-1.32.0 → sourcecode-1.32.2}/src/sourcecode/classifier.py +4 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/src/sourcecode/cli.py +58 -3
- {sourcecode-1.32.0 → sourcecode-1.32.2}/src/sourcecode/context_summarizer.py +1 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/src/sourcecode/dependency_analyzer.py +3 -3
- {sourcecode-1.32.0 → sourcecode-1.32.2}/src/sourcecode/detectors/java.py +6 -1
- {sourcecode-1.32.0 → sourcecode-1.32.2}/src/sourcecode/mcp/server.py +36 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/src/sourcecode/prepare_context.py +7 -1
- {sourcecode-1.32.0 → sourcecode-1.32.2}/src/sourcecode/repository_ir.py +6 -1
- sourcecode-1.32.2/src/sourcecode/ris.py +372 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/src/sourcecode/summarizer.py +1 -0
- sourcecode-1.32.0/.continue-here.md +0 -89
- {sourcecode-1.32.0 → sourcecode-1.32.2}/.agents/skills/source-command-gsd-join-discord/SKILL.md +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/.agents/skills/source-command-gsd-review-backlog/SKILL.md +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/.agents/skills/source-command-gsd-workstreams/SKILL.md +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/.github/workflows/build-windows.yml +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/.gitignore +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/.ruff.toml +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/.sourcecode-cache/snapshot-3b5997a-fa5c742c.json +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/AUDIT_REAL_REPOS.md +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/AUDIT_v1.31.23.md +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/CHANGELOG.md +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/CONTRIBUTING.md +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/LICENSE +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/README.md +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/SECURITY.md +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/docs/PRODUCT_AUDIT.md +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/docs/PRODUCT_TIERS.md +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/docs/USER_GUIDE.md +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/docs/privacy.md +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/docs/schema.md +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/raw +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/run_cli.py +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/src/sourcecode/adaptive_scanner.py +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/src/sourcecode/architecture_summary.py +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/src/sourcecode/ast_extractor.py +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/src/sourcecode/cache.py +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/src/sourcecode/canonical_ir.py +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/src/sourcecode/code_notes_analyzer.py +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/src/sourcecode/confidence_analyzer.py +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/src/sourcecode/context_scorer.py +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/src/sourcecode/contract_model.py +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/src/sourcecode/contract_pipeline.py +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/src/sourcecode/coverage_parser.py +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/src/sourcecode/detectors/__init__.py +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/src/sourcecode/detectors/base.py +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/src/sourcecode/detectors/csproj_parser.py +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/src/sourcecode/detectors/dart.py +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/src/sourcecode/detectors/dotnet.py +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/src/sourcecode/detectors/elixir.py +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/src/sourcecode/detectors/go.py +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/src/sourcecode/detectors/heuristic.py +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/src/sourcecode/detectors/hybrid.py +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/src/sourcecode/detectors/jvm_ext.py +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/src/sourcecode/detectors/nodejs.py +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/src/sourcecode/detectors/parsers.py +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/src/sourcecode/detectors/php.py +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/src/sourcecode/detectors/project.py +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/src/sourcecode/detectors/python.py +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/src/sourcecode/detectors/ruby.py +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/src/sourcecode/detectors/rust.py +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/src/sourcecode/detectors/systems.py +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/src/sourcecode/detectors/terraform.py +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/src/sourcecode/detectors/tooling.py +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/src/sourcecode/doc_analyzer.py +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/src/sourcecode/entrypoint_classifier.py +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/src/sourcecode/env_analyzer.py +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/src/sourcecode/file_classifier.py +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/src/sourcecode/flow_analyzer.py +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/src/sourcecode/git_analyzer.py +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/src/sourcecode/graph_analyzer.py +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/src/sourcecode/license.py +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/src/sourcecode/mcp/__init__.py +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/src/sourcecode/mcp/onboarding/__init__.py +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/src/sourcecode/mcp/onboarding/applier.py +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/src/sourcecode/mcp/onboarding/backup.py +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/src/sourcecode/mcp/onboarding/detector.py +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/src/sourcecode/mcp/onboarding/planner.py +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/src/sourcecode/mcp/runner.py +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/src/sourcecode/mcp_nudge.py +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/src/sourcecode/metrics_analyzer.py +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/src/sourcecode/output_budget.py +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/src/sourcecode/path_filters.py +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/src/sourcecode/pr_comment_renderer.py +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/src/sourcecode/progress.py +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/src/sourcecode/ranking_engine.py +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/src/sourcecode/redactor.py +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/src/sourcecode/relevance_scorer.py +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/src/sourcecode/repo_classifier.py +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/src/sourcecode/runtime_classifier.py +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/src/sourcecode/scanner.py +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/src/sourcecode/schema.py +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/src/sourcecode/semantic_analyzer.py +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/src/sourcecode/serializer.py +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/src/sourcecode/telemetry/__init__.py +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/src/sourcecode/telemetry/config.py +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/src/sourcecode/telemetry/consent.py +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/src/sourcecode/telemetry/events.py +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/src/sourcecode/telemetry/filters.py +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/src/sourcecode/telemetry/transport.py +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/src/sourcecode/tree_utils.py +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/src/sourcecode/workspace.py +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/tests/__init__.py +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/tests/conftest.py +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/tests/fixtures/coverage.xml +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/tests/fixtures/fastapi_app/pyproject.toml +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/tests/fixtures/fastapi_app/src/main.py +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/tests/fixtures/go_service/cmd/api/main.go +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/tests/fixtures/go_service/go.mod +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/tests/fixtures/jacoco.xml +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/tests/fixtures/latin1_sample.java +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/tests/fixtures/latin1_sample_iso.java +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/tests/fixtures/lcov.info +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/tests/fixtures/nextjs_app/app/page.tsx +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/tests/fixtures/nextjs_app/package.json +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/tests/fixtures/nextjs_app/pnpm-lock.yaml +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/tests/fixtures/pnpm_monorepo/apps/web/app/page.tsx +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/tests/fixtures/pnpm_monorepo/apps/web/package.json +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/tests/fixtures/pnpm_monorepo/packages/api/main.py +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/tests/fixtures/pnpm_monorepo/packages/api/pyproject.toml +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/tests/fixtures/pnpm_monorepo/pnpm-workspace.yaml +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/tests/fixtures/spring_boot_minimal/pom.xml +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/ausente/application/service/FindAusenteService.java +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/ausente/domain/entities/Ausente.java +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/ausente/infrastructure/rest/AusenteRestController.java +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/autocoberturas/application/service/FindAutocoberturasService.java +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/autocoberturas/domain/entities/Autocoberturas.java +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/autocoberturas/infrastructure/rest/AutocoberturasRestController.java +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/calendarioTrabajador/application/service/FindCalendarioTrabajadorService.java +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/calendarioTrabajador/domain/entities/CalendarioTrabajador.java +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/calendarioTrabajador/infrastructure/rest/CalendarioTrabajadorRestController.java +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/departamento/application/service/FindDepartamentoService.java +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/departamento/domain/entities/Departamento.java +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/departamento/infrastructure/rest/DepartamentoRestController.java +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/empleado/application/service/FindEmpleadoService.java +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/empleado/domain/entities/Empleado.java +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/empleado/infrastructure/rest/EmpleadoRestController.java +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/demo/DemoApplication.java +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/demo/config/FilterConfig.java +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/demo/domain/Health.java +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/demo/mapper/HealthMapper.java +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/demo/repository/HealthRepository.java +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/demo/service/HealthService.java +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/demo/web/HealthRestController.java +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/demo/web/NominaRestController.java +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/tests/fixtures/spring_boot_minimal/src/main/resources/application-dev.yml +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/tests/fixtures/spring_boot_minimal/src/main/resources/application.yml +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/tests/fixtures/spring_boot_minimal/src/main/resources/mapper/HealthMapper.xml +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/tests/test_architecture_analyzer.py +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/tests/test_architecture_summary.py +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/tests/test_ast_extractor.py +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/tests/test_audit_fixes.py +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/tests/test_audit_sas_v2.py +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/tests/test_block1_reliability.py +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/tests/test_block2_coverage.py +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/tests/test_block5_quality.py +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/tests/test_broadleaf_fixes.py +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/tests/test_bug_fixes_v1302.py +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/tests/test_bug_fixes_v13115.py +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/tests/test_bug_fixes_v1312.py +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/tests/test_bug_fixes_v13122.py +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/tests/test_bug_fixes_v1313.py +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/tests/test_bug_fixes_v13130.py +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/tests/test_bug_fixes_v1321.py +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/tests/test_bug_fixes_v16.py +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/tests/test_bug_fixes_v2.py +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/tests/test_cache.py +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/tests/test_canonical_ir.py +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/tests/test_classifier.py +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/tests/test_cli.py +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/tests/test_code_notes_analyzer.py +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/tests/test_context_scorer.py +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/tests/test_contract_pipeline.py +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/tests/test_coverage_parser.py +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/tests/test_cross_consistency.py +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/tests/test_dependency_analyzer_node_python.py +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/tests/test_dependency_analyzer_polyglot.py +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/tests/test_dependency_schema.py +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/tests/test_detector_dotnet.py +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/tests/test_detector_go_rust_java.py +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/tests/test_detector_nodejs.py +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/tests/test_detector_php_ruby_dart.py +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/tests/test_detector_python.py +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/tests/test_detector_universal_managed.py +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/tests/test_detector_universal_systems.py +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/tests/test_detectors_base.py +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/tests/test_doc_analyzer_jsdom.py +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/tests/test_doc_analyzer_python.py +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/tests/test_encoding_regression.py +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/tests/test_enterprise_benchmarks.py +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/tests/test_graph_analyzer_polyglot.py +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/tests/test_graph_analyzer_python_node.py +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/tests/test_graph_schema.py +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/tests/test_hybrid_inference.py +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/tests/test_integration.py +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/tests/test_integration_dependencies.py +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/tests/test_integration_detection.py +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/tests/test_integration_docs.py +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/tests/test_integration_graph_modules.py +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/tests/test_integration_lqn.py +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/tests/test_integration_metrics.py +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/tests/test_integration_multistack.py +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/tests/test_integration_semantics.py +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/tests/test_integration_universal.py +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/tests/test_java_spring_integration.py +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/tests/test_mcp_nudge.py +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/tests/test_mcp_runner.py +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/tests/test_mcp_serve.py +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/tests/test_mcp_tools.py +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/tests/test_metrics_analyzer.py +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/tests/test_output_ux.py +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/tests/test_packaging.py +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/tests/test_phase1_improvements.py +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/tests/test_pipeline_integrity.py +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/tests/test_real_projects.py +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/tests/test_redactor.py +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/tests/test_repository_ir.py +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/tests/test_scanner.py +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/tests/test_schema.py +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/tests/test_schema_normalization.py +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/tests/test_scoring_calibration.py +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/tests/test_semantic_analyzer_node.py +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/tests/test_semantic_analyzer_python.py +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/tests/test_semantic_import_resolution.py +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/tests/test_semantic_schema.py +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/tests/test_signal_hierarchy.py +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/tests/test_summarizer.py +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/tests/test_surface_honesty.py +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/tests/test_task_differentiation.py +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/tests/test_telemetry.py +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/tests/test_v131_improvements.py +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/tests/test_v1_10_regressions.py +0 -0
- {sourcecode-1.32.0 → sourcecode-1.32.2}/tests/test_workspace_analyzer.py +0 -0
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
# .continue-here.md — sourcecode CLI
|
|
2
|
+
**Session paused:** 2026-05-28
|
|
3
|
+
**Branch:** master
|
|
4
|
+
**Last commit:** `7b5011e` fix: 9 correctness bugs — i18n, controller detection, project_type, dep dedup, arch pattern
|
|
5
|
+
**Version:** 1.32.1
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## What was done this session
|
|
10
|
+
|
|
11
|
+
Fixed 9 correctness/reliability bugs identified by user from testing against spring-petclinic and other Spring repos. All committed in `7b5011e`.
|
|
12
|
+
|
|
13
|
+
| # | Severity | File(s) | Fix |
|
|
14
|
+
|---|----------|---------|-----|
|
|
15
|
+
| 1 | CRITICAL | `architecture_analyzer.py`, `dependency_analyzer.py`, `cli.py` | 6 Spanish strings in JSON output → English |
|
|
16
|
+
| 2 | HIGH | `detectors/java.py` | `@Controller` detection accepts `@GetMapping`/`@PostMapping`/etc, not just `@RequestMapping` — fixes undercount of controllers |
|
|
17
|
+
| 3 | HIGH | `detectors/java.py`, `classifier.py`, `context_summarizer.py`, `summarizer.py` | Added Thymeleaf/FreeMarker detection; classifier returns `"web_mvc"` for Spring + server-side template apps instead of `"api"` |
|
|
18
|
+
| 4 | MEDIUM | `prepare_context.py` | Dedup `key_dependencies` by name before ranking — mirrors dedup already in cli.py |
|
|
19
|
+
| 5 | MEDIUM | `architecture_analyzer.py` | New `_detect_spring_domain_modules()` — detects petclinic-style domain packages via longest-common-prefix stripping; returns `"spring_mvc_layered"` pattern |
|
|
20
|
+
| 6 | MEDIUM | — | Resolved by Bug #2 (IR controller count now consistent with entry_points) |
|
|
21
|
+
| 7 | LOW | `repository_ir.py` | `_canonical_subsystem_pkg` uses depth 5 for `springframework`/`apache` namespaces so `cross_module_impact.module` shows app modules not framework package names |
|
|
22
|
+
| 8 | LOW | `repository_ir.py` | `mappers_affected.role` defaults to `"repository"` for JPA repos, `"mapper"` only for MyBatis `mapper_interface` symbols |
|
|
23
|
+
| 9 | LOW | — | **SKIPPED** — onboard vs architecture confidence divergence; no acceptance criterion check; low risk |
|
|
24
|
+
|
|
25
|
+
Version also bumped: 1.32.0 → 1.32.1 (`__init__.py` + `pyproject.toml`).
|
|
26
|
+
|
|
27
|
+
---
|
|
28
|
+
|
|
29
|
+
## What remains
|
|
30
|
+
|
|
31
|
+
### From the bug fix task spec
|
|
32
|
+
- [ ] **Bug #9** (LOW): `onboard.confidence "high"` vs `architecture.confidence "low"` divergence — use min of two, or document. Not in acceptance criteria so deferred.
|
|
33
|
+
- [ ] **Validation**: Run `sourcecode spring-petclinic --agent | jq .` to verify acceptance criteria live:
|
|
34
|
+
- JSON output 100% English (done statically via grep — passed)
|
|
35
|
+
- `entry_points.controllers.classes == 6`
|
|
36
|
+
- `project_type: "web_mvc"`
|
|
37
|
+
- `key_dependencies` no duplicates
|
|
38
|
+
- `architecture.pattern: "spring_mvc_layered"`
|
|
39
|
+
|
|
40
|
+
### From session 29 handoff (pre-existing)
|
|
41
|
+
Three tiering policy gaps — still open:
|
|
42
|
+
- **GAP 1 (easy)**: Add `"upgrade_hint": "sourcecode activate <license_key>"` to JSON payload in `require_feature()` in `license.py:244` — one-liner
|
|
43
|
+
- **GAP 2 (medium)**: Tiered `--help` output (Free shows core commands + lock labels, Pro shows full). Requires custom `--help` callback since `is_pro` unavailable at module init.
|
|
44
|
+
- **GAP 3 (medium)**: Free-tier node cap (max 10) for `--graph-modules` and `--semantics` outputs
|
|
45
|
+
|
|
46
|
+
### Optional P1 (backlog)
|
|
47
|
+
- `project_summary` quality improvements
|
|
48
|
+
- `relevant_files.score` ranking improvements
|
|
49
|
+
|
|
50
|
+
---
|
|
51
|
+
|
|
52
|
+
## Key technical context for next session
|
|
53
|
+
|
|
54
|
+
### Bug #5 — spring domain detection
|
|
55
|
+
`_detect_spring_domain_modules` in `architecture_analyzer.py`:
|
|
56
|
+
1. Finds longest common path prefix across all source paths
|
|
57
|
+
2. Strips it (e.g. `src/main/java/org/springframework/samples/petclinic/`)
|
|
58
|
+
3. Takes first remaining segment as module name
|
|
59
|
+
4. ≥3 distinct modules with ≥2 files each → returns `"spring_mvc_layered"`
|
|
60
|
+
Pattern priority 3 in `_PATTERN_PRIORITY` (same as `"mvc"`).
|
|
61
|
+
|
|
62
|
+
### Bug #3 classifier ordering
|
|
63
|
+
`classifier.py._classify_project_type()` order:
|
|
64
|
+
1. `_WEB_FRAMEWORKS` → `"webapp"`
|
|
65
|
+
2. NEW: `_SERVERSIDE_TEMPLATE_FRAMEWORKS` (Thymeleaf, FreeMarker) → `"web_mvc"`
|
|
66
|
+
3. `_API_FRAMEWORKS` (Spring Boot, etc.) → `"api"`
|
|
67
|
+
|
|
68
|
+
### Bug #7 — framework namespace depth
|
|
69
|
+
Only triggers when `parts[1] in _FRAMEWORK_NS` AND `len(parts) >= 5`.
|
|
70
|
+
`org.keycloak.services.Foo` → parts[1]="keycloak" (not in FRAMEWORK_NS) → unchanged.
|
|
71
|
+
`org.springframework.samples.petclinic.owner.X` → depth 5 → `org.springframework.samples.petclinic.owner`.
|
|
72
|
+
|
|
73
|
+
### GAP 1 location (license.py:244)
|
|
74
|
+
```python
|
|
75
|
+
payload = {
|
|
76
|
+
"error": "pro_required",
|
|
77
|
+
"feature": feature_name,
|
|
78
|
+
"message": (...),
|
|
79
|
+
# ADD: "upgrade_hint": "sourcecode activate <license_key>",
|
|
80
|
+
}
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
---
|
|
84
|
+
|
|
85
|
+
## Files modified this session
|
|
86
|
+
- `src/sourcecode/__init__.py`
|
|
87
|
+
- `pyproject.toml`
|
|
88
|
+
- `src/sourcecode/architecture_analyzer.py`
|
|
89
|
+
- `src/sourcecode/classifier.py`
|
|
90
|
+
- `src/sourcecode/cli.py`
|
|
91
|
+
- `src/sourcecode/context_summarizer.py`
|
|
92
|
+
- `src/sourcecode/dependency_analyzer.py`
|
|
93
|
+
- `src/sourcecode/detectors/java.py`
|
|
94
|
+
- `src/sourcecode/prepare_context.py`
|
|
95
|
+
- `src/sourcecode/repository_ir.py`
|
|
96
|
+
- `src/sourcecode/summarizer.py`
|
|
97
|
+
|
|
98
|
+
## Untracked (not part of current work)
|
|
99
|
+
- `docs/PRODUCT_AUDIT.md`
|
|
100
|
+
|
|
101
|
+
---
|
|
102
|
+
|
|
103
|
+
## Resume
|
|
104
|
+
```
|
|
105
|
+
/gsd:resume-work
|
|
106
|
+
```
|
|
@@ -152,14 +152,15 @@ LAYER_PATTERNS: dict[str, dict[str, list[str]]] = {
|
|
|
152
152
|
|
|
153
153
|
# Higher value = wins when score ties
|
|
154
154
|
_PATTERN_PRIORITY: dict[str, int] = {
|
|
155
|
-
"cqrs":
|
|
156
|
-
"clean":
|
|
157
|
-
"onion":
|
|
158
|
-
"hexagonal":
|
|
159
|
-
"monorepo":
|
|
160
|
-
"
|
|
161
|
-
"
|
|
162
|
-
"
|
|
155
|
+
"cqrs": 8,
|
|
156
|
+
"clean": 7,
|
|
157
|
+
"onion": 6,
|
|
158
|
+
"hexagonal": 5,
|
|
159
|
+
"monorepo": 4,
|
|
160
|
+
"spring_mvc_layered": 3,
|
|
161
|
+
"mvc": 3,
|
|
162
|
+
"layered": 2,
|
|
163
|
+
"fullstack": 1,
|
|
163
164
|
}
|
|
164
165
|
|
|
165
166
|
|
|
@@ -248,9 +249,9 @@ class ArchitectureAnalyzer:
|
|
|
248
249
|
pattern, layers = self._detect_layers(filtered)
|
|
249
250
|
if pattern in (None, "flat", "unknown"):
|
|
250
251
|
if pattern == "flat":
|
|
251
|
-
limitations.append("
|
|
252
|
+
limitations.append("Layer pattern not detected: project has a flat directory structure")
|
|
252
253
|
elif pattern == "unknown":
|
|
253
|
-
limitations.append("
|
|
254
|
+
limitations.append("Unrecognized layer pattern: directory structure has no clear architectural signals")
|
|
254
255
|
|
|
255
256
|
# Step 3b: monorepo override — workspace config is hard evidence.
|
|
256
257
|
# Overrides all weak inferred patterns; only truly specialised patterns
|
|
@@ -269,7 +270,7 @@ class ArchitectureAnalyzer:
|
|
|
269
270
|
pattern = "monorepo"
|
|
270
271
|
layers = mono_layers
|
|
271
272
|
limitations.append(
|
|
272
|
-
"Workspace config
|
|
273
|
+
"Workspace config detected — architecture reflects package topology"
|
|
273
274
|
)
|
|
274
275
|
ws_files = [p for p in sm.file_paths if p.split("/")[-1] in _WORKSPACE_CONFIG_FILES]
|
|
275
276
|
evidence.append({
|
|
@@ -570,28 +571,76 @@ class ArchitectureAnalyzer:
|
|
|
570
571
|
))
|
|
571
572
|
return best_pattern, layers
|
|
572
573
|
|
|
573
|
-
# 2.
|
|
574
|
+
# 2. Spring domain-module detection (petclinic-style: deep common prefix + feature dirs)
|
|
575
|
+
spring_result = self._detect_spring_domain_modules(source_paths)
|
|
576
|
+
if spring_result is not None:
|
|
577
|
+
return spring_result
|
|
578
|
+
|
|
579
|
+
# 3. Microservices structural detection (before file-naming heuristics)
|
|
574
580
|
microservices_result = self._detect_microservices(source_paths)
|
|
575
581
|
if microservices_result is not None:
|
|
576
582
|
return microservices_result
|
|
577
583
|
|
|
578
|
-
#
|
|
584
|
+
# 5. Functional file-naming heuristic: *_analyzer.py, cli.py, schema.py, …
|
|
579
585
|
func_result = self._detect_layered_functional(source_paths)
|
|
580
586
|
if func_result is not None:
|
|
581
587
|
return func_result
|
|
582
588
|
|
|
583
|
-
#
|
|
589
|
+
# 6. Modular sub-package heuristic: ≥2 distinct named sub-packages
|
|
584
590
|
modular_result = self._detect_modular(source_paths)
|
|
585
591
|
if modular_result is not None:
|
|
586
592
|
return modular_result
|
|
587
593
|
|
|
588
|
-
#
|
|
594
|
+
# 7. Fallback: flat (shallow) vs truly unknown (deep but unrecognised)
|
|
589
595
|
max_depth = max(
|
|
590
596
|
(len(p.replace("\\", "/").split("/")) - 1 for p in source_paths),
|
|
591
597
|
default=0,
|
|
592
598
|
)
|
|
593
599
|
return ("flat" if max_depth <= 2 else "unknown"), []
|
|
594
600
|
|
|
601
|
+
def _detect_spring_domain_modules(
|
|
602
|
+
self, paths: list[str]
|
|
603
|
+
) -> Optional[tuple[str, list[ArchitectureLayer]]]:
|
|
604
|
+
"""Detect Spring Boot domain-organized packages (petclinic-style).
|
|
605
|
+
|
|
606
|
+
When all source paths share a deep common package prefix
|
|
607
|
+
(e.g. src/main/java/org/springframework/samples/petclinic/),
|
|
608
|
+
strips that prefix and detects feature/domain modules in the remainder.
|
|
609
|
+
Requires ≥3 distinct domain directories to avoid false positives.
|
|
610
|
+
"""
|
|
611
|
+
if len(paths) < 6:
|
|
612
|
+
return None
|
|
613
|
+
|
|
614
|
+
parts_list = [p.replace("\\", "/").split("/") for p in paths]
|
|
615
|
+
min_depth = min(len(p) for p in parts_list)
|
|
616
|
+
common_depth = 0
|
|
617
|
+
for i in range(min_depth - 1):
|
|
618
|
+
seg = parts_list[0][i]
|
|
619
|
+
if all(pl[i] == seg for pl in parts_list):
|
|
620
|
+
common_depth = i + 1
|
|
621
|
+
else:
|
|
622
|
+
break
|
|
623
|
+
|
|
624
|
+
if common_depth < 3:
|
|
625
|
+
return None
|
|
626
|
+
|
|
627
|
+
module_files: dict[str, list[str]] = {}
|
|
628
|
+
for orig, pl in zip(paths, parts_list):
|
|
629
|
+
remaining = pl[common_depth:]
|
|
630
|
+
if remaining and remaining[0] not in _GENERIC_NAMES:
|
|
631
|
+
module_files.setdefault(remaining[0], []).append(orig)
|
|
632
|
+
|
|
633
|
+
meaningful = {k: v for k, v in module_files.items() if len(v) >= 2}
|
|
634
|
+
if len(meaningful) < 3:
|
|
635
|
+
return None
|
|
636
|
+
|
|
637
|
+
return "spring_mvc_layered", [
|
|
638
|
+
ArchitectureLayer(
|
|
639
|
+
name=k, pattern="spring_mvc_layered", files=v, confidence="medium"
|
|
640
|
+
)
|
|
641
|
+
for k, v in meaningful.items()
|
|
642
|
+
]
|
|
643
|
+
|
|
595
644
|
def _detect_microservices(
|
|
596
645
|
self, paths: list[str]
|
|
597
646
|
) -> Optional[tuple[str, list[ArchitectureLayer]]]:
|
|
@@ -118,6 +118,10 @@ class TypeClassifier:
|
|
|
118
118
|
):
|
|
119
119
|
return "webapp"
|
|
120
120
|
|
|
121
|
+
_SERVERSIDE_TEMPLATE_FRAMEWORKS = frozenset({"Thymeleaf", "FreeMarker"})
|
|
122
|
+
if framework_names & _SERVERSIDE_TEMPLATE_FRAMEWORKS:
|
|
123
|
+
return "web_mvc"
|
|
124
|
+
|
|
121
125
|
if framework_names & _API_FRAMEWORKS:
|
|
122
126
|
return "api"
|
|
123
127
|
|
|
@@ -140,7 +140,21 @@ def _check_pipeline_coherence(sm: "SourceMap") -> list[str]: # type: ignore[nam
|
|
|
140
140
|
|
|
141
141
|
return issues
|
|
142
142
|
|
|
143
|
-
|
|
143
|
+
def _build_help_text() -> str:
|
|
144
|
+
"""Build --help text dynamically based on current license state."""
|
|
145
|
+
try:
|
|
146
|
+
from sourcecode.license import is_pro as _is_pro
|
|
147
|
+
except Exception:
|
|
148
|
+
_is_pro = False
|
|
149
|
+
|
|
150
|
+
if _is_pro:
|
|
151
|
+
plan_badge = "[bold green]● Pro[/bold green]"
|
|
152
|
+
else:
|
|
153
|
+
plan_badge = "[yellow]Free[/yellow] · [dim]sourcecode activate <key>[/dim] to unlock Pro"
|
|
154
|
+
|
|
155
|
+
text = f"""\
|
|
156
|
+
[bold]sourcecode[/bold] {plan_badge}
|
|
157
|
+
|
|
144
158
|
Deterministic codebase context for AI coding agents.
|
|
145
159
|
|
|
146
160
|
[bold]Primary usage:[/bold]
|
|
@@ -164,6 +178,26 @@ Deterministic codebase context for AI coding agents.
|
|
|
164
178
|
version
|
|
165
179
|
"""
|
|
166
180
|
|
|
181
|
+
if not _is_pro:
|
|
182
|
+
text += """\
|
|
183
|
+
|
|
184
|
+
[dim bold]Locked (Pro):[/dim bold]
|
|
185
|
+
[dim]impact blast radius before any change[/dim]
|
|
186
|
+
[dim]modernize (full) dead zones, tangles, full coupling[/dim]
|
|
187
|
+
[dim]fix-bug (full) complete risk-ranked file list[/dim]
|
|
188
|
+
[dim]review-pr (expanded) CI-grade PR review[/dim]
|
|
189
|
+
[dim]prepare-context delta incremental context for CI/CD[/dim]
|
|
190
|
+
[dim]prepare-context generate-tests test gap analysis[/dim]
|
|
191
|
+
[dim]--full removes all truncation limits[/dim]
|
|
192
|
+
|
|
193
|
+
[dim cyan]→ sourcecode activate <key>[/dim cyan]
|
|
194
|
+
"""
|
|
195
|
+
|
|
196
|
+
return text
|
|
197
|
+
|
|
198
|
+
|
|
199
|
+
_HELP = _build_help_text()
|
|
200
|
+
|
|
167
201
|
# Known subcommand names — tokens matching these are routed as subcommands,
|
|
168
202
|
# not consumed as a repository path.
|
|
169
203
|
_SUBCOMMANDS: frozenset[str] = frozenset(
|
|
@@ -344,6 +378,10 @@ def _get_command_with_preprocessing(typer_instance: Any) -> Any:
|
|
|
344
378
|
cmd = _orig_get_command(typer_instance)
|
|
345
379
|
if typer_instance is not app:
|
|
346
380
|
return cmd # only wrap the root app, not telemetry_app etc.
|
|
381
|
+
|
|
382
|
+
# Refresh help text at invocation time so it reflects current license state.
|
|
383
|
+
cmd.help = _build_help_text()
|
|
384
|
+
|
|
347
385
|
_orig_cmd_main = cmd.main
|
|
348
386
|
|
|
349
387
|
def _cmd_main(args: Optional[list[str]] = None, **kwargs: Any) -> Any:
|
|
@@ -2011,6 +2049,15 @@ def main(
|
|
|
2011
2049
|
except Exception:
|
|
2012
2050
|
pass # non-fatal: cache write failure
|
|
2013
2051
|
|
|
2052
|
+
# Update RIS with aggregated snapshot data (non-fatal side-effect).
|
|
2053
|
+
if not no_cache and not _pipeline_error and _core_key:
|
|
2054
|
+
try:
|
|
2055
|
+
from sourcecode.serializer import core_view as _ris_core_view
|
|
2056
|
+
from sourcecode.ris import maybe_update_ris as _ris_update
|
|
2057
|
+
_ris_update(target, _ris_core_view(sm), _git_sha)
|
|
2058
|
+
except Exception:
|
|
2059
|
+
pass
|
|
2060
|
+
|
|
2014
2061
|
if _pipeline_error:
|
|
2015
2062
|
raise typer.Exit(code=2)
|
|
2016
2063
|
|
|
@@ -3147,6 +3194,14 @@ def endpoints_cmd(
|
|
|
3147
3194
|
raise typer.Exit(code=1)
|
|
3148
3195
|
|
|
3149
3196
|
data = _extract_java_endpoints(target)
|
|
3197
|
+
|
|
3198
|
+
# Update RIS api_surface section (non-fatal side-effect).
|
|
3199
|
+
try:
|
|
3200
|
+
from sourcecode.ris import update_ris_api_surface as _ris_ep
|
|
3201
|
+
_ris_ep(target, data)
|
|
3202
|
+
except Exception:
|
|
3203
|
+
pass
|
|
3204
|
+
|
|
3150
3205
|
output = _serialize_dict(data, format)
|
|
3151
3206
|
|
|
3152
3207
|
if output_path is not None:
|
|
@@ -3824,7 +3879,7 @@ def mcp_init(
|
|
|
3824
3879
|
raise typer.Exit(code=1)
|
|
3825
3880
|
|
|
3826
3881
|
typer.echo("MCP integration active.")
|
|
3827
|
-
typer.echo(" Note: repo_path
|
|
3882
|
+
typer.echo(" Note: repo_path must use forward slashes: C:/Users/... or /unix/path")
|
|
3828
3883
|
typer.echo("")
|
|
3829
3884
|
|
|
3830
3885
|
# Post-write: validate config and warn if client not running
|
|
@@ -3976,7 +4031,7 @@ def mcp_status() -> None:
|
|
|
3976
4031
|
typer.echo(sep)
|
|
3977
4032
|
typer.echo(" Note: 'configured' and 'running' are checked independently.")
|
|
3978
4033
|
typer.echo(" A running app still needs restart after first-time config.")
|
|
3979
|
-
typer.echo(" Path: repo_path
|
|
4034
|
+
typer.echo(" Path: repo_path must use forward slashes: C:/Users/... or /unix/path")
|
|
3980
4035
|
typer.echo(" Setup: sourcecode mcp init")
|
|
3981
4036
|
typer.echo(" Remove: sourcecode mcp remove")
|
|
3982
4037
|
|
|
@@ -1118,7 +1118,7 @@ class DependencyAnalyzer:
|
|
|
1118
1118
|
try:
|
|
1119
1119
|
tree = ET.parse(pom)
|
|
1120
1120
|
except (ET.ParseError, OSError):
|
|
1121
|
-
return [], ["java: error
|
|
1121
|
+
return [], ["java: error parsing pom.xml"]
|
|
1122
1122
|
|
|
1123
1123
|
root_elem = tree.getroot()
|
|
1124
1124
|
ns_match = re.match(r"\{[^}]+\}", root_elem.tag)
|
|
@@ -1217,10 +1217,10 @@ class DependencyAnalyzer:
|
|
|
1217
1217
|
try:
|
|
1218
1218
|
content = gradle_file.read_text(encoding="utf-8", errors="replace")
|
|
1219
1219
|
except OSError:
|
|
1220
|
-
return [], [f"gradle: error
|
|
1220
|
+
return [], [f"gradle: error reading {filename}"]
|
|
1221
1221
|
props = self._parse_gradle_properties(root, content)
|
|
1222
1222
|
records = self._parse_gradle_dependencies(content, props, filename)
|
|
1223
|
-
return records, ["gradle:
|
|
1223
|
+
return records, ["gradle: no compatible lockfile found; transitive dependencies unavailable"]
|
|
1224
1224
|
return [], []
|
|
1225
1225
|
|
|
1226
1226
|
def _parse_gradle_properties(self, root: Path, content: str) -> dict[str, str]:
|
|
@@ -23,6 +23,7 @@ _MAX_ANNOTATION_ENTRY_POINTS = 1000
|
|
|
23
23
|
_REST_CONTROLLER_RE = re.compile(r'@RestController\b')
|
|
24
24
|
_MVC_CONTROLLER_RE = re.compile(r'@Controller\b')
|
|
25
25
|
_REQUEST_MAPPING_RE = re.compile(r'@RequestMapping\b')
|
|
26
|
+
_ANY_MAPPING_RE = re.compile(r'@(?:Request|Get|Post|Put|Delete|Patch)Mapping\b')
|
|
26
27
|
_CONTROLLER_ADVICE_RE = re.compile(r'@ControllerAdvice\b')
|
|
27
28
|
_WEB_FILTER_RE = re.compile(r'@WebFilter\b')
|
|
28
29
|
_FILTER_BEAN_RE = re.compile(r'FilterRegistrationBean\b')
|
|
@@ -298,6 +299,10 @@ class JavaDetector(AbstractDetector):
|
|
|
298
299
|
frameworks.append(FrameworkDetection(name="Jakarta EE", source=source))
|
|
299
300
|
if "mybatis" in text:
|
|
300
301
|
frameworks.append(FrameworkDetection(name="MyBatis", source=source))
|
|
302
|
+
if "thymeleaf" in text:
|
|
303
|
+
frameworks.append(FrameworkDetection(name="Thymeleaf", source=source))
|
|
304
|
+
if "freemarker" in text:
|
|
305
|
+
frameworks.append(FrameworkDetection(name="FreeMarker", source=source))
|
|
301
306
|
if "spring-boot-starter-security" in text or "spring-security-core" in text:
|
|
302
307
|
frameworks.append(FrameworkDetection(name="Spring Security", source=source))
|
|
303
308
|
if "spring-boot-starter-data-jpa" in text or "spring-data-jpa" in text:
|
|
@@ -470,7 +475,7 @@ class JavaDetector(AbstractDetector):
|
|
|
470
475
|
path=rel_path, stack="java", kind="exception_handler",
|
|
471
476
|
source="annotation", confidence="medium",
|
|
472
477
|
)]
|
|
473
|
-
if _MVC_CONTROLLER_RE.search(content) and
|
|
478
|
+
if _MVC_CONTROLLER_RE.search(content) and _ANY_MAPPING_RE.search(content):
|
|
474
479
|
http_path_match = _HTTP_PATH_RE.search(content)
|
|
475
480
|
http_path = http_path_match.group(1) if http_path_match else None
|
|
476
481
|
verb_match = _REQUEST_METHOD_VERB_RE.search(content)
|
|
@@ -109,6 +109,42 @@ def _check_repo_path(path: str) -> "CallToolResult | None":
|
|
|
109
109
|
return None
|
|
110
110
|
|
|
111
111
|
|
|
112
|
+
@mcp.tool()
|
|
113
|
+
def get_cold_start_context(repo_path: str = ".") -> dict:
|
|
114
|
+
"""Instant session bootstrap from persisted Repository Intelligence Snapshot (RIS).
|
|
115
|
+
|
|
116
|
+
CALL THIS FIRST at the start of every MCP session. Returns cached structural
|
|
117
|
+
context built from prior analysis runs — zero re-analysis cost.
|
|
118
|
+
|
|
119
|
+
status values:
|
|
120
|
+
"cold_start_ready" — RIS exists and matches the current git HEAD.
|
|
121
|
+
"cold_start_stale" — RIS exists but HEAD has changed since last analysis.
|
|
122
|
+
Data is still useful; run get_compact_context to refresh.
|
|
123
|
+
"no_ris" — No RIS yet for this repo; run get_compact_context first.
|
|
124
|
+
|
|
125
|
+
Returns: status, repo_id, git_head, stale (bool), last_updated_at,
|
|
126
|
+
summary (compact snapshot), entrypoints, endpoints, hotspots.
|
|
127
|
+
|
|
128
|
+
repo_path: absolute path to the repository (default: current working directory).
|
|
129
|
+
"""
|
|
130
|
+
_raw = repo_path
|
|
131
|
+
try:
|
|
132
|
+
if not isinstance(repo_path, str):
|
|
133
|
+
return _err("repo_path must be a string", "INVALID_ARGUMENT")
|
|
134
|
+
repo_path = _normalize_repo_path(repo_path)
|
|
135
|
+
_path_err = _check_repo_path(repo_path)
|
|
136
|
+
if _path_err is not None:
|
|
137
|
+
return _path_err
|
|
138
|
+
from pathlib import Path as _Path
|
|
139
|
+
from sourcecode.ris import get_cold_start_context as _gcs
|
|
140
|
+
return _ok(_gcs(_Path(repo_path)))
|
|
141
|
+
except Exception as exc:
|
|
142
|
+
return _err(
|
|
143
|
+
f"Internal error: {type(exc).__name__}: {exc} — repo_path: {_raw}",
|
|
144
|
+
"INTERNAL_ERROR",
|
|
145
|
+
)
|
|
146
|
+
|
|
147
|
+
|
|
112
148
|
@mcp.tool()
|
|
113
149
|
def get_compact_context(repo_path: str = ".", git_context: bool = False) -> dict:
|
|
114
150
|
"""Compact human/LLM summary of a repository (~1000-3000 tokens). USE THIS FIRST.
|
|
@@ -981,12 +981,18 @@ class TaskContextBuilder:
|
|
|
981
981
|
|
|
982
982
|
dep_records, dep_summary = DependencyAnalyzer().analyze(self.root)
|
|
983
983
|
primary_eco = stacks[0].stack if stacks else ""
|
|
984
|
-
|
|
984
|
+
_direct_raw = [
|
|
985
985
|
d for d in dep_records
|
|
986
986
|
if d.scope != "transitive" and d.source in {"manifest", "lockfile"}
|
|
987
987
|
and (d.role or "unknown") in {"runtime", "parsing", "serialization", "observability", "infra"}
|
|
988
988
|
and d.scope not in {"dev"}
|
|
989
989
|
]
|
|
990
|
+
_seen_dep: set[str] = set()
|
|
991
|
+
direct = []
|
|
992
|
+
for _d in _direct_raw:
|
|
993
|
+
if _d.name not in _seen_dep:
|
|
994
|
+
_seen_dep.add(_d.name)
|
|
995
|
+
direct.append(_d)
|
|
990
996
|
# Rank by framework centrality: core infra (ORM, Spring) > serialization > other.
|
|
991
997
|
# Penalise vendored tooling (closure-compiler, shaded utilities) so that
|
|
992
998
|
# Hibernate/JPA/Solr appear before minor build-time dependencies.
|
|
@@ -1697,6 +1697,9 @@ def _canonical_subsystem_pkg(fqn: str) -> str:
|
|
|
1697
1697
|
(even if uppercase) to force at least 2-segment grouping.
|
|
1698
1698
|
"""
|
|
1699
1699
|
_TOP_LEVEL = {"com", "org", "net", "io", "java", "javax"}
|
|
1700
|
+
# Well-known framework namespaces that are not application boundaries;
|
|
1701
|
+
# go one level deeper (depth 5) so callers get the actual app module.
|
|
1702
|
+
_FRAMEWORK_NS = {"springframework", "apache", "eclipse", "google", "jetbrains"}
|
|
1700
1703
|
parts: list[str] = []
|
|
1701
1704
|
for segment in fqn.split("."):
|
|
1702
1705
|
if "#" in segment or (segment and segment[0].isupper()):
|
|
@@ -1705,6 +1708,8 @@ def _canonical_subsystem_pkg(fqn: str) -> str:
|
|
|
1705
1708
|
if not parts:
|
|
1706
1709
|
return fqn.rsplit(".", 1)[0] if "." in fqn else fqn
|
|
1707
1710
|
if parts[0] in _TOP_LEVEL and len(parts) >= 3:
|
|
1711
|
+
if len(parts) >= 5 and len(parts) > 3 and parts[1] in _FRAMEWORK_NS:
|
|
1712
|
+
return ".".join(parts[:5])
|
|
1708
1713
|
return ".".join(parts[:3])
|
|
1709
1714
|
# Prevent bare TLD collapse: "org" or "com" alone as subsystem key is meaningless
|
|
1710
1715
|
# and groups ALL classes under that TLD into a single giant component.
|
|
@@ -3338,7 +3343,7 @@ def compute_blast_radius(
|
|
|
3338
3343
|
_seen_mapper_fqns.add(fqn)
|
|
3339
3344
|
_mapper_entry: dict = {
|
|
3340
3345
|
"fqn": fqn,
|
|
3341
|
-
"role": role or "mapper",
|
|
3346
|
+
"role": role or ("mapper" if symbol_kind == "mapper_interface" else "repository"),
|
|
3342
3347
|
"source_file": node_dict.get("source_file") or "",
|
|
3343
3348
|
}
|
|
3344
3349
|
if canonical != fqn:
|