sourcecode 1.10.0__tar.gz → 1.12.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (186) hide show
  1. {sourcecode-1.10.0 → sourcecode-1.12.0}/PKG-INFO +38 -66
  2. sourcecode-1.12.0/README.md +114 -0
  3. {sourcecode-1.10.0 → sourcecode-1.12.0}/pyproject.toml +1 -1
  4. {sourcecode-1.10.0 → sourcecode-1.12.0}/src/sourcecode/__init__.py +1 -1
  5. {sourcecode-1.10.0 → sourcecode-1.12.0}/src/sourcecode/cli.py +28 -7
  6. {sourcecode-1.10.0 → sourcecode-1.12.0}/src/sourcecode/detectors/java.py +99 -3
  7. {sourcecode-1.10.0 → sourcecode-1.12.0}/src/sourcecode/detectors/project.py +3 -0
  8. {sourcecode-1.10.0 → sourcecode-1.12.0}/src/sourcecode/prepare_context.py +19 -0
  9. {sourcecode-1.10.0 → sourcecode-1.12.0}/src/sourcecode/schema.py +1 -0
  10. {sourcecode-1.10.0 → sourcecode-1.12.0}/src/sourcecode/serializer.py +342 -36
  11. {sourcecode-1.10.0 → sourcecode-1.12.0}/src/sourcecode/summarizer.py +7 -1
  12. sourcecode-1.12.0/tests/fixtures/spring_boot_minimal/src/main/java/com/example/demo/config/FilterConfig.java +17 -0
  13. sourcecode-1.12.0/tests/fixtures/spring_boot_minimal/src/main/java/com/example/demo/web/NominaRestController.java +16 -0
  14. sourcecode-1.12.0/tests/fixtures/spring_boot_minimal/src/main/resources/mapper/HealthMapper.xml +8 -0
  15. {sourcecode-1.10.0 → sourcecode-1.12.0}/tests/test_cli.py +1 -1
  16. sourcecode-1.12.0/tests/test_surface_honesty.py +339 -0
  17. sourcecode-1.12.0/tests/test_v1_10_regressions.py +560 -0
  18. sourcecode-1.10.0/README.md +0 -142
  19. {sourcecode-1.10.0 → sourcecode-1.12.0}/.agents/skills/source-command-gsd-join-discord/SKILL.md +0 -0
  20. {sourcecode-1.10.0 → sourcecode-1.12.0}/.agents/skills/source-command-gsd-review-backlog/SKILL.md +0 -0
  21. {sourcecode-1.10.0 → sourcecode-1.12.0}/.agents/skills/source-command-gsd-workstreams/SKILL.md +0 -0
  22. {sourcecode-1.10.0 → sourcecode-1.12.0}/.continue-here.md +0 -0
  23. {sourcecode-1.10.0 → sourcecode-1.12.0}/.github/workflows/build-windows.yml +0 -0
  24. {sourcecode-1.10.0 → sourcecode-1.12.0}/.gitignore +0 -0
  25. {sourcecode-1.10.0 → sourcecode-1.12.0}/.ruff.toml +0 -0
  26. {sourcecode-1.10.0 → sourcecode-1.12.0}/CONTRIBUTING.md +0 -0
  27. {sourcecode-1.10.0 → sourcecode-1.12.0}/LICENSE +0 -0
  28. {sourcecode-1.10.0 → sourcecode-1.12.0}/SECURITY.md +0 -0
  29. {sourcecode-1.10.0 → sourcecode-1.12.0}/docs/privacy.md +0 -0
  30. {sourcecode-1.10.0 → sourcecode-1.12.0}/docs/schema.md +0 -0
  31. {sourcecode-1.10.0 → sourcecode-1.12.0}/raw +0 -0
  32. {sourcecode-1.10.0 → sourcecode-1.12.0}/run_cli.py +0 -0
  33. {sourcecode-1.10.0 → sourcecode-1.12.0}/src/sourcecode/adaptive_scanner.py +0 -0
  34. {sourcecode-1.10.0 → sourcecode-1.12.0}/src/sourcecode/architecture_analyzer.py +0 -0
  35. {sourcecode-1.10.0 → sourcecode-1.12.0}/src/sourcecode/architecture_summary.py +0 -0
  36. {sourcecode-1.10.0 → sourcecode-1.12.0}/src/sourcecode/ast_extractor.py +0 -0
  37. {sourcecode-1.10.0 → sourcecode-1.12.0}/src/sourcecode/classifier.py +0 -0
  38. {sourcecode-1.10.0 → sourcecode-1.12.0}/src/sourcecode/code_notes_analyzer.py +0 -0
  39. {sourcecode-1.10.0 → sourcecode-1.12.0}/src/sourcecode/confidence_analyzer.py +0 -0
  40. {sourcecode-1.10.0 → sourcecode-1.12.0}/src/sourcecode/context_scorer.py +0 -0
  41. {sourcecode-1.10.0 → sourcecode-1.12.0}/src/sourcecode/context_summarizer.py +0 -0
  42. {sourcecode-1.10.0 → sourcecode-1.12.0}/src/sourcecode/contract_model.py +0 -0
  43. {sourcecode-1.10.0 → sourcecode-1.12.0}/src/sourcecode/contract_pipeline.py +0 -0
  44. {sourcecode-1.10.0 → sourcecode-1.12.0}/src/sourcecode/coverage_parser.py +0 -0
  45. {sourcecode-1.10.0 → sourcecode-1.12.0}/src/sourcecode/dependency_analyzer.py +0 -0
  46. {sourcecode-1.10.0 → sourcecode-1.12.0}/src/sourcecode/detectors/__init__.py +0 -0
  47. {sourcecode-1.10.0 → sourcecode-1.12.0}/src/sourcecode/detectors/base.py +0 -0
  48. {sourcecode-1.10.0 → sourcecode-1.12.0}/src/sourcecode/detectors/csproj_parser.py +0 -0
  49. {sourcecode-1.10.0 → sourcecode-1.12.0}/src/sourcecode/detectors/dart.py +0 -0
  50. {sourcecode-1.10.0 → sourcecode-1.12.0}/src/sourcecode/detectors/dotnet.py +0 -0
  51. {sourcecode-1.10.0 → sourcecode-1.12.0}/src/sourcecode/detectors/elixir.py +0 -0
  52. {sourcecode-1.10.0 → sourcecode-1.12.0}/src/sourcecode/detectors/go.py +0 -0
  53. {sourcecode-1.10.0 → sourcecode-1.12.0}/src/sourcecode/detectors/heuristic.py +0 -0
  54. {sourcecode-1.10.0 → sourcecode-1.12.0}/src/sourcecode/detectors/hybrid.py +0 -0
  55. {sourcecode-1.10.0 → sourcecode-1.12.0}/src/sourcecode/detectors/jvm_ext.py +0 -0
  56. {sourcecode-1.10.0 → sourcecode-1.12.0}/src/sourcecode/detectors/nodejs.py +0 -0
  57. {sourcecode-1.10.0 → sourcecode-1.12.0}/src/sourcecode/detectors/parsers.py +0 -0
  58. {sourcecode-1.10.0 → sourcecode-1.12.0}/src/sourcecode/detectors/php.py +0 -0
  59. {sourcecode-1.10.0 → sourcecode-1.12.0}/src/sourcecode/detectors/python.py +0 -0
  60. {sourcecode-1.10.0 → sourcecode-1.12.0}/src/sourcecode/detectors/ruby.py +0 -0
  61. {sourcecode-1.10.0 → sourcecode-1.12.0}/src/sourcecode/detectors/rust.py +0 -0
  62. {sourcecode-1.10.0 → sourcecode-1.12.0}/src/sourcecode/detectors/systems.py +0 -0
  63. {sourcecode-1.10.0 → sourcecode-1.12.0}/src/sourcecode/detectors/terraform.py +0 -0
  64. {sourcecode-1.10.0 → sourcecode-1.12.0}/src/sourcecode/detectors/tooling.py +0 -0
  65. {sourcecode-1.10.0 → sourcecode-1.12.0}/src/sourcecode/doc_analyzer.py +0 -0
  66. {sourcecode-1.10.0 → sourcecode-1.12.0}/src/sourcecode/entrypoint_classifier.py +0 -0
  67. {sourcecode-1.10.0 → sourcecode-1.12.0}/src/sourcecode/env_analyzer.py +0 -0
  68. {sourcecode-1.10.0 → sourcecode-1.12.0}/src/sourcecode/file_classifier.py +0 -0
  69. {sourcecode-1.10.0 → sourcecode-1.12.0}/src/sourcecode/git_analyzer.py +0 -0
  70. {sourcecode-1.10.0 → sourcecode-1.12.0}/src/sourcecode/graph_analyzer.py +0 -0
  71. {sourcecode-1.10.0 → sourcecode-1.12.0}/src/sourcecode/metrics_analyzer.py +0 -0
  72. {sourcecode-1.10.0 → sourcecode-1.12.0}/src/sourcecode/progress.py +0 -0
  73. {sourcecode-1.10.0 → sourcecode-1.12.0}/src/sourcecode/ranking_engine.py +0 -0
  74. {sourcecode-1.10.0 → sourcecode-1.12.0}/src/sourcecode/redactor.py +0 -0
  75. {sourcecode-1.10.0 → sourcecode-1.12.0}/src/sourcecode/relevance_scorer.py +0 -0
  76. {sourcecode-1.10.0 → sourcecode-1.12.0}/src/sourcecode/repo_classifier.py +0 -0
  77. {sourcecode-1.10.0 → sourcecode-1.12.0}/src/sourcecode/runtime_classifier.py +0 -0
  78. {sourcecode-1.10.0 → sourcecode-1.12.0}/src/sourcecode/scanner.py +0 -0
  79. {sourcecode-1.10.0 → sourcecode-1.12.0}/src/sourcecode/semantic_analyzer.py +0 -0
  80. {sourcecode-1.10.0 → sourcecode-1.12.0}/src/sourcecode/telemetry/__init__.py +0 -0
  81. {sourcecode-1.10.0 → sourcecode-1.12.0}/src/sourcecode/telemetry/config.py +0 -0
  82. {sourcecode-1.10.0 → sourcecode-1.12.0}/src/sourcecode/telemetry/consent.py +0 -0
  83. {sourcecode-1.10.0 → sourcecode-1.12.0}/src/sourcecode/telemetry/events.py +0 -0
  84. {sourcecode-1.10.0 → sourcecode-1.12.0}/src/sourcecode/telemetry/filters.py +0 -0
  85. {sourcecode-1.10.0 → sourcecode-1.12.0}/src/sourcecode/telemetry/transport.py +0 -0
  86. {sourcecode-1.10.0 → sourcecode-1.12.0}/src/sourcecode/tree_utils.py +0 -0
  87. {sourcecode-1.10.0 → sourcecode-1.12.0}/src/sourcecode/workspace.py +0 -0
  88. {sourcecode-1.10.0 → sourcecode-1.12.0}/tests/__init__.py +0 -0
  89. {sourcecode-1.10.0 → sourcecode-1.12.0}/tests/conftest.py +0 -0
  90. {sourcecode-1.10.0 → sourcecode-1.12.0}/tests/fixtures/coverage.xml +0 -0
  91. {sourcecode-1.10.0 → sourcecode-1.12.0}/tests/fixtures/fastapi_app/pyproject.toml +0 -0
  92. {sourcecode-1.10.0 → sourcecode-1.12.0}/tests/fixtures/fastapi_app/src/main.py +0 -0
  93. {sourcecode-1.10.0 → sourcecode-1.12.0}/tests/fixtures/go_service/cmd/api/main.go +0 -0
  94. {sourcecode-1.10.0 → sourcecode-1.12.0}/tests/fixtures/go_service/go.mod +0 -0
  95. {sourcecode-1.10.0 → sourcecode-1.12.0}/tests/fixtures/jacoco.xml +0 -0
  96. {sourcecode-1.10.0 → sourcecode-1.12.0}/tests/fixtures/lcov.info +0 -0
  97. {sourcecode-1.10.0 → sourcecode-1.12.0}/tests/fixtures/nextjs_app/app/page.tsx +0 -0
  98. {sourcecode-1.10.0 → sourcecode-1.12.0}/tests/fixtures/nextjs_app/package.json +0 -0
  99. {sourcecode-1.10.0 → sourcecode-1.12.0}/tests/fixtures/nextjs_app/pnpm-lock.yaml +0 -0
  100. {sourcecode-1.10.0 → sourcecode-1.12.0}/tests/fixtures/pnpm_monorepo/apps/web/app/page.tsx +0 -0
  101. {sourcecode-1.10.0 → sourcecode-1.12.0}/tests/fixtures/pnpm_monorepo/apps/web/package.json +0 -0
  102. {sourcecode-1.10.0 → sourcecode-1.12.0}/tests/fixtures/pnpm_monorepo/packages/api/main.py +0 -0
  103. {sourcecode-1.10.0 → sourcecode-1.12.0}/tests/fixtures/pnpm_monorepo/packages/api/pyproject.toml +0 -0
  104. {sourcecode-1.10.0 → sourcecode-1.12.0}/tests/fixtures/pnpm_monorepo/pnpm-workspace.yaml +0 -0
  105. {sourcecode-1.10.0 → sourcecode-1.12.0}/tests/fixtures/spring_boot_minimal/pom.xml +0 -0
  106. {sourcecode-1.10.0 → sourcecode-1.12.0}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/ausente/application/service/FindAusenteService.java +0 -0
  107. {sourcecode-1.10.0 → sourcecode-1.12.0}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/ausente/domain/entities/Ausente.java +0 -0
  108. {sourcecode-1.10.0 → sourcecode-1.12.0}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/ausente/infrastructure/rest/AusenteRestController.java +0 -0
  109. {sourcecode-1.10.0 → sourcecode-1.12.0}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/autocoberturas/application/service/FindAutocoberturasService.java +0 -0
  110. {sourcecode-1.10.0 → sourcecode-1.12.0}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/autocoberturas/domain/entities/Autocoberturas.java +0 -0
  111. {sourcecode-1.10.0 → sourcecode-1.12.0}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/autocoberturas/infrastructure/rest/AutocoberturasRestController.java +0 -0
  112. {sourcecode-1.10.0 → sourcecode-1.12.0}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/calendarioTrabajador/application/service/FindCalendarioTrabajadorService.java +0 -0
  113. {sourcecode-1.10.0 → sourcecode-1.12.0}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/calendarioTrabajador/domain/entities/CalendarioTrabajador.java +0 -0
  114. {sourcecode-1.10.0 → sourcecode-1.12.0}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/calendarioTrabajador/infrastructure/rest/CalendarioTrabajadorRestController.java +0 -0
  115. {sourcecode-1.10.0 → sourcecode-1.12.0}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/departamento/application/service/FindDepartamentoService.java +0 -0
  116. {sourcecode-1.10.0 → sourcecode-1.12.0}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/departamento/domain/entities/Departamento.java +0 -0
  117. {sourcecode-1.10.0 → sourcecode-1.12.0}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/departamento/infrastructure/rest/DepartamentoRestController.java +0 -0
  118. {sourcecode-1.10.0 → sourcecode-1.12.0}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/empleado/application/service/FindEmpleadoService.java +0 -0
  119. {sourcecode-1.10.0 → sourcecode-1.12.0}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/empleado/domain/entities/Empleado.java +0 -0
  120. {sourcecode-1.10.0 → sourcecode-1.12.0}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/empleado/infrastructure/rest/EmpleadoRestController.java +0 -0
  121. {sourcecode-1.10.0 → sourcecode-1.12.0}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/demo/DemoApplication.java +0 -0
  122. {sourcecode-1.10.0 → sourcecode-1.12.0}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/demo/domain/Health.java +0 -0
  123. {sourcecode-1.10.0 → sourcecode-1.12.0}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/demo/mapper/HealthMapper.java +0 -0
  124. {sourcecode-1.10.0 → sourcecode-1.12.0}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/demo/repository/HealthRepository.java +0 -0
  125. {sourcecode-1.10.0 → sourcecode-1.12.0}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/demo/service/HealthService.java +0 -0
  126. {sourcecode-1.10.0 → sourcecode-1.12.0}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/demo/web/HealthRestController.java +0 -0
  127. {sourcecode-1.10.0 → sourcecode-1.12.0}/tests/fixtures/spring_boot_minimal/src/main/resources/application-dev.yml +0 -0
  128. {sourcecode-1.10.0 → sourcecode-1.12.0}/tests/fixtures/spring_boot_minimal/src/main/resources/application.yml +0 -0
  129. {sourcecode-1.10.0 → sourcecode-1.12.0}/tests/test_architecture_analyzer.py +0 -0
  130. {sourcecode-1.10.0 → sourcecode-1.12.0}/tests/test_architecture_summary.py +0 -0
  131. {sourcecode-1.10.0 → sourcecode-1.12.0}/tests/test_ast_extractor.py +0 -0
  132. {sourcecode-1.10.0 → sourcecode-1.12.0}/tests/test_block1_reliability.py +0 -0
  133. {sourcecode-1.10.0 → sourcecode-1.12.0}/tests/test_block2_coverage.py +0 -0
  134. {sourcecode-1.10.0 → sourcecode-1.12.0}/tests/test_block5_quality.py +0 -0
  135. {sourcecode-1.10.0 → sourcecode-1.12.0}/tests/test_bug_fixes_v16.py +0 -0
  136. {sourcecode-1.10.0 → sourcecode-1.12.0}/tests/test_classifier.py +0 -0
  137. {sourcecode-1.10.0 → sourcecode-1.12.0}/tests/test_code_notes_analyzer.py +0 -0
  138. {sourcecode-1.10.0 → sourcecode-1.12.0}/tests/test_context_scorer.py +0 -0
  139. {sourcecode-1.10.0 → sourcecode-1.12.0}/tests/test_contract_pipeline.py +0 -0
  140. {sourcecode-1.10.0 → sourcecode-1.12.0}/tests/test_coverage_parser.py +0 -0
  141. {sourcecode-1.10.0 → sourcecode-1.12.0}/tests/test_cross_consistency.py +0 -0
  142. {sourcecode-1.10.0 → sourcecode-1.12.0}/tests/test_dependency_analyzer_node_python.py +0 -0
  143. {sourcecode-1.10.0 → sourcecode-1.12.0}/tests/test_dependency_analyzer_polyglot.py +0 -0
  144. {sourcecode-1.10.0 → sourcecode-1.12.0}/tests/test_dependency_schema.py +0 -0
  145. {sourcecode-1.10.0 → sourcecode-1.12.0}/tests/test_detector_dotnet.py +0 -0
  146. {sourcecode-1.10.0 → sourcecode-1.12.0}/tests/test_detector_go_rust_java.py +0 -0
  147. {sourcecode-1.10.0 → sourcecode-1.12.0}/tests/test_detector_nodejs.py +0 -0
  148. {sourcecode-1.10.0 → sourcecode-1.12.0}/tests/test_detector_php_ruby_dart.py +0 -0
  149. {sourcecode-1.10.0 → sourcecode-1.12.0}/tests/test_detector_python.py +0 -0
  150. {sourcecode-1.10.0 → sourcecode-1.12.0}/tests/test_detector_universal_managed.py +0 -0
  151. {sourcecode-1.10.0 → sourcecode-1.12.0}/tests/test_detector_universal_systems.py +0 -0
  152. {sourcecode-1.10.0 → sourcecode-1.12.0}/tests/test_detectors_base.py +0 -0
  153. {sourcecode-1.10.0 → sourcecode-1.12.0}/tests/test_doc_analyzer_jsdom.py +0 -0
  154. {sourcecode-1.10.0 → sourcecode-1.12.0}/tests/test_doc_analyzer_python.py +0 -0
  155. {sourcecode-1.10.0 → sourcecode-1.12.0}/tests/test_graph_analyzer_polyglot.py +0 -0
  156. {sourcecode-1.10.0 → sourcecode-1.12.0}/tests/test_graph_analyzer_python_node.py +0 -0
  157. {sourcecode-1.10.0 → sourcecode-1.12.0}/tests/test_graph_schema.py +0 -0
  158. {sourcecode-1.10.0 → sourcecode-1.12.0}/tests/test_hybrid_inference.py +0 -0
  159. {sourcecode-1.10.0 → sourcecode-1.12.0}/tests/test_integration.py +0 -0
  160. {sourcecode-1.10.0 → sourcecode-1.12.0}/tests/test_integration_dependencies.py +0 -0
  161. {sourcecode-1.10.0 → sourcecode-1.12.0}/tests/test_integration_detection.py +0 -0
  162. {sourcecode-1.10.0 → sourcecode-1.12.0}/tests/test_integration_docs.py +0 -0
  163. {sourcecode-1.10.0 → sourcecode-1.12.0}/tests/test_integration_graph_modules.py +0 -0
  164. {sourcecode-1.10.0 → sourcecode-1.12.0}/tests/test_integration_lqn.py +0 -0
  165. {sourcecode-1.10.0 → sourcecode-1.12.0}/tests/test_integration_metrics.py +0 -0
  166. {sourcecode-1.10.0 → sourcecode-1.12.0}/tests/test_integration_multistack.py +0 -0
  167. {sourcecode-1.10.0 → sourcecode-1.12.0}/tests/test_integration_semantics.py +0 -0
  168. {sourcecode-1.10.0 → sourcecode-1.12.0}/tests/test_integration_universal.py +0 -0
  169. {sourcecode-1.10.0 → sourcecode-1.12.0}/tests/test_java_spring_integration.py +0 -0
  170. {sourcecode-1.10.0 → sourcecode-1.12.0}/tests/test_metrics_analyzer.py +0 -0
  171. {sourcecode-1.10.0 → sourcecode-1.12.0}/tests/test_packaging.py +0 -0
  172. {sourcecode-1.10.0 → sourcecode-1.12.0}/tests/test_phase1_improvements.py +0 -0
  173. {sourcecode-1.10.0 → sourcecode-1.12.0}/tests/test_pipeline_integrity.py +0 -0
  174. {sourcecode-1.10.0 → sourcecode-1.12.0}/tests/test_real_projects.py +0 -0
  175. {sourcecode-1.10.0 → sourcecode-1.12.0}/tests/test_redactor.py +0 -0
  176. {sourcecode-1.10.0 → sourcecode-1.12.0}/tests/test_scanner.py +0 -0
  177. {sourcecode-1.10.0 → sourcecode-1.12.0}/tests/test_schema.py +0 -0
  178. {sourcecode-1.10.0 → sourcecode-1.12.0}/tests/test_schema_normalization.py +0 -0
  179. {sourcecode-1.10.0 → sourcecode-1.12.0}/tests/test_semantic_analyzer_node.py +0 -0
  180. {sourcecode-1.10.0 → sourcecode-1.12.0}/tests/test_semantic_analyzer_python.py +0 -0
  181. {sourcecode-1.10.0 → sourcecode-1.12.0}/tests/test_semantic_import_resolution.py +0 -0
  182. {sourcecode-1.10.0 → sourcecode-1.12.0}/tests/test_semantic_schema.py +0 -0
  183. {sourcecode-1.10.0 → sourcecode-1.12.0}/tests/test_signal_hierarchy.py +0 -0
  184. {sourcecode-1.10.0 → sourcecode-1.12.0}/tests/test_summarizer.py +0 -0
  185. {sourcecode-1.10.0 → sourcecode-1.12.0}/tests/test_telemetry.py +0 -0
  186. {sourcecode-1.10.0 → sourcecode-1.12.0}/tests/test_workspace_analyzer.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: sourcecode
