sourcecode 1.31.3__tar.gz → 1.31.5__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.
Files changed (212) hide show
  1. {sourcecode-1.31.3 → sourcecode-1.31.5}/PKG-INFO +3 -3
  2. {sourcecode-1.31.3 → sourcecode-1.31.5}/README.md +2 -2
  3. {sourcecode-1.31.3 → sourcecode-1.31.5}/pyproject.toml +1 -1
  4. {sourcecode-1.31.3 → sourcecode-1.31.5}/src/sourcecode/__init__.py +1 -1
  5. {sourcecode-1.31.3 → sourcecode-1.31.5}/src/sourcecode/cli.py +121 -39
  6. {sourcecode-1.31.3 → sourcecode-1.31.5}/src/sourcecode/detectors/heuristic.py +6 -1
  7. {sourcecode-1.31.3 → sourcecode-1.31.5}/src/sourcecode/prepare_context.py +67 -4
  8. {sourcecode-1.31.3 → sourcecode-1.31.5}/src/sourcecode/serializer.py +8 -2
  9. sourcecode-1.31.5/tests/test_bug_fixes_v1313.py +350 -0
  10. {sourcecode-1.31.3 → sourcecode-1.31.5}/.agents/skills/source-command-gsd-join-discord/SKILL.md +0 -0
  11. {sourcecode-1.31.3 → sourcecode-1.31.5}/.agents/skills/source-command-gsd-review-backlog/SKILL.md +0 -0
  12. {sourcecode-1.31.3 → sourcecode-1.31.5}/.agents/skills/source-command-gsd-workstreams/SKILL.md +0 -0
  13. {sourcecode-1.31.3 → sourcecode-1.31.5}/.continue-here.md +0 -0
  14. {sourcecode-1.31.3 → sourcecode-1.31.5}/.github/workflows/build-windows.yml +0 -0
  15. {sourcecode-1.31.3 → sourcecode-1.31.5}/.gitignore +0 -0
  16. {sourcecode-1.31.3 → sourcecode-1.31.5}/.ruff.toml +0 -0
  17. {sourcecode-1.31.3 → sourcecode-1.31.5}/CHANGELOG.md +0 -0
  18. {sourcecode-1.31.3 → sourcecode-1.31.5}/CONTRIBUTING.md +0 -0
  19. {sourcecode-1.31.3 → sourcecode-1.31.5}/LICENSE +0 -0
  20. {sourcecode-1.31.3 → sourcecode-1.31.5}/SECURITY.md +0 -0
  21. {sourcecode-1.31.3 → sourcecode-1.31.5}/docs/privacy.md +0 -0
  22. {sourcecode-1.31.3 → sourcecode-1.31.5}/docs/schema.md +0 -0
  23. {sourcecode-1.31.3 → sourcecode-1.31.5}/raw +0 -0
  24. {sourcecode-1.31.3 → sourcecode-1.31.5}/run_cli.py +0 -0
  25. {sourcecode-1.31.3 → sourcecode-1.31.5}/src/sourcecode/adaptive_scanner.py +0 -0
  26. {sourcecode-1.31.3 → sourcecode-1.31.5}/src/sourcecode/architecture_analyzer.py +0 -0
  27. {sourcecode-1.31.3 → sourcecode-1.31.5}/src/sourcecode/architecture_summary.py +0 -0
  28. {sourcecode-1.31.3 → sourcecode-1.31.5}/src/sourcecode/ast_extractor.py +0 -0
  29. {sourcecode-1.31.3 → sourcecode-1.31.5}/src/sourcecode/classifier.py +0 -0
  30. {sourcecode-1.31.3 → sourcecode-1.31.5}/src/sourcecode/code_notes_analyzer.py +0 -0
  31. {sourcecode-1.31.3 → sourcecode-1.31.5}/src/sourcecode/confidence_analyzer.py +0 -0
  32. {sourcecode-1.31.3 → sourcecode-1.31.5}/src/sourcecode/context_scorer.py +0 -0
  33. {sourcecode-1.31.3 → sourcecode-1.31.5}/src/sourcecode/context_summarizer.py +0 -0
  34. {sourcecode-1.31.3 → sourcecode-1.31.5}/src/sourcecode/contract_model.py +0 -0
  35. {sourcecode-1.31.3 → sourcecode-1.31.5}/src/sourcecode/contract_pipeline.py +0 -0
  36. {sourcecode-1.31.3 → sourcecode-1.31.5}/src/sourcecode/coverage_parser.py +0 -0
  37. {sourcecode-1.31.3 → sourcecode-1.31.5}/src/sourcecode/dependency_analyzer.py +0 -0
  38. {sourcecode-1.31.3 → sourcecode-1.31.5}/src/sourcecode/detectors/__init__.py +0 -0
  39. {sourcecode-1.31.3 → sourcecode-1.31.5}/src/sourcecode/detectors/base.py +0 -0
  40. {sourcecode-1.31.3 → sourcecode-1.31.5}/src/sourcecode/detectors/csproj_parser.py +0 -0
  41. {sourcecode-1.31.3 → sourcecode-1.31.5}/src/sourcecode/detectors/dart.py +0 -0
  42. {sourcecode-1.31.3 → sourcecode-1.31.5}/src/sourcecode/detectors/dotnet.py +0 -0
  43. {sourcecode-1.31.3 → sourcecode-1.31.5}/src/sourcecode/detectors/elixir.py +0 -0
  44. {sourcecode-1.31.3 → sourcecode-1.31.5}/src/sourcecode/detectors/go.py +0 -0
  45. {sourcecode-1.31.3 → sourcecode-1.31.5}/src/sourcecode/detectors/hybrid.py +0 -0
  46. {sourcecode-1.31.3 → sourcecode-1.31.5}/src/sourcecode/detectors/java.py +0 -0
  47. {sourcecode-1.31.3 → sourcecode-1.31.5}/src/sourcecode/detectors/jvm_ext.py +0 -0
  48. {sourcecode-1.31.3 → sourcecode-1.31.5}/src/sourcecode/detectors/nodejs.py +0 -0
  49. {sourcecode-1.31.3 → sourcecode-1.31.5}/src/sourcecode/detectors/parsers.py +0 -0
  50. {sourcecode-1.31.3 → sourcecode-1.31.5}/src/sourcecode/detectors/php.py +0 -0
  51. {sourcecode-1.31.3 → sourcecode-1.31.5}/src/sourcecode/detectors/project.py +0 -0
  52. {sourcecode-1.31.3 → sourcecode-1.31.5}/src/sourcecode/detectors/python.py +0 -0
  53. {sourcecode-1.31.3 → sourcecode-1.31.5}/src/sourcecode/detectors/ruby.py +0 -0
  54. {sourcecode-1.31.3 → sourcecode-1.31.5}/src/sourcecode/detectors/rust.py +0 -0
  55. {sourcecode-1.31.3 → sourcecode-1.31.5}/src/sourcecode/detectors/systems.py +0 -0
  56. {sourcecode-1.31.3 → sourcecode-1.31.5}/src/sourcecode/detectors/terraform.py +0 -0
  57. {sourcecode-1.31.3 → sourcecode-1.31.5}/src/sourcecode/detectors/tooling.py +0 -0
  58. {sourcecode-1.31.3 → sourcecode-1.31.5}/src/sourcecode/doc_analyzer.py +0 -0
  59. {sourcecode-1.31.3 → sourcecode-1.31.5}/src/sourcecode/entrypoint_classifier.py +0 -0
  60. {sourcecode-1.31.3 → sourcecode-1.31.5}/src/sourcecode/env_analyzer.py +0 -0
  61. {sourcecode-1.31.3 → sourcecode-1.31.5}/src/sourcecode/file_classifier.py +0 -0
  62. {sourcecode-1.31.3 → sourcecode-1.31.5}/src/sourcecode/flow_analyzer.py +0 -0
  63. {sourcecode-1.31.3 → sourcecode-1.31.5}/src/sourcecode/git_analyzer.py +0 -0
  64. {sourcecode-1.31.3 → sourcecode-1.31.5}/src/sourcecode/graph_analyzer.py +0 -0
  65. {sourcecode-1.31.3 → sourcecode-1.31.5}/src/sourcecode/mcp/__init__.py +0 -0
  66. {sourcecode-1.31.3 → sourcecode-1.31.5}/src/sourcecode/mcp/onboarding/__init__.py +0 -0
  67. {sourcecode-1.31.3 → sourcecode-1.31.5}/src/sourcecode/mcp/onboarding/applier.py +0 -0
  68. {sourcecode-1.31.3 → sourcecode-1.31.5}/src/sourcecode/mcp/onboarding/backup.py +0 -0
  69. {sourcecode-1.31.3 → sourcecode-1.31.5}/src/sourcecode/mcp/onboarding/detector.py +0 -0
  70. {sourcecode-1.31.3 → sourcecode-1.31.5}/src/sourcecode/mcp/onboarding/planner.py +0 -0
  71. {sourcecode-1.31.3 → sourcecode-1.31.5}/src/sourcecode/mcp/runner.py +0 -0
  72. {sourcecode-1.31.3 → sourcecode-1.31.5}/src/sourcecode/mcp/server.py +0 -0
  73. {sourcecode-1.31.3 → sourcecode-1.31.5}/src/sourcecode/metrics_analyzer.py +0 -0
  74. {sourcecode-1.31.3 → sourcecode-1.31.5}/src/sourcecode/pr_comment_renderer.py +0 -0
  75. {sourcecode-1.31.3 → sourcecode-1.31.5}/src/sourcecode/progress.py +0 -0
  76. {sourcecode-1.31.3 → sourcecode-1.31.5}/src/sourcecode/ranking_engine.py +0 -0
  77. {sourcecode-1.31.3 → sourcecode-1.31.5}/src/sourcecode/redactor.py +0 -0
  78. {sourcecode-1.31.3 → sourcecode-1.31.5}/src/sourcecode/relevance_scorer.py +0 -0
  79. {sourcecode-1.31.3 → sourcecode-1.31.5}/src/sourcecode/repo_classifier.py +0 -0
  80. {sourcecode-1.31.3 → sourcecode-1.31.5}/src/sourcecode/repository_ir.py +0 -0
  81. {sourcecode-1.31.3 → sourcecode-1.31.5}/src/sourcecode/runtime_classifier.py +0 -0
  82. {sourcecode-1.31.3 → sourcecode-1.31.5}/src/sourcecode/scanner.py +0 -0
  83. {sourcecode-1.31.3 → sourcecode-1.31.5}/src/sourcecode/schema.py +0 -0
  84. {sourcecode-1.31.3 → sourcecode-1.31.5}/src/sourcecode/semantic_analyzer.py +0 -0
  85. {sourcecode-1.31.3 → sourcecode-1.31.5}/src/sourcecode/summarizer.py +0 -0
  86. {sourcecode-1.31.3 → sourcecode-1.31.5}/src/sourcecode/telemetry/__init__.py +0 -0
  87. {sourcecode-1.31.3 → sourcecode-1.31.5}/src/sourcecode/telemetry/config.py +0 -0
  88. {sourcecode-1.31.3 → sourcecode-1.31.5}/src/sourcecode/telemetry/consent.py +0 -0
  89. {sourcecode-1.31.3 → sourcecode-1.31.5}/src/sourcecode/telemetry/events.py +0 -0
  90. {sourcecode-1.31.3 → sourcecode-1.31.5}/src/sourcecode/telemetry/filters.py +0 -0
  91. {sourcecode-1.31.3 → sourcecode-1.31.5}/src/sourcecode/telemetry/transport.py +0 -0
  92. {sourcecode-1.31.3 → sourcecode-1.31.5}/src/sourcecode/tree_utils.py +0 -0
  93. {sourcecode-1.31.3 → sourcecode-1.31.5}/src/sourcecode/workspace.py +0 -0
  94. {sourcecode-1.31.3 → sourcecode-1.31.5}/tests/__init__.py +0 -0
  95. {sourcecode-1.31.3 → sourcecode-1.31.5}/tests/conftest.py +0 -0
  96. {sourcecode-1.31.3 → sourcecode-1.31.5}/tests/fixtures/coverage.xml +0 -0
  97. {sourcecode-1.31.3 → sourcecode-1.31.5}/tests/fixtures/fastapi_app/pyproject.toml +0 -0
  98. {sourcecode-1.31.3 → sourcecode-1.31.5}/tests/fixtures/fastapi_app/src/main.py +0 -0
  99. {sourcecode-1.31.3 → sourcecode-1.31.5}/tests/fixtures/go_service/cmd/api/main.go +0 -0
  100. {sourcecode-1.31.3 → sourcecode-1.31.5}/tests/fixtures/go_service/go.mod +0 -0
  101. {sourcecode-1.31.3 → sourcecode-1.31.5}/tests/fixtures/jacoco.xml +0 -0
  102. {sourcecode-1.31.3 → sourcecode-1.31.5}/tests/fixtures/latin1_sample.java +0 -0
  103. {sourcecode-1.31.3 → sourcecode-1.31.5}/tests/fixtures/latin1_sample_iso.java +0 -0
  104. {sourcecode-1.31.3 → sourcecode-1.31.5}/tests/fixtures/lcov.info +0 -0
  105. {sourcecode-1.31.3 → sourcecode-1.31.5}/tests/fixtures/nextjs_app/app/page.tsx +0 -0
  106. {sourcecode-1.31.3 → sourcecode-1.31.5}/tests/fixtures/nextjs_app/package.json +0 -0
  107. {sourcecode-1.31.3 → sourcecode-1.31.5}/tests/fixtures/nextjs_app/pnpm-lock.yaml +0 -0
  108. {sourcecode-1.31.3 → sourcecode-1.31.5}/tests/fixtures/pnpm_monorepo/apps/web/app/page.tsx +0 -0
  109. {sourcecode-1.31.3 → sourcecode-1.31.5}/tests/fixtures/pnpm_monorepo/apps/web/package.json +0 -0
  110. {sourcecode-1.31.3 → sourcecode-1.31.5}/tests/fixtures/pnpm_monorepo/packages/api/main.py +0 -0
  111. {sourcecode-1.31.3 → sourcecode-1.31.5}/tests/fixtures/pnpm_monorepo/packages/api/pyproject.toml +0 -0
  112. {sourcecode-1.31.3 → sourcecode-1.31.5}/tests/fixtures/pnpm_monorepo/pnpm-workspace.yaml +0 -0
  113. {sourcecode-1.31.3 → sourcecode-1.31.5}/tests/fixtures/spring_boot_minimal/pom.xml +0 -0
  114. {sourcecode-1.31.3 → sourcecode-1.31.5}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/ausente/application/service/FindAusenteService.java +0 -0
  115. {sourcecode-1.31.3 → sourcecode-1.31.5}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/ausente/domain/entities/Ausente.java +0 -0
  116. {sourcecode-1.31.3 → sourcecode-1.31.5}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/ausente/infrastructure/rest/AusenteRestController.java +0 -0
  117. {sourcecode-1.31.3 → sourcecode-1.31.5}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/autocoberturas/application/service/FindAutocoberturasService.java +0 -0
  118. {sourcecode-1.31.3 → sourcecode-1.31.5}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/autocoberturas/domain/entities/Autocoberturas.java +0 -0
  119. {sourcecode-1.31.3 → sourcecode-1.31.5}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/autocoberturas/infrastructure/rest/AutocoberturasRestController.java +0 -0
  120. {sourcecode-1.31.3 → sourcecode-1.31.5}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/calendarioTrabajador/application/service/FindCalendarioTrabajadorService.java +0 -0
  121. {sourcecode-1.31.3 → sourcecode-1.31.5}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/calendarioTrabajador/domain/entities/CalendarioTrabajador.java +0 -0
  122. {sourcecode-1.31.3 → sourcecode-1.31.5}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/calendarioTrabajador/infrastructure/rest/CalendarioTrabajadorRestController.java +0 -0
  123. {sourcecode-1.31.3 → sourcecode-1.31.5}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/departamento/application/service/FindDepartamentoService.java +0 -0
  124. {sourcecode-1.31.3 → sourcecode-1.31.5}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/departamento/domain/entities/Departamento.java +0 -0
  125. {sourcecode-1.31.3 → sourcecode-1.31.5}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/departamento/infrastructure/rest/DepartamentoRestController.java +0 -0
  126. {sourcecode-1.31.3 → sourcecode-1.31.5}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/empleado/application/service/FindEmpleadoService.java +0 -0
  127. {sourcecode-1.31.3 → sourcecode-1.31.5}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/empleado/domain/entities/Empleado.java +0 -0
  128. {sourcecode-1.31.3 → sourcecode-1.31.5}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/empleado/infrastructure/rest/EmpleadoRestController.java +0 -0
  129. {sourcecode-1.31.3 → sourcecode-1.31.5}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/demo/DemoApplication.java +0 -0
  130. {sourcecode-1.31.3 → sourcecode-1.31.5}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/demo/config/FilterConfig.java +0 -0
  131. {sourcecode-1.31.3 → sourcecode-1.31.5}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/demo/domain/Health.java +0 -0
  132. {sourcecode-1.31.3 → sourcecode-1.31.5}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/demo/mapper/HealthMapper.java +0 -0
  133. {sourcecode-1.31.3 → sourcecode-1.31.5}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/demo/repository/HealthRepository.java +0 -0
  134. {sourcecode-1.31.3 → sourcecode-1.31.5}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/demo/service/HealthService.java +0 -0
  135. {sourcecode-1.31.3 → sourcecode-1.31.5}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/demo/web/HealthRestController.java +0 -0
  136. {sourcecode-1.31.3 → sourcecode-1.31.5}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/demo/web/NominaRestController.java +0 -0
  137. {sourcecode-1.31.3 → sourcecode-1.31.5}/tests/fixtures/spring_boot_minimal/src/main/resources/application-dev.yml +0 -0
  138. {sourcecode-1.31.3 → sourcecode-1.31.5}/tests/fixtures/spring_boot_minimal/src/main/resources/application.yml +0 -0
  139. {sourcecode-1.31.3 → sourcecode-1.31.5}/tests/fixtures/spring_boot_minimal/src/main/resources/mapper/HealthMapper.xml +0 -0
  140. {sourcecode-1.31.3 → sourcecode-1.31.5}/tests/test_architecture_analyzer.py +0 -0
  141. {sourcecode-1.31.3 → sourcecode-1.31.5}/tests/test_architecture_summary.py +0 -0
  142. {sourcecode-1.31.3 → sourcecode-1.31.5}/tests/test_ast_extractor.py +0 -0
  143. {sourcecode-1.31.3 → sourcecode-1.31.5}/tests/test_block1_reliability.py +0 -0
  144. {sourcecode-1.31.3 → sourcecode-1.31.5}/tests/test_block2_coverage.py +0 -0
  145. {sourcecode-1.31.3 → sourcecode-1.31.5}/tests/test_block5_quality.py +0 -0
  146. {sourcecode-1.31.3 → sourcecode-1.31.5}/tests/test_bug_fixes_v1302.py +0 -0
  147. {sourcecode-1.31.3 → sourcecode-1.31.5}/tests/test_bug_fixes_v1312.py +0 -0
  148. {sourcecode-1.31.3 → sourcecode-1.31.5}/tests/test_bug_fixes_v16.py +0 -0
  149. {sourcecode-1.31.3 → sourcecode-1.31.5}/tests/test_bug_fixes_v2.py +0 -0
  150. {sourcecode-1.31.3 → sourcecode-1.31.5}/tests/test_classifier.py +0 -0
  151. {sourcecode-1.31.3 → sourcecode-1.31.5}/tests/test_cli.py +0 -0
  152. {sourcecode-1.31.3 → sourcecode-1.31.5}/tests/test_code_notes_analyzer.py +0 -0
  153. {sourcecode-1.31.3 → sourcecode-1.31.5}/tests/test_context_scorer.py +0 -0
  154. {sourcecode-1.31.3 → sourcecode-1.31.5}/tests/test_contract_pipeline.py +0 -0
  155. {sourcecode-1.31.3 → sourcecode-1.31.5}/tests/test_coverage_parser.py +0 -0
  156. {sourcecode-1.31.3 → sourcecode-1.31.5}/tests/test_cross_consistency.py +0 -0
  157. {sourcecode-1.31.3 → sourcecode-1.31.5}/tests/test_dependency_analyzer_node_python.py +0 -0
  158. {sourcecode-1.31.3 → sourcecode-1.31.5}/tests/test_dependency_analyzer_polyglot.py +0 -0
  159. {sourcecode-1.31.3 → sourcecode-1.31.5}/tests/test_dependency_schema.py +0 -0
  160. {sourcecode-1.31.3 → sourcecode-1.31.5}/tests/test_detector_dotnet.py +0 -0
  161. {sourcecode-1.31.3 → sourcecode-1.31.5}/tests/test_detector_go_rust_java.py +0 -0
  162. {sourcecode-1.31.3 → sourcecode-1.31.5}/tests/test_detector_nodejs.py +0 -0
  163. {sourcecode-1.31.3 → sourcecode-1.31.5}/tests/test_detector_php_ruby_dart.py +0 -0
  164. {sourcecode-1.31.3 → sourcecode-1.31.5}/tests/test_detector_python.py +0 -0
  165. {sourcecode-1.31.3 → sourcecode-1.31.5}/tests/test_detector_universal_managed.py +0 -0
  166. {sourcecode-1.31.3 → sourcecode-1.31.5}/tests/test_detector_universal_systems.py +0 -0
  167. {sourcecode-1.31.3 → sourcecode-1.31.5}/tests/test_detectors_base.py +0 -0
  168. {sourcecode-1.31.3 → sourcecode-1.31.5}/tests/test_doc_analyzer_jsdom.py +0 -0
  169. {sourcecode-1.31.3 → sourcecode-1.31.5}/tests/test_doc_analyzer_python.py +0 -0
  170. {sourcecode-1.31.3 → sourcecode-1.31.5}/tests/test_encoding_regression.py +0 -0
  171. {sourcecode-1.31.3 → sourcecode-1.31.5}/tests/test_graph_analyzer_polyglot.py +0 -0
  172. {sourcecode-1.31.3 → sourcecode-1.31.5}/tests/test_graph_analyzer_python_node.py +0 -0
  173. {sourcecode-1.31.3 → sourcecode-1.31.5}/tests/test_graph_schema.py +0 -0
  174. {sourcecode-1.31.3 → sourcecode-1.31.5}/tests/test_hybrid_inference.py +0 -0
  175. {sourcecode-1.31.3 → sourcecode-1.31.5}/tests/test_integration.py +0 -0
  176. {sourcecode-1.31.3 → sourcecode-1.31.5}/tests/test_integration_dependencies.py +0 -0
  177. {sourcecode-1.31.3 → sourcecode-1.31.5}/tests/test_integration_detection.py +0 -0
  178. {sourcecode-1.31.3 → sourcecode-1.31.5}/tests/test_integration_docs.py +0 -0
  179. {sourcecode-1.31.3 → sourcecode-1.31.5}/tests/test_integration_graph_modules.py +0 -0
  180. {sourcecode-1.31.3 → sourcecode-1.31.5}/tests/test_integration_lqn.py +0 -0
  181. {sourcecode-1.31.3 → sourcecode-1.31.5}/tests/test_integration_metrics.py +0 -0
  182. {sourcecode-1.31.3 → sourcecode-1.31.5}/tests/test_integration_multistack.py +0 -0
  183. {sourcecode-1.31.3 → sourcecode-1.31.5}/tests/test_integration_semantics.py +0 -0
  184. {sourcecode-1.31.3 → sourcecode-1.31.5}/tests/test_integration_universal.py +0 -0
  185. {sourcecode-1.31.3 → sourcecode-1.31.5}/tests/test_java_spring_integration.py +0 -0
  186. {sourcecode-1.31.3 → sourcecode-1.31.5}/tests/test_mcp_runner.py +0 -0
  187. {sourcecode-1.31.3 → sourcecode-1.31.5}/tests/test_mcp_serve.py +0 -0
  188. {sourcecode-1.31.3 → sourcecode-1.31.5}/tests/test_mcp_tools.py +0 -0
  189. {sourcecode-1.31.3 → sourcecode-1.31.5}/tests/test_metrics_analyzer.py +0 -0
  190. {sourcecode-1.31.3 → sourcecode-1.31.5}/tests/test_output_ux.py +0 -0
  191. {sourcecode-1.31.3 → sourcecode-1.31.5}/tests/test_packaging.py +0 -0
  192. {sourcecode-1.31.3 → sourcecode-1.31.5}/tests/test_phase1_improvements.py +0 -0
  193. {sourcecode-1.31.3 → sourcecode-1.31.5}/tests/test_pipeline_integrity.py +0 -0
  194. {sourcecode-1.31.3 → sourcecode-1.31.5}/tests/test_real_projects.py +0 -0
  195. {sourcecode-1.31.3 → sourcecode-1.31.5}/tests/test_redactor.py +0 -0
  196. {sourcecode-1.31.3 → sourcecode-1.31.5}/tests/test_repository_ir.py +0 -0
  197. {sourcecode-1.31.3 → sourcecode-1.31.5}/tests/test_scanner.py +0 -0
  198. {sourcecode-1.31.3 → sourcecode-1.31.5}/tests/test_schema.py +0 -0
  199. {sourcecode-1.31.3 → sourcecode-1.31.5}/tests/test_schema_normalization.py +0 -0
  200. {sourcecode-1.31.3 → sourcecode-1.31.5}/tests/test_scoring_calibration.py +0 -0
  201. {sourcecode-1.31.3 → sourcecode-1.31.5}/tests/test_semantic_analyzer_node.py +0 -0
  202. {sourcecode-1.31.3 → sourcecode-1.31.5}/tests/test_semantic_analyzer_python.py +0 -0
  203. {sourcecode-1.31.3 → sourcecode-1.31.5}/tests/test_semantic_import_resolution.py +0 -0
  204. {sourcecode-1.31.3 → sourcecode-1.31.5}/tests/test_semantic_schema.py +0 -0
  205. {sourcecode-1.31.3 → sourcecode-1.31.5}/tests/test_signal_hierarchy.py +0 -0
  206. {sourcecode-1.31.3 → sourcecode-1.31.5}/tests/test_summarizer.py +0 -0
  207. {sourcecode-1.31.3 → sourcecode-1.31.5}/tests/test_surface_honesty.py +0 -0
  208. {sourcecode-1.31.3 → sourcecode-1.31.5}/tests/test_task_differentiation.py +0 -0
  209. {sourcecode-1.31.3 → sourcecode-1.31.5}/tests/test_telemetry.py +0 -0
  210. {sourcecode-1.31.3 → sourcecode-1.31.5}/tests/test_v131_improvements.py +0 -0
  211. {sourcecode-1.31.3 → sourcecode-1.31.5}/tests/test_v1_10_regressions.py +0 -0
  212. {sourcecode-1.31.3 → sourcecode-1.31.5}/tests/test_workspace_analyzer.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: sourcecode