3
- Version: 1.10.0
3
+ Version: 1.12.0
4
4
  Summary: Deterministic codebase context for AI coding agents
5
5
  License: Apache License
6
6
  Version 2.0, January 2004
@@ -254,48 +254,45 @@ sourcecode version
254
254
 
255
255
  ## Quickstart
256
256
 
257
- The most useful command for integrating `sourcecode` into an AI agent:
257
+ The primary command a high-signal, low-noise summary for Java/Spring codebases:
258
258
 
259
259
  ```bash
260
- sourcecode --agent
260
+ sourcecode --compact
261
+ # ~600-800 tokens: stack, entry points, dependencies, risk flags, confidence.
262
+
263
+ sourcecode --compact --git-context
264
+ # Adds git hotspots and uncommitted file count.
265
+
266
+ sourcecode --compact --copy
267
+ # Copies the result to clipboard.
261
268
  ```
262
269
 
263
- It produces a structured JSON with the essential sections (no noise, no file tree), ready to paste into an LLM context:
270
+ Example output for a Spring Boot project:
264
271
 
265
272
  ```json
266
273
  {
267
- "project": {
268
- "type": "fullstack",
269
- "summary": "Full-stack project in Nodejs, mvc, 4075 source files. Domains: atlas-client, atlas-server, atlas-hub, atlas-reports. 3300 dependencies (java, nodejs).",
270
- "primary_stack": "nodejs",
271
- "secondary_stacks": ["java"]
274
+ "project_type": "api",
275
+ "stacks": [{ "stack": "java", "frameworks": ["Spring Boot", "MyBatis"] }],
276
+ "entry_points": {
277
+ "bootstrap": ["src/main/java/io/spring/RealWorldApplication.java"],
278
+ "security": ["src/main/java/io/spring/api/security/WebSecurityConfig.java"],
279
+ "controllers": { "count": 8, "sample": [...] }
272
280
  },
273
- "entry_points": [
274
- {
275
- "path": "atlas-server/src/main/java/com/example/atlas/AtlasServerApplication.java",
276
- "stack": "java",
277
- "kind": "application",
278
- "confidence": "high"
279
- },
280
- {
281
- "path": "atlas-client/src/main.ts",
282
- "stack": "nodejs",
283
- "kind": "entrypoint",
284
- "confidence": "high"
285
- }
281
+ "key_dependencies": [
282
+ { "name": "org.mybatis.spring.boot:mybatis-spring-boot-starter",
283
+ "version": "2.2.2", "risk_flags": ["spring-boot-2.x-eol"] }
286
284
  ],
287
- "runtime_packages": [ ... ],
288
- "dependencies": { ... },
289
- "env_map": { ... },
290
- "code_notes": [ ... ]
285
+ "language_version": "11",
286
+ "deployment": { "spring_boot_version": "2.6.3" },
287
+ "mybatis": { "mapper_interfaces": 4, "xml_files": 4 },
288
+ "confidence_summary": { "overall": "high" }
291
289
  }
292
290
  ```
293
291
 
294
- For large repositories where context matters, use `--compact` to reduce to ~600-800 tokens:
292
+ For full structured output with per-file contracts and signals, use `--agent`:
295
293
 
296
294
  ```bash
297
- sourcecode --compact --copy
298
- # Copies the summary to the clipboard. Ready to paste.
295
+ sourcecode --agent
299
296
  ```
300
297
 
301
298
  ---
@@ -304,41 +301,18 @@ sourcecode --compact --copy
304
301
 
305
302
  ### Global options
306
303
 
307
- | Flag | Alias | Type | Default | Description | Status |
308
- |------|-------|------|---------|-------------|--------|
309
- | `--format` | `-f` | `json\|yaml` | `json` | Output format. YAML is more readable, JSON preferred in pipelines. | ✅ CORE |
310
- | `--output` | `-o` | `PATH` | stdout | Writes output to a file instead of stdout. | CORE |
311
- | `--compact` | | flag | off | ~600-800 token output: stacks, entry points, deps, gaps. No file tree. | ✅ CORE |
312
- | `--agent` | | flag | off | JSON optimized for agents. Automatically enables `--dependencies`, `--env-map`, `--code-notes`. | CORE |
313
- | `--dependencies` | | flag | off | Analyzes direct and transitive deps from manifests and lockfiles. | ✅ CORE |
314
- | `--git-context` | `-g` | flag | off | Includes recent commits, change hotspots, uncommitted changes, contributors. | ✅ CORE |
315
- | `--git-depth` | | `INT [1–100]` | `20` | Number of recent commits with `--git-context`. | CORE |
316
- | `--git-days` | | `INT [1–3650]` | `90` | Window in days to detect hotspots with `--git-context`. | ✅ CORE |
317
- | `--env-map` | | flag | off | Maps environment variables: key, type, category, files that reference them. | ✅ CORE |
318
- | `--code-notes` | | flag | off | Extracts inline annotations: TODO, FIXME, HACK, BUG, DEPRECATED, NOTE, etc. | ✅ CORE |
319
- | `--copy` | `-c` | flag | off | Copies output to the clipboard after successful execution. | ✅ CORE |
320
- | `--depth` | | `INT [1–20]` | `4` | Maximum file tree traversal depth. Java/Maven requires ≥8. | ✅ CORE |
321
- | `--mode` | | `contract\|standard\|raw` | `contract` | `contract`: minimal contracts per file. `standard`: full detail. `raw`: project level only. | ✅ CORE |
322
- | `--tree` | | flag | off | Includes full `file_tree` and `file_paths` in the output. Increases size significantly. | ✅ CORE |
323
- | `--changed-only` | | flag | off | Contract mode: only files modified in git (staged, unstaged, untracked). | ✅ CORE |
324
- | `--rank-by` | | `relevance\|centrality\|git-churn` | `relevance` | File ranking strategy in contract mode. | ✅ CORE |
325
- | `--semantics` | | flag | off | Cross-file symbol resolution, call graph with confidence levels, fan-in/fan-out hotspots. Slower. | 🧪 EXP |
326
- | `--architecture` | | flag | off | Architectural layer inference (MVC/hexagonal/bounded contexts). Low confidence without `--semantics`. | 🧪 EXP |
327
- | `--graph-modules` | | flag | off | Structural module graph: nodes (files/symbols) and edges (imports, calls, contains). | 🧪 EXP |
328
- | `--graph-detail` | | `high\|medium\|full` | `high` | Module graph detail level. | 🧪 EXP |
329
- | `--max-nodes` | | `INT [≥1]` | — | Maximum nodes in `--graph-modules`. Prevents huge graphs in large repos. | 🧪 EXP |
330
- | `--graph-edges` | | `TEXT` | all | Edge types for `--graph-modules`, comma-separated: `imports,calls,contains`. | 🧪 EXP |
331
- | `--docs` | | flag | off | Extracts docstrings, function signatures, and module comments. | 🧪 EXP |
332
- | `--docs-depth` | | `module\|symbols\|full` | `symbols` | Docs extraction depth. `full` includes private symbols. | 🧪 EXP |
333
- | `--symbol` | | `TEXT` | — | Contract mode: localized context for a specific symbol. Python, TS, JS only. **Does not support Java.** | 🧪 EXP |
334
- | `--max-importers` | | `INT [1–10000]` | `50` | Limit on importer files returned by `--symbol`. | 🧪 EXP |
335
- | `--full-metrics` | | flag | off | Per-file technical metrics: LOC, cyclomatic complexity, coverage. Aimed at CI, not at agents. | 🧪 EXP |
336
- | `--emit-graph` | | flag | off | Contract mode: includes a compact dependency graph (nodes + edges) in the output. | 🚧 WIP |
337
- | `--entrypoints-only` | | flag | off | Contract mode: only files with exports or entry points. Note: includes *all* files with exports. | 🚧 WIP |
338
- | `--max-symbols` | | `INT [≥1]` | — | Limits total exported symbols in contract mode. Discards lower-ranked files. | 🚧 WIP |
339
- | `--no-redact` | | flag | off | Disables automatic secret redaction. Output may contain sensitive values. | 🚧 WIP |
340
- | `--trace-pipeline` | | flag | off | Diagnostic mode: includes a trace of each candidate and filtering decision. Debugging only. | 🚧 WIP |
341
- | `--version` | `-v` | flag | — | Shows version and exits. | ✅ CORE |
304
+ | Flag | Alias | Type | Default | Description |
305
+ |------|-------|------|---------|-------------|
306
+ | `--compact` | | flag | off | **Recommended.** ~600-800 token summary: stack, entry points, deps, risk flags, confidence. |
307
+ | `--git-context` | `-g` | flag | off | Adds git hotspots (top changed files), branch, uncommitted file count. Use with `--compact`. |
308
+ | `--agent` | | flag | off | Full structured JSON for AI agents. Auto-enables dependency, env-var, and code-notes analysis. |
309
+ | `--changed-only` | | flag | off | Limit output to git-modified files (staged, unstaged, untracked). |
310
+ | `--depth` | | `INT [1–20]` | `4` | File tree traversal depth. Java projects auto-adjust to 12. |
311
+ | `--format` | `-f` | `json\|yaml` | `json` | Output format. JSON preferred in pipelines. |
312
+ | `--output` | `-o` | `PATH` | stdout | Write output to a file instead of stdout. |
313
+ | `--copy` | `-c` | flag | off | Copy output to clipboard after a successful run. |
314
+ | `--no-redact` | | flag | off | Disable automatic secret redaction. Output may contain sensitive values. |
315
+ | `--version` | `-v` | flag | | Show version and exit. |
342
316
 