3
- Version: 1.31.3
3
+ Version: 1.31.5
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
  **Deterministic, behavior-aware codebase context for AI agents and PR review.**
227
227
 
228
- ![Version](https://img.shields.io/badge/version-1.31.3-blue)
228
+ ![Version](https://img.shields.io/badge/version-1.31.5-blue)
229
229
  ![Python](https://img.shields.io/badge/python-3.10%2B-green)
230
230
 
231
231
  ---
@@ -261,7 +261,7 @@ pipx install sourcecode
261
261
 
262
262
  ```bash
263
263
  sourcecode version
264
- # sourcecode 1.31.3
264
+ # sourcecode 1.31.5
265
265
  ```
266
266
 
267
267
  ---
@@ -2,7 +2,7 @@
2
2
 
3
3
  **Deterministic, behavior-aware codebase context for AI agents and PR review.**
4
4
 
5
- ![Version](https://img.shields.io/badge/version-1.31.3-blue)
5
+ ![Version](https://img.shields.io/badge/version-1.31.5-blue)
6
6
  ![Python](https://img.shields.io/badge/python-3.10%2B-green)
7
7
 
8
8
  ---
@@ -38,7 +38,7 @@ pipx install sourcecode
38
38
 
39
39
  ```bash
40
40
  sourcecode version
41
- # sourcecode 1.31.3
41
+ # sourcecode 1.31.5
42
42
  ```
43
43
 
44
44
  ---
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "sourcecode"
7
- version = "1.31.3"
7
+ version = "1.31.5"
8
8
  description = "Deterministic codebase context for AI coding agents"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.9"
@@ -1,3 +1,3 @@
1
1
  """sourcecode — Deterministic codebase context maps for AI coding agents."""
2
2
 
3
- __version__ = "1.31.3"
3
+ __version__ = "1.31.5"
@@ -401,7 +401,7 @@ def main(
401
401
  help=(
402
402
  "High-signal summary (typically 1000–3000 tokens depending on repo size): "
403
403
  "stacks, entry points, dependency summary, confidence, and gaps. "
404
- "Includes security_surface, mybatis, and transactional_boundaries for Java projects. "
404
+ "Includes security_surface (when @M3FiltroSeguridad detected), mybatis (when MyBatis framework detected), and transactional_boundaries for Java projects. "
405
405
  "Use --agent for maximum signal or --slim (when available) for minimal token footprint."
406
406
  ),
407
407
  ),
@@ -1849,6 +1849,11 @@ def prepare_context_cmd(
1849
1849
  "--include-config",
1850
1850
  help="(generate-tests) Include tooling config files (*.conf.js, .eslintrc*, etc.) in test_gaps. Excluded by default.",
1851
1851
  ),
1852
+ all_gaps: bool = typer.Option(
1853
+ False,
1854
+ "--all",
1855
+ help="(generate-tests) Return the full test_gaps list without truncating to top 20.",
1856
+ ),
1852
1857
  ) -> None:
1853
1858
  """Task-specific context for AI coding agents.
1854
1859
 
@@ -1930,7 +1935,7 @@ def prepare_context_cmd(
1930
1935
  _sys.stderr.flush()
1931
1936
  _t0 = _time.perf_counter()
1932
1937
  try:
1933
- output = builder.build(task, since=since, symptom=symptom, fast=fast, include_config=include_config)
1938
+ output = builder.build(task, since=since, symptom=symptom, fast=fast, include_config=include_config, all_gaps=all_gaps)
1934
1939
  finally:
1935
1940
  _progress.finish()
1936
1941
  _t_total = (_time.perf_counter() - _t0) * 1000
@@ -1957,8 +1962,8 @@ def prepare_context_cmd(
1957
1962
  },
1958
1963
  "explain": {
1959
1964
  "project_summary": True, "architecture_summary": True,
1960
- "relevant_files": True, "key_dependencies": True,
1961
- "gaps": True, "confidence": True,
1965
+ "relevant_files": False, "key_dependencies": True,
1966
+ "gaps": False, "confidence": True,
1962
1967
  "suspected_areas": False, "improvement_opportunities": False,
1963
1968
  "test_gaps": False, "code_notes_summary": False,
1964
1969
  "changed_files": False, "affected_entry_points": False,
@@ -2413,14 +2418,20 @@ def repo_ir_cmd(
2413
2418
 
2414
2419
  if output_path:
2415
2420
  output_path.write_text(output, encoding="utf-8")
2416
- n_nodes = len((ir.get("graph") or {}).get("nodes") or [])
2417
- n_edges = len((ir.get("graph") or {}).get("edges") or [])
2418
2421
  size_kb = len(output.encode("utf-8")) // 1024
2419
- typer.echo(
2420
- f"IR written to {output_path} "
2421
- f"({size_kb}KB, {n_nodes} nodes, {n_edges} edges)",
2422
- err=True,
2423
- )
2422
+ if summary_only:
2423
+ typer.echo(
2424
+ f"IR written to {output_path} ({size_kb}KB, graph omitted by --summary-only)",
2425
+ err=True,
2426
+ )
2427
+ else:
2428
+ n_nodes = len((ir.get("graph") or {}).get("nodes") or [])
2429
+ n_edges = len((ir.get("graph") or {}).get("edges") or [])
2430
+ typer.echo(
2431
+ f"IR written to {output_path} "
2432
+ f"({size_kb}KB, {n_nodes} nodes, {n_edges} edges)",
2433
+ err=True,
2434
+ )
2424
2435
  else:
2425
2436
  try:
2426
2437
  _sys.stdout.buffer.write(output.encode("utf-8"))
@@ -2457,7 +2468,11 @@ def _extract_java_endpoints(root: "Path") -> "dict[str, Any]":
2457
2468
  r'@(Get|Post|Put|Delete|Patch|Request)Mapping\s*'
2458
2469
  r'(?:\(\s*(?:value\s*=\s*)?(?:"([^"]*)"|\{[^}]*\}|[^)]*)\s*\))?',
2459
2470
  )
2460
- _CLASS_RE = _re.compile(r'(?:class|interface)\s+(\w+)')
2471
+ _CLASS_RE = _re.compile(
2472
+ r'^[ \t]*(?:(?:public|protected|private|abstract|final|@\w+)\s+)*'
2473
+ r'(?:class|interface)\s+(\w+)',
2474
+ _re.MULTILINE,
2475
+ )
2461
2476
  _METHOD_RE = _re.compile(
2462
2477
  r'(?:public|protected|private)\s+\S+\s+(\w+)\s*\(',
2463
2478
  )
@@ -2467,6 +2482,9 @@ def _extract_java_endpoints(root: "Path") -> "dict[str, Any]":
2467
2482
  _CLASS_PATH_RE = _re.compile(
2468
2483
  r'@RequestMapping\s*\(\s*(?:value\s*=\s*)?["\']([^"\']+)["\']',
2469
2484
  )
2485
+ # Handles array syntax: @RequestMapping({"/v1/foo", "/v1/bar"})
2486
+ _CLASS_ARRAY_PATH_RE = _re.compile(r'@RequestMapping\s*\(\s*\{([^}]*)\}')
2487
+ _QUOTED_STR_RE = _re.compile(r'"([^"]+)"')
2470
2488
  _REQUEST_METHOD_VERB_RE = _re.compile(r'method\s*=\s*RequestMethod\.([A-Z]+)')
2471
2489
  _VALUE_PATH_RE = _re.compile(r'value\s*=\s*"([^"]+)"')
2472
2490
 
@@ -2505,7 +2523,6 @@ def _extract_java_endpoints(root: "Path") -> "dict[str, Any]":
2505
2523
  class_name = cls_m.group(1) if cls_m else java_file.stem
2506
2524
 
2507
2525
  # Extract class-level base path and locate class body start
2508
- class_base = ""
2509
2526
  lines = content.splitlines()
2510
2527
 
2511
2528
  # First pass: find class/interface declaration line index
@@ -2518,26 +2535,91 @@ def _extract_java_endpoints(root: "Path") -> "dict[str, Any]":
2518
2535
  class_body_start = i + 1
2519
2536
  break
2520
2537
 
2521
- # Second pass: extract class-level @RequestMapping path (only before class body)
2538
+ # Second pass: extract class-level @RequestMapping path (only before class body).
2539
+ # Supports both single-string and array syntax (Bug #1B).
2522
2540
  search_end = class_body_start if class_body_start else len(lines)
2541
+ class_bases: list[str] = [""] # default: no prefix
2523
2542
  for i in range(search_end):
2543
+ sl = lines[i].strip()
2544
+ if sl.startswith("//") or sl.startswith("*"):
2545
+ continue
2524
2546
  if "@RequestMapping" in lines[i]:
2525
- block = "\n".join(lines[max(0, i - 1): i + 5])
2547
+ # Cap block to search_end so method annotations inside the class body
2548
+ # cannot be matched as the class-level prefix (Bug #1B).
2549
+ block = "\n".join(lines[max(0, i - 1): min(i + 5, search_end + 1)])
2526
2550
  if "class " in block or "interface " in block:
2527
2551
  path_m = _CLASS_PATH_RE.search(block)
2528
2552
  if path_m:
2529
- class_base = path_m.group(1).rstrip("/")
2530
- break
2553
+ captured = path_m.group(1).rstrip("/")
2554
+ # Handle string concat: @RequestMapping("lit" + ClassName.CONST)
2555
+ _CONCAT_CONST_RE = _re.compile(
2556
+ r'@RequestMapping\s*\(\s*(?:value\s*=\s*)?'
2557
+ r'["\']([^"\']*)["\'\s]*\+\s*(\w+)\.(\w+)'
2558
+ )
2559
+ cc_m = _CONCAT_CONST_RE.search(block)
2560
+ if cc_m:
2561
+ prefix_lit = cc_m.group(1)
2562
+ c_class = cc_m.group(2)
2563
+ c_field = cc_m.group(3)
2564
+ _SVAL_RE = _re.compile(
2565
+ r'static\s+final\s+String\s+'
2566
+ + _re.escape(c_field)
2567
+ + r'\s*=\s*"([^"]+)"'
2568
+ )
2569
+ resolved = None
2570
+ m_cur = _SVAL_RE.search(content)
2571
+ if m_cur:
2572
+ resolved = m_cur.group(1)
2573
+ else:
2574
+ for _jf in java_files:
2575
+ if _jf.stem == c_class:
2576
+ try:
2577
+ _jf_txt = _jf.read_text(
2578
+ encoding="utf-8", errors="replace"
2579
+ )
2580
+ m_jf = _SVAL_RE.search(_jf_txt)
2581
+ if m_jf:
2582
+ resolved = m_jf.group(1)
2583
+ break
2584
+ except OSError:
2585
+ pass
2586
+ if resolved is not None:
2587
+ class_bases = [(prefix_lit + resolved).rstrip("/")]
2588
+ else:
2589
+ class_bases = [captured] if captured else [""]
2590
+ else:
2591
+ class_bases = [captured] if captured else [""]
2592
+ else:
2593
+ arr_m = _CLASS_ARRAY_PATH_RE.search(block)
2594
+ if arr_m:
2595
+ paths = _QUOTED_STR_RE.findall(arr_m.group(1))
2596
+ if paths:
2597
+ class_bases = [p.rstrip("/") for p in paths]
2598
+ break
2531
2599
 
2532
- # Extract method-level endpoints starting from inside class body
2533
- # (skipping class-level annotations that appear before the class declaration)
2600
+ # Extract method-level endpoints starting from inside class body.
2601
+ # Bug #1A fix: track block comments and skip // lines before annotation checks.
2534
2602
  pending_annotations: list[tuple[str, str]] = [] # (http_verb, path_suffix)
2535
2603
  pending_filtro: Optional[str] = None
2604
+ in_block_comment = False
2536
2605
 
2537
2606
  for i in range(class_body_start, len(lines)):
2538
2607
  line = lines[i]
2539
2608
  stripped = line.strip()
2540
2609
 
2610
+ # Block comment state tracking (Bug #1A)
2611
+ if in_block_comment:
2612
+ if "*/" in stripped:
2613
+ in_block_comment = False
2614
+ continue
2615
+ if stripped.startswith("/*"):
2616
+ if "*/" not in stripped:
2617
+ in_block_comment = True
2618
+ continue
2619
+ # Skip line comments (Bug #1A)
2620
+ if stripped.startswith("//"):
2621
+ continue
2622
+
2541
2623
  # Check for @M3FiltroSeguridad
2542
2624
  fm = _FILTRO_RE.search(stripped)
2543
2625
  if fm:
@@ -2572,30 +2654,30 @@ def _extract_java_endpoints(root: "Path") -> "dict[str, Any]":
2572
2654
  handler = mm.group(1) if mm else ""
2573
2655
  if handler and not handler.startswith("class"):
2574
2656
  for http_verb, path_suffix in pending_annotations:
2575
- full_path = (class_base + "/" + path_suffix).replace("//", "/").rstrip("/") or "/"
2576
- if not full_path.startswith("/"):
2577
- full_path = "/" + full_path
2578
- key = (class_name, handler, http_verb)
2579
- if key not in seen:
2580
- seen.add(key)
2581
- entry: dict[str, Any] = {
2582
- "method": http_verb,
2583
- "path": full_path,
2584
- "controller": class_name,
2585
- "handler": handler,
2586
- }
2587
- if pending_filtro:
2588
- entry["required_permission"] = pending_filtro
2589
- endpoints.append(entry)
2657
+ for _cb in class_bases: # Bug #1B: one endpoint per class prefix
2658
+ full_path = (_cb + "/" + path_suffix).replace("//", "/").rstrip("/") or "/"
2659
+ if not full_path.startswith("/"):
2660
+ full_path = "/" + full_path
2661
+ key = (class_name, handler, http_verb, _cb)
2662
+ if key not in seen:
2663
+ seen.add(key)
2664
+ entry: dict[str, Any] = {
2665
+ "method": http_verb,
2666
+ "path": full_path,
2667
+ "controller": class_name,
2668
+ "handler": handler,
2669
+ }
2670
+ if pending_filtro:
2671
+ entry["required_permission"] = pending_filtro
2672
+ endpoints.append(entry)
2590
2673
  pending_annotations = []
2591
2674
  pending_filtro = None
2592
2675
  continue
2593
2676
 
2594
- # Non-annotation, non-method line — reset if it's a closing brace or blank
2595
- if stripped in ("}", "{", "") or stripped.startswith("//") or stripped.startswith("*"):
2596
- if stripped == "}":
2597
- pending_annotations = []
2598
- pending_filtro = None
2677
+ # Non-annotation, non-method line — reset on closing brace
2678
+ if stripped == "}":
2679
+ pending_annotations = []
2680
+ pending_filtro = None
2599
2681
 
2600
2682
  endpoints.sort(key=lambda e: (e.get("controller", ""), e.get("path", "")))
2601
2683
  undocumented = sum(1 for e in endpoints if "required_permission" not in e)
@@ -59,8 +59,13 @@ class HeuristicDetector(AbstractDetector):
59
59
  paths = flatten_file_tree(context.file_tree)
60
60
  counts: Counter[str] = Counter()
61
61
  for path in paths:
62
- if path.startswith("."):
62
+ if path.startswith(".") or _is_auxiliary_path(path):
63
63
  continue
64
+ # Skip JS/TS files bundled as Java static resources (not Node.js source)
65
+ if path.endswith((".js", ".ts", ".tsx", ".jsx", ".mjs")):
66
+ _np = path.replace("\\", "/")
67
+ if "src/main/resources/" in _np or "src/main/webapp/" in _np:
68
+ continue
64
69
  for extension, stack in _EXTENSION_MAP.items():
65
70
  if path.endswith(extension):
66
71
  counts[stack] += 1
@@ -721,7 +721,7 @@ class TaskContextBuilder:
721
721
  def __init__(self, root: Path) -> None:
722
722
  self.root = root
723
723
 
724
- def build(self, task_name: str, *, since: Optional[str] = None, symptom: Optional[str] = None, fast: bool = False, include_config: bool = False) -> TaskOutput:
724
+ def build(self, task_name: str, *, since: Optional[str] = None, symptom: Optional[str] = None, fast: bool = False, include_config: bool = False, all_gaps: bool = False) -> TaskOutput:
725
725
  if task_name not in TASKS:
726
726
  raise ValueError(
727
727
  f"Unknown task '{task_name}'. Available: {', '.join(TASKS)}"
@@ -1763,14 +1763,18 @@ class TaskContextBuilder:
1763
1763
  "_rank": _pub_count + _ann_count * 2,
1764
1764
  })
1765
1765
 
1766
- _java_candidates.sort(key=lambda x: -x["_rank"])
1766
+ _java_candidates.sort(
1767
+ key=lambda x: -(x["public_method_count"] * (1.5 if x["has_spring_annotations"] else 1.0))
1768
+ )
1769
+ _top = _java_candidates if all_gaps else _java_candidates[:20]
1767
1770
  test_gaps = [
1768
1771
  {
1769
1772
  "path": c["path"],
1770
1773
  "public_method_count": c["public_method_count"],
1771
1774
  "has_spring_annotations": c["has_spring_annotations"],
1775
+ "rank_score": round(c["public_method_count"] * (1.5 if c["has_spring_annotations"] else 1.0), 1),
1772
1776
  }
1773
- for c in _java_candidates
1777
+ for c in _top
1774
1778
  ]
1775
1779
  else:
1776
1780
  # Non-Java algorithm (unchanged)
@@ -2206,8 +2210,67 @@ class TaskContextBuilder:
2206
2210
  "refactor": max(15, min(30, _repo_size // 120)),
2207
2211
  }
2208
2212
  _budget = _task_budget.get(task_name, 15)
2209
- _selected = _ctx.select_subgraph(_ns, contracts=[], budget=_budget, min_score=0.15)
2213
+ _selected = list(_ctx.select_subgraph(_ns, contracts=[], budget=_budget, min_score=0.15))
2210
2214
  _rf_map = {path: rf for _, path, rf in scored}
2215
+
2216
+ # Bug #3: onboard must cover ≥3 arch layers (controllers/services/domain/repositories).
2217
+ if task_name == "onboard":
2218
+ def _arch_layer(p: str) -> str:
2219
+ n = Path(p).name.lower()
2220
+ if "controller" in n:
2221
+ return "controllers"
2222
+ if "repository" in n or "mapper" in n or "dao" in n:
2223
+ return "repositories"
2224
+ if "service" in n:
2225
+ return "services"
2226
+ pn = p.replace("\\", "/")
2227
+ if "entity" in n or "/entity/" in pn or "/domain/" in pn or "/model/" in pn:
2228
+ return "domain"
2229
+ return "other"
2230
+
2231
+ _REQUIRED = {"controllers", "services", "repositories", "domain"}
2232
+ _covered = {_arch_layer(p) for p in _selected} & _REQUIRED
2233
+ _missing = _REQUIRED - _covered
2234
+ if len(_covered) < 3 and _missing:
2235
+ _sel_set = set(_selected)
2236
+ # First pass: inject from already-scored files
2237
+ for _, _p, _ in sorted(scored, key=lambda x: -x[0]):
2238
+ if len(_covered) >= 3:
2239
+ break
2240
+ if _p in _sel_set or _p not in _rf_map:
2241
+ continue
2242
+ _layer = _arch_layer(_p)
2243
+ if _layer in _missing:
2244
+ _selected.append(_p)
2245
+ _sel_set.add(_p)
2246
+ _covered.add(_layer)
2247
+ _missing.discard(_layer)
2248
+ # Second pass: fallback scan of all_paths when scored files
2249
+ # don't cover enough layers (e.g. all Java files scored ≤ 0
2250
+ # due to auxiliary/example package detection).
2251
+ if len(_covered) < 3 and _missing:
2252
+ _NON_TEST = ("/test/", "/tests/", "/spec/")
2253
+ for _p in all_paths:
2254
+ if len(_covered) >= 3:
2255
+ break
2256
+ if _p in _sel_set:
2257
+ continue
2258
+ if any(s in _p.replace("\\", "/") for s in _NON_TEST):
2259
+ continue
2260
+ _layer = _arch_layer(_p)
2261
+ if _layer not in _missing:
2262
+ continue
2263
+ _rf_map[_p] = RelevantFile(
2264
+ path=_p,
2265
+ role="source",
2266
+ score=0.1,
2267
+ reason="layer coverage (onboard)",
2268
+ )
2269
+ _selected.append(_p)
2270
+ _sel_set.add(_p)
2271
+ _covered.add(_layer)
2272
+ _missing.discard(_layer)
2273
+
2211
2274
  return [_rf_map[p] for p in _selected if p in _rf_map]
2212
2275
  except Exception:
2213
2276
  return [f for _, _, f in scored[:15]]
@@ -409,7 +409,10 @@ def _spring_profiles_context(sm: "SourceMap") -> "Optional[dict[str, Any]]":
409
409
  else:
410
410
  matches = [
411
411
  p for p in sm.file_paths
412
- if pfx in Path(p).stem.lower() and p.endswith(".java")
412
+ if (Path(p).stem.lower() == pfx
413
+ or Path(p).stem.lower().startswith(pfx + "-")
414
+ or Path(p).stem.lower().endswith("-" + pfx))
415
+ and p.endswith(".java")
413
416
  ]
414
417
  if matches:
415
418
  per_profile[profile] = [Path(p).name for p in matches[:5]]
@@ -534,6 +537,8 @@ def _bootstrap_structured(eps: list) -> "Optional[dict[str, Any]]":
534
537
 
535
538
  for ep in eps:
536
539
  path = getattr(ep, "path", "")
540
+ if "/test/" in path or "/tests/" in path:
541
+ continue
537
542
  kind = getattr(ep, "kind", "")
538
543
  stem = _Path(path).stem
539
544
 
@@ -587,8 +592,9 @@ def _bootstrap_structured(eps: list) -> "Optional[dict[str, Any]]":
587
592
  module_names.append(module)
588
593
 
589
594
  _ctrl_note = (
590
- f"{controller_methods} @RequestMapping methods across "
595
+ f"{controller_methods} detected entry-point methods across "
591
596
  f"{controller_classes} controller classes"
597
+ f" (use 'sourcecode endpoints' for full surface)"
592
598
  )
593
599
  if len(module_names) > 30:
594
600
  # Group by first path segment under ddd/ (inferred domain area)