343
317
  ---
344
318
 
@@ -357,5 +331,3 @@ Generates task-specific context for AI agents.
357
331
  | `refactor` | Structural problems, improvement opportunities | 🧪 EXP |
358
332
  | `generate-tests` | Files without tests, coverage gap analysis | 🧪 EXP |
359
333
  | `review-pr` | Changed files + architectural impact | 🧪 EXP |
360
-
361
- ...
@@ -0,0 +1,114 @@
1
+ # sourcecode
2
+
3
+ **Deterministic codebase context for AI coding agents.**
4
+
5
+ ![Version](https://img.shields.io/badge/version-1.0.0-blue)
6
+ ![Status](https://img.shields.io/badge/status-MVP-orange)
7
+ ![Python](https://img.shields.io/badge/python-3.10%2B-green)
8
+
9
+ ---
10
+
11
+ ## What is it?
12
+
13
+ `sourcecode` analyzes a repository and produces a structured context map (JSON or YAML) designed to be consumed by AI agents or language models. It solves the "stuff the whole repo into the prompt" problem by instead producing a deterministic extract: entry points, dependencies, stacks, inline annotations, environment variables, and git activity. It is an MVP tool under active evolution — the semantic analysis and module graph features work but have known limitations that are explicitly documented below.
14
+
15
+ ---
16
+
17
+ ## Installation
18
+
19
+ **Prerequisites:** Python 3.10+
20
+
21
+ ```bash
22
+ pip install sourcecode
23
+ # or with pipx for isolation:
24
+ pipx install sourcecode
25
+ ```
26
+
27
+ Verify installation:
28
+
29
+ ```bash
30
+ sourcecode version
31
+ # sourcecode 1.0.0
32
+ ```
33
+
34
+ ---
35
+
36
+ ## Quickstart
37
+
38
+ The primary command — a high-signal, low-noise summary for Java/Spring codebases:
39
+
40
+ ```bash
41
+ sourcecode --compact
42
+ # ~600-800 tokens: stack, entry points, dependencies, risk flags, confidence.
43
+
44
+ sourcecode --compact --git-context
45
+ # Adds git hotspots and uncommitted file count.
46
+
47
+ sourcecode --compact --copy
48
+ # Copies the result to clipboard.
49
+ ```
50
+
51
+ Example output for a Spring Boot project:
52
+
53
+ ```json
54
+ {
55
+ "project_type": "api",
56
+ "stacks": [{ "stack": "java", "frameworks": ["Spring Boot", "MyBatis"] }],
57
+ "entry_points": {
58
+ "bootstrap": ["src/main/java/io/spring/RealWorldApplication.java"],
59
+ "security": ["src/main/java/io/spring/api/security/WebSecurityConfig.java"],
60
+ "controllers": { "count": 8, "sample": [...] }
61
+ },
62
+ "key_dependencies": [
63
+ { "name": "org.mybatis.spring.boot:mybatis-spring-boot-starter",
64
+ "version": "2.2.2", "risk_flags": ["spring-boot-2.x-eol"] }
65
+ ],
66
+ "language_version": "11",
67
+ "deployment": { "spring_boot_version": "2.6.3" },
68
+ "mybatis": { "mapper_interfaces": 4, "xml_files": 4 },
69
+ "confidence_summary": { "overall": "high" }
70
+ }
71
+ ```
72
+
73
+ For full structured output with per-file contracts and signals, use `--agent`:
74
+
75
+ ```bash
76
+ sourcecode --agent
77
+ ```
78
+
79
+ ---
80
+
81
+ ## Flags reference
82
+
83
+ ### Global options
84
+
85
+ | Flag | Alias | Type | Default | Description |
86
+ |------|-------|------|---------|-------------|
87
+ | `--compact` | | flag | off | **Recommended.** ~600-800 token summary: stack, entry points, deps, risk flags, confidence. |
88
+ | `--git-context` | `-g` | flag | off | Adds git hotspots (top changed files), branch, uncommitted file count. Use with `--compact`. |
89
+ | `--agent` | | flag | off | Full structured JSON for AI agents. Auto-enables dependency, env-var, and code-notes analysis. |
90
+ | `--changed-only` | | flag | off | Limit output to git-modified files (staged, unstaged, untracked). |
91
+ | `--depth` | | `INT [1–20]` | `4` | File tree traversal depth. Java projects auto-adjust to 12. |
92
+ | `--format` | `-f` | `json\|yaml` | `json` | Output format. JSON preferred in pipelines. |
93
+ | `--output` | `-o` | `PATH` | stdout | Write output to a file instead of stdout. |
94
+ | `--copy` | `-c` | flag | off | Copy output to clipboard after a successful run. |
95
+ | `--no-redact` | | flag | off | Disable automatic secret redaction. Output may contain sensitive values. |
96
+ | `--version` | `-v` | flag | — | Show version and exit. |
97
+
98
+ ---
99
+
100
+ ## Subcommands
101
+
102
+ ### `prepare-context TASK [PATH]`
103
+
104
+ Generates task-specific context for AI agents.
105
+
106
+ | Task | Description | Status |
107
+ |------|-------------|--------|
108
+ | `explain` | Architecture, entry points, key dependencies | ✅ CORE |
109
+ | `fix-bug` | Files prioritized by risk, inline annotations | ✅ CORE |
110
+ | `onboard` | Full context for new agents or developers | ✅ CORE |
111
+ | `delta` | Incremental context: only files changed in git | ✅ CORE |
112
+ | `refactor` | Structural problems, improvement opportunities | 🧪 EXP |
113
+ | `generate-tests` | Files without tests, coverage gap analysis | 🧪 EXP |
114
+ | `review-pr` | Changed files + architectural impact | 🧪 EXP |
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "sourcecode"
7
- version = "1.10.0"
7
+ version = "1.12.0"
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.10.0"
3
+ __version__ = "1.12.0"
@@ -141,10 +141,14 @@ def _check_pipeline_coherence(sm: "SourceMap") -> list[str]: # type: ignore[nam
141
141
  _HELP = """\
142
142
  Compressed AI-ready context for Java/Spring enterprise codebases.
143
143
 
144
+ [bold]Primary usage:[/bold]
145
+ sourcecode --compact high-signal summary (~600-800 tokens)
146
+ sourcecode --compact --git-context include git hotspots and uncommitted files
147
+
144
148
  [bold]Examples:[/bold]
145
149
  sourcecode saint-server --compact
150
+ sourcecode . --compact --git-context --copy
146
151
  sourcecode . --changed-only --git-context
147
- sourcecode saint-server --symbol SeguridadRestController
148
152
  sourcecode prepare-context onboard saint-server
149
153
  sourcecode prepare-context delta . --since main
150
154
 
@@ -565,7 +569,8 @@ def main(
565
569
  symbol: Optional[str] = typer.Option(
566
570
  None,
567
571
  "--symbol",
568
- help="Extract context for a specific symbol: defining file + all importers.",
572
+ hidden=True,
573
+ help="Extract context for a specific symbol (Python/TS/JS only — not supported for Java).",
569
574
  ),
570
575
  max_importers: int = typer.Option(
571
576
  50,
@@ -586,10 +591,10 @@ def main(
586
591
 
587
592
  \b
588
593
  Examples:
589
- sourcecode analyze current directory
590
- sourcecode /path/to/repo analyze specific path
591
- sourcecode --agent agent-optimized output
592
- sourcecode --agent --git-context include git activity signals
594
+ sourcecode --compact high-signal summary (recommended)
595
+ sourcecode --compact --git-context include git hotspots
596
+ sourcecode /path/to/repo --compact analyze specific path
597
+ sourcecode --agent agent-optimized output (full detail)
593
598
  """
594
599
  # First-run consent (skip for telemetry/version/config subcommands)
595
600
  if ctx.invoked_subcommand not in ("telemetry", "version", "config"):
@@ -629,6 +634,10 @@ def main(
629
634
  )
630
635
  raise typer.Exit(code=1)
631
636
 
637
+ if symbol is not None and not symbol.strip():
638
+ typer.echo("symbol query cannot be empty", err=True)
639
+ raise typer.Exit(code=2)
640
+
632
641
  if symbol and mode not in ("contract", "standard"):
633
642
  typer.echo(
634
643
  f"Error: --symbol requires --mode contract or standard (got '{mode}'). "
@@ -760,6 +769,16 @@ def main(
760
769
  _java_min_depth = 12
761
770
  effective_depth = max(depth, _java_min_depth) if _is_java and depth < _java_min_depth else depth
762
771
 
772
+ if symbol is not None and _is_java:
773
+ typer.echo(
774
+ f"Error: --symbol is not supported for Java/JVM repositories. "
775
+ "Per-file AST extraction is unavailable for JVM — symbol search only works with Python, TypeScript, and JavaScript. "
776
+ "Alternatives: use --agent --compact to get file relevance scores, "
777
+ "or use --git-context to find recently changed files.",
778
+ err=True,
779
+ )
780
+ raise typer.Exit(code=1)
781
+
763
782
  # --agent: enable signal analyzers; output via agent_view (not compact)
764
783
  if agent:
765
784
  dependencies = True
@@ -1485,7 +1504,9 @@ def main(
1485
1504
  if _is_contract_mode and sm.file_contracts:
1486
1505
  from sourcecode.serializer import _serialize_contract_minimal
1487
1506
  data.pop("file_relevance", None)
1488
- _MAX_AGENT_CONTRACTS = 10
1507
+ _jvm_stacks_agent = {"java", "kotlin", "scala", "groovy"}
1508
+ _is_jvm_agent = any(s.stack in _jvm_stacks_agent for s in sm.stacks)
1509
+ _MAX_AGENT_CONTRACTS = 50 if _is_jvm_agent else 10
1489
1510
  _all_contracts = sm.file_contracts
1490
1511
  _sorted = sorted(_all_contracts, key=lambda c: getattr(c, "relevance_score", 0.0), reverse=True)
1491
1512
  _sampled = _sorted[:_MAX_AGENT_CONTRACTS]
@@ -41,6 +41,34 @@ _M3_FILTRO_PARAMS_RE = re.compile(
41
41
  r'(?:[^)]*nivelRequerido\s*=\s*(\d+))?'
42
42
  )
43
43
 
44
+ # Security config detection
45
+ _WEB_SECURITY_CONFIGURER_RE = re.compile(r'WebSecurityConfigurerAdapter\b')
46
+ _SECURITY_FILTER_CHAIN_RE = re.compile(r'SecurityFilterChain\b')
47
+ _SECURITY_CONFIG_ANNOTATION_RE = re.compile(r'@EnableWebSecurity\b')
48
+ # JWT/token filter detection (files that process every request)
49
+ _ONCE_PER_REQUEST_FILTER_RE = re.compile(r'extends\s+(?:OncePerRequestFilter|GenericFilterBean)\b')
50
+ _JWT_FILTER_KEYWORDS_RE = re.compile(r'\b(?:jwt|token|bearer|authorization)\b', re.IGNORECASE)
51
+
52
+ # @Transactional detection
53
+ _TRANSACTIONAL_RE = re.compile(r'@Transactional\b')
54
+ # Extracts class name: `public class Foo` or `class Foo`
55
+ _CLASS_NAME_RE = re.compile(r'\bclass\s+([A-Z][A-Za-z0-9_]*)')
56
+
57
+ # Gradle plugin Spring Boot version: id 'org.springframework.boot' version '2.6.3'
58
+ _GRADLE_SB_PLUGIN_RE = re.compile(
59
+ r"""id\s*['"]\s*org\.springframework\.boot\s*['"]\s+version\s*['"]([\d.]+)['"']""",
60
+ re.IGNORECASE,
61
+ )
62
+ # Gradle Java version: sourceCompatibility = '11' or sourceCompatibility = JavaVersion.VERSION_11
63
+ _GRADLE_JAVA_VERSION_RE = re.compile(
64
+ r"""(?:sourceCompatibility|targetCompatibility|javaVersion)\s*=\s*['"]?([0-9.]+)['"]?""",
65
+ re.IGNORECASE,
66
+ )
67
+ # JavaVersion.VERSION_11 form
68
+ _GRADLE_JAVA_ENUM_RE = re.compile(
69
+ r"""(?:sourceCompatibility|targetCompatibility)\s*=\s*JavaVersion\.VERSION_(\d+)"""
70
+ )
71
+
44
72
 
45
73
  class JavaDetector(AbstractDetector):
46
74
  name = "java"
@@ -69,6 +97,12 @@ class JavaDetector(AbstractDetector):
69
97
  if "build.gradle" in context.manifests:
70
98
  manifests.append("build.gradle")
71
99
  frameworks.extend(self._frameworks_from_gradle(context.root / "build.gradle"))
100
+ if language_version is None:
101
+ try:
102
+ gradle_content = "\n".join(read_text_lines(context.root / "build.gradle"))
103
+ language_version = self._extract_gradle_java_version(gradle_content)
104
+ except OSError:
105
+ pass
72
106
 
73
107
  # Detect app server from descriptor files
74
108
  all_paths = flatten_file_tree(context.file_tree)
@@ -81,6 +115,7 @@ class JavaDetector(AbstractDetector):
81
115
  spring_profiles = self._detect_spring_profiles(context.root, all_paths)
82
116
 
83
117
  entry_points = self._collect_entry_points(context)
118
+ transactional_classes = self._collect_transactional_classes(context, all_paths)
84
119
  stack = StackDetection(
85
120
  stack="java",
86
121
  detection_method="manifest",
@@ -91,6 +126,7 @@ class JavaDetector(AbstractDetector):
91
126
  packaging=packaging,
92
127
  app_server_hint=app_server_hint,
93
128
  spring_profiles=spring_profiles,
129
+ transactional_classes=transactional_classes,
94
130
  )
95
131
  return [stack], entry_points
96
132
 
@@ -196,8 +232,24 @@ class JavaDetector(AbstractDetector):
196
232
  return frameworks
197
233
 
198
234
  def _frameworks_from_gradle(self, path: Path) -> list[FrameworkDetection]:
199
- content = "\n".join(read_text_lines(path)).lower()
200
- return self._detect_jvm_frameworks(content, "build.gradle")
235
+ original = "\n".join(read_text_lines(path))
236
+ content = original.lower()
237
+ sb_version = self._extract_gradle_sb_version(original)
238
+ return self._detect_jvm_frameworks(content, "build.gradle", sb_version=sb_version)
239
+
240
+ def _extract_gradle_sb_version(self, content: str) -> str | None:
241
+ m = _GRADLE_SB_PLUGIN_RE.search(content)
242
+ return m.group(1) if m else None
243
+
244
+ def _extract_gradle_java_version(self, content: str) -> str | None:
245
+ m = _GRADLE_JAVA_ENUM_RE.search(content)
246
+ if m:
247
+ v = m.group(1)
248
+ return "1." + v if int(v) <= 8 else v
249
+ m = _GRADLE_JAVA_VERSION_RE.search(content)
250
+ if m:
251
+ return m.group(1)
252
+ return None
201
253
 
202
254
  def _detect_jvm_frameworks(self, text: str, source: str, *, sb_version: str | None = None) -> list[FrameworkDetection]:
203
255
  frameworks: list[FrameworkDetection] = []
@@ -319,7 +371,11 @@ class JavaDetector(AbstractDetector):
319
371
  return []
320
372
 
321
373
  # Quick pre-filter before running regexes
322
- if ("Controller" not in content and "Filter" not in content
374
+ has_controller = "Controller" in content
375
+ has_filter = "Filter" in content
376
+ has_security = "WebSecurityConfigurerAdapter" in content or "SecurityFilterChain" in content or "EnableWebSecurity" in content
377
+ has_once_filter = "OncePerRequestFilter" in content or "GenericFilterBean" in content
378
+ if (not has_controller and not has_filter and not has_security
323
379
  and "ControllerAdvice" not in content
324
380
  and "M3FiltroSeguridad" not in content):
325
381
  return []
@@ -379,6 +435,23 @@ class JavaDetector(AbstractDetector):
379
435
  path=rel_path, stack="java", kind="filter",
380
436
  source="annotation", confidence="medium",
381
437
  )]
438
+ if has_security and (
439
+ _WEB_SECURITY_CONFIGURER_RE.search(content)
440
+ or _SECURITY_CONFIG_ANNOTATION_RE.search(content)
441
+ or _SECURITY_FILTER_CHAIN_RE.search(content)
442
+ ):
443
+ return [EntryPoint(
444
+ path=rel_path, stack="java", kind="security_config",
445
+ source="annotation", confidence="high",
446
+ evidence="Spring Security configuration",
447
+ )]
448
+ if has_once_filter and _ONCE_PER_REQUEST_FILTER_RE.search(content):
449
+ is_jwt = bool(_JWT_FILTER_KEYWORDS_RE.search(content))
450
+ return [EntryPoint(
451
+ path=rel_path, stack="java", kind="security_filter",
452
+ source="annotation", confidence="high",
453
+ evidence="jwt_filter" if is_jwt else "request_filter",
454
+ )]
382
455
  return []
383
456
 
384
457
  def _parse_web_xml(self, abs_path: Path, rel_path: str) -> list[EntryPoint]:
@@ -412,3 +485,26 @@ class JavaDetector(AbstractDetector):
412
485
  seen.add(framework.name)
413
486
  result.append(framework)
414
487
  return result
488
+
489
+ def _collect_transactional_classes(self, context: DetectionContext, all_paths: list[str]) -> list[str]:
490
+ """Scan Java source files for @Transactional and return unique class names."""
491
+ classes: list[str] = []
492
+ seen: set[str] = set()
493
+ java_paths = [p for p in all_paths if p.endswith(".java") and "/test/" not in p and "/tests/" not in p]
494
+ for rel_path in java_paths[:_MAX_JAVA_ENTRY_SCAN]:
495
+ abs_path = context.root / rel_path
496
+ try:
497
+ if abs_path.stat().st_size > _MAX_FILE_SIZE:
498
+ continue
499
+ content = abs_path.read_text(encoding="utf-8", errors="replace")
500
+ except OSError:
501
+ continue
502
+ if not _TRANSACTIONAL_RE.search(content):
503
+ continue
504
+ m = _CLASS_NAME_RE.search(content)
505
+ if m:
506
+ cls = m.group(1)
507
+ if cls not in seen:
508
+ seen.add(cls)
509
+ classes.append(cls)
510
+ return classes
@@ -121,6 +121,7 @@ class ProjectDetector:
121
121
  packaging=stack.packaging,
122
122
  app_server_hint=stack.app_server_hint,
123
123
  spring_profiles=list(stack.spring_profiles),
124
+ transactional_classes=list(stack.transactional_classes),
124
125
  )
125
126
 
126
127
  def _merge_stack(self, current: StackDetection, incoming: StackDetection) -> StackDetection:
@@ -144,6 +145,8 @@ class ProjectDetector:
144
145
  current.app_server_hint = incoming.app_server_hint
145
146
  if incoming.spring_profiles and not current.spring_profiles:
146
147
  current.spring_profiles = list(incoming.spring_profiles)
148
+ if incoming.transactional_classes and not current.transactional_classes:
149
+ current.transactional_classes = list(incoming.transactional_classes)
147
150
  return current
148
151
 
149
152
  def _merge_frameworks(
@@ -563,6 +563,25 @@ class TaskContextBuilder:
563
563
  except Exception:
564
564
  pass
565
565
 
566
+ # ── 5c. review-pr suspected_areas (needs git uncommitted_files) ──────
567
+ if task_name == "review-pr" and spec.enable_code_notes:
568
+ pr_areas: dict[str, int] = {}
569
+ for path in uncommitted_files:
570
+ pr_areas[path] = pr_areas.get(path, 0) + 10
571
+ review_kinds = {"FIXME", "TODO", "BUG", "HACK"}
572
+ for note in cn_notes_for_ranking:
573
+ if note.kind in review_kinds:
574
+ pr_areas[note.path] = pr_areas.get(note.path, 0) + 1
575
+ _BOOST_STEMS = ("Controller", "Service", "Repository", "Mapper", "Filter", "Security")
576
+ for path in all_paths:
577
+ stem = Path(path).stem
578
+ if any(k in stem for k in _BOOST_STEMS):
579
+ pr_areas[path] = pr_areas.get(path, 0) + 2
580
+ suspected_areas = [
581
+ p for p, _ in sorted(pr_areas.items(), key=lambda x: -x[1])[:8]
582
+ if not self._is_test(p)
583
+ ]
584
+
566
585
  # ── 6. Rank files ──────────────────────────────────────────────────
567
586
  entry_set = {ep.path for ep in entry_points}
568
587
  test_set = {p for p in all_paths if self._is_test(p)}
@@ -68,6 +68,7 @@ class StackDetection:
68
68
  packaging: Optional[str] = None # e.g. "war" | "jar"
69
69
  app_server_hint: Optional[str] = None # e.g. "weblogic" | "wildfly"
70
70
  spring_profiles: list[str] = field(default_factory=list) # detected Spring profiles
71
+ transactional_classes: list[str] = field(default_factory=list) # classes with @Transactional
71
72
 
72
73
 
73
74
  @dataclass