sourcecode 1.28.0__tar.gz → 1.29.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 (189) hide show
  1. {sourcecode-1.28.0 → sourcecode-1.29.0}/PKG-INFO +3 -3
  2. {sourcecode-1.28.0 → sourcecode-1.29.0}/README.md +2 -2
  3. {sourcecode-1.28.0 → sourcecode-1.29.0}/pyproject.toml +1 -1
  4. {sourcecode-1.28.0 → sourcecode-1.29.0}/src/sourcecode/__init__.py +1 -1
  5. {sourcecode-1.28.0 → sourcecode-1.29.0}/src/sourcecode/cli.py +58 -1
  6. {sourcecode-1.28.0 → sourcecode-1.29.0}/src/sourcecode/prepare_context.py +172 -10
  7. {sourcecode-1.28.0 → sourcecode-1.29.0}/tests/test_v1_10_regressions.py +39 -13
  8. {sourcecode-1.28.0 → sourcecode-1.29.0}/.agents/skills/source-command-gsd-join-discord/SKILL.md +0 -0
  9. {sourcecode-1.28.0 → sourcecode-1.29.0}/.agents/skills/source-command-gsd-review-backlog/SKILL.md +0 -0
  10. {sourcecode-1.28.0 → sourcecode-1.29.0}/.agents/skills/source-command-gsd-workstreams/SKILL.md +0 -0
  11. {sourcecode-1.28.0 → sourcecode-1.29.0}/.continue-here.md +0 -0
  12. {sourcecode-1.28.0 → sourcecode-1.29.0}/.github/workflows/build-windows.yml +0 -0
  13. {sourcecode-1.28.0 → sourcecode-1.29.0}/.gitignore +0 -0
  14. {sourcecode-1.28.0 → sourcecode-1.29.0}/.ruff.toml +0 -0
  15. {sourcecode-1.28.0 → sourcecode-1.29.0}/CONTRIBUTING.md +0 -0
  16. {sourcecode-1.28.0 → sourcecode-1.29.0}/LICENSE +0 -0
  17. {sourcecode-1.28.0 → sourcecode-1.29.0}/SECURITY.md +0 -0
  18. {sourcecode-1.28.0 → sourcecode-1.29.0}/docs/privacy.md +0 -0
  19. {sourcecode-1.28.0 → sourcecode-1.29.0}/docs/schema.md +0 -0
  20. {sourcecode-1.28.0 → sourcecode-1.29.0}/raw +0 -0
  21. {sourcecode-1.28.0 → sourcecode-1.29.0}/run_cli.py +0 -0
  22. {sourcecode-1.28.0 → sourcecode-1.29.0}/src/sourcecode/adaptive_scanner.py +0 -0
  23. {sourcecode-1.28.0 → sourcecode-1.29.0}/src/sourcecode/architecture_analyzer.py +0 -0
  24. {sourcecode-1.28.0 → sourcecode-1.29.0}/src/sourcecode/architecture_summary.py +0 -0
  25. {sourcecode-1.28.0 → sourcecode-1.29.0}/src/sourcecode/ast_extractor.py +0 -0
  26. {sourcecode-1.28.0 → sourcecode-1.29.0}/src/sourcecode/classifier.py +0 -0
  27. {sourcecode-1.28.0 → sourcecode-1.29.0}/src/sourcecode/code_notes_analyzer.py +0 -0
  28. {sourcecode-1.28.0 → sourcecode-1.29.0}/src/sourcecode/confidence_analyzer.py +0 -0
  29. {sourcecode-1.28.0 → sourcecode-1.29.0}/src/sourcecode/context_scorer.py +0 -0
  30. {sourcecode-1.28.0 → sourcecode-1.29.0}/src/sourcecode/context_summarizer.py +0 -0
  31. {sourcecode-1.28.0 → sourcecode-1.29.0}/src/sourcecode/contract_model.py +0 -0
  32. {sourcecode-1.28.0 → sourcecode-1.29.0}/src/sourcecode/contract_pipeline.py +0 -0
  33. {sourcecode-1.28.0 → sourcecode-1.29.0}/src/sourcecode/coverage_parser.py +0 -0
  34. {sourcecode-1.28.0 → sourcecode-1.29.0}/src/sourcecode/dependency_analyzer.py +0 -0
  35. {sourcecode-1.28.0 → sourcecode-1.29.0}/src/sourcecode/detectors/__init__.py +0 -0
  36. {sourcecode-1.28.0 → sourcecode-1.29.0}/src/sourcecode/detectors/base.py +0 -0
  37. {sourcecode-1.28.0 → sourcecode-1.29.0}/src/sourcecode/detectors/csproj_parser.py +0 -0
  38. {sourcecode-1.28.0 → sourcecode-1.29.0}/src/sourcecode/detectors/dart.py +0 -0
  39. {sourcecode-1.28.0 → sourcecode-1.29.0}/src/sourcecode/detectors/dotnet.py +0 -0
  40. {sourcecode-1.28.0 → sourcecode-1.29.0}/src/sourcecode/detectors/elixir.py +0 -0
  41. {sourcecode-1.28.0 → sourcecode-1.29.0}/src/sourcecode/detectors/go.py +0 -0
  42. {sourcecode-1.28.0 → sourcecode-1.29.0}/src/sourcecode/detectors/heuristic.py +0 -0
  43. {sourcecode-1.28.0 → sourcecode-1.29.0}/src/sourcecode/detectors/hybrid.py +0 -0
  44. {sourcecode-1.28.0 → sourcecode-1.29.0}/src/sourcecode/detectors/java.py +0 -0
  45. {sourcecode-1.28.0 → sourcecode-1.29.0}/src/sourcecode/detectors/jvm_ext.py +0 -0
  46. {sourcecode-1.28.0 → sourcecode-1.29.0}/src/sourcecode/detectors/nodejs.py +0 -0
  47. {sourcecode-1.28.0 → sourcecode-1.29.0}/src/sourcecode/detectors/parsers.py +0 -0
  48. {sourcecode-1.28.0 → sourcecode-1.29.0}/src/sourcecode/detectors/php.py +0 -0
  49. {sourcecode-1.28.0 → sourcecode-1.29.0}/src/sourcecode/detectors/project.py +0 -0
  50. {sourcecode-1.28.0 → sourcecode-1.29.0}/src/sourcecode/detectors/python.py +0 -0
  51. {sourcecode-1.28.0 → sourcecode-1.29.0}/src/sourcecode/detectors/ruby.py +0 -0
  52. {sourcecode-1.28.0 → sourcecode-1.29.0}/src/sourcecode/detectors/rust.py +0 -0
  53. {sourcecode-1.28.0 → sourcecode-1.29.0}/src/sourcecode/detectors/systems.py +0 -0
  54. {sourcecode-1.28.0 → sourcecode-1.29.0}/src/sourcecode/detectors/terraform.py +0 -0
  55. {sourcecode-1.28.0 → sourcecode-1.29.0}/src/sourcecode/detectors/tooling.py +0 -0
  56. {sourcecode-1.28.0 → sourcecode-1.29.0}/src/sourcecode/doc_analyzer.py +0 -0
  57. {sourcecode-1.28.0 → sourcecode-1.29.0}/src/sourcecode/entrypoint_classifier.py +0 -0
  58. {sourcecode-1.28.0 → sourcecode-1.29.0}/src/sourcecode/env_analyzer.py +0 -0
  59. {sourcecode-1.28.0 → sourcecode-1.29.0}/src/sourcecode/file_classifier.py +0 -0
  60. {sourcecode-1.28.0 → sourcecode-1.29.0}/src/sourcecode/git_analyzer.py +0 -0
  61. {sourcecode-1.28.0 → sourcecode-1.29.0}/src/sourcecode/graph_analyzer.py +0 -0
  62. {sourcecode-1.28.0 → sourcecode-1.29.0}/src/sourcecode/metrics_analyzer.py +0 -0
  63. {sourcecode-1.28.0 → sourcecode-1.29.0}/src/sourcecode/progress.py +0 -0
  64. {sourcecode-1.28.0 → sourcecode-1.29.0}/src/sourcecode/ranking_engine.py +0 -0
  65. {sourcecode-1.28.0 → sourcecode-1.29.0}/src/sourcecode/redactor.py +0 -0
  66. {sourcecode-1.28.0 → sourcecode-1.29.0}/src/sourcecode/relevance_scorer.py +0 -0
  67. {sourcecode-1.28.0 → sourcecode-1.29.0}/src/sourcecode/repo_classifier.py +0 -0
  68. {sourcecode-1.28.0 → sourcecode-1.29.0}/src/sourcecode/runtime_classifier.py +0 -0
  69. {sourcecode-1.28.0 → sourcecode-1.29.0}/src/sourcecode/scanner.py +0 -0
  70. {sourcecode-1.28.0 → sourcecode-1.29.0}/src/sourcecode/schema.py +0 -0
  71. {sourcecode-1.28.0 → sourcecode-1.29.0}/src/sourcecode/semantic_analyzer.py +0 -0
  72. {sourcecode-1.28.0 → sourcecode-1.29.0}/src/sourcecode/serializer.py +0 -0
  73. {sourcecode-1.28.0 → sourcecode-1.29.0}/src/sourcecode/summarizer.py +0 -0
  74. {sourcecode-1.28.0 → sourcecode-1.29.0}/src/sourcecode/telemetry/__init__.py +0 -0
  75. {sourcecode-1.28.0 → sourcecode-1.29.0}/src/sourcecode/telemetry/config.py +0 -0
  76. {sourcecode-1.28.0 → sourcecode-1.29.0}/src/sourcecode/telemetry/consent.py +0 -0
  77. {sourcecode-1.28.0 → sourcecode-1.29.0}/src/sourcecode/telemetry/events.py +0 -0
  78. {sourcecode-1.28.0 → sourcecode-1.29.0}/src/sourcecode/telemetry/filters.py +0 -0
  79. {sourcecode-1.28.0 → sourcecode-1.29.0}/src/sourcecode/telemetry/transport.py +0 -0
  80. {sourcecode-1.28.0 → sourcecode-1.29.0}/src/sourcecode/tree_utils.py +0 -0
  81. {sourcecode-1.28.0 → sourcecode-1.29.0}/src/sourcecode/workspace.py +0 -0
  82. {sourcecode-1.28.0 → sourcecode-1.29.0}/tests/__init__.py +0 -0
  83. {sourcecode-1.28.0 → sourcecode-1.29.0}/tests/conftest.py +0 -0
  84. {sourcecode-1.28.0 → sourcecode-1.29.0}/tests/fixtures/coverage.xml +0 -0
  85. {sourcecode-1.28.0 → sourcecode-1.29.0}/tests/fixtures/fastapi_app/pyproject.toml +0 -0
  86. {sourcecode-1.28.0 → sourcecode-1.29.0}/tests/fixtures/fastapi_app/src/main.py +0 -0
  87. {sourcecode-1.28.0 → sourcecode-1.29.0}/tests/fixtures/go_service/cmd/api/main.go +0 -0
  88. {sourcecode-1.28.0 → sourcecode-1.29.0}/tests/fixtures/go_service/go.mod +0 -0
  89. {sourcecode-1.28.0 → sourcecode-1.29.0}/tests/fixtures/jacoco.xml +0 -0
  90. {sourcecode-1.28.0 → sourcecode-1.29.0}/tests/fixtures/latin1_sample.java +0 -0
  91. {sourcecode-1.28.0 → sourcecode-1.29.0}/tests/fixtures/latin1_sample_iso.java +0 -0
  92. {sourcecode-1.28.0 → sourcecode-1.29.0}/tests/fixtures/lcov.info +0 -0
  93. {sourcecode-1.28.0 → sourcecode-1.29.0}/tests/fixtures/nextjs_app/app/page.tsx +0 -0
  94. {sourcecode-1.28.0 → sourcecode-1.29.0}/tests/fixtures/nextjs_app/package.json +0 -0
  95. {sourcecode-1.28.0 → sourcecode-1.29.0}/tests/fixtures/nextjs_app/pnpm-lock.yaml +0 -0
  96. {sourcecode-1.28.0 → sourcecode-1.29.0}/tests/fixtures/pnpm_monorepo/apps/web/app/page.tsx +0 -0
  97. {sourcecode-1.28.0 → sourcecode-1.29.0}/tests/fixtures/pnpm_monorepo/apps/web/package.json +0 -0
  98. {sourcecode-1.28.0 → sourcecode-1.29.0}/tests/fixtures/pnpm_monorepo/packages/api/main.py +0 -0
  99. {sourcecode-1.28.0 → sourcecode-1.29.0}/tests/fixtures/pnpm_monorepo/packages/api/pyproject.toml +0 -0
  100. {sourcecode-1.28.0 → sourcecode-1.29.0}/tests/fixtures/pnpm_monorepo/pnpm-workspace.yaml +0 -0
  101. {sourcecode-1.28.0 → sourcecode-1.29.0}/tests/fixtures/spring_boot_minimal/pom.xml +0 -0
  102. {sourcecode-1.28.0 → sourcecode-1.29.0}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/ausente/application/service/FindAusenteService.java +0 -0
  103. {sourcecode-1.28.0 → sourcecode-1.29.0}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/ausente/domain/entities/Ausente.java +0 -0
  104. {sourcecode-1.28.0 → sourcecode-1.29.0}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/ausente/infrastructure/rest/AusenteRestController.java +0 -0
  105. {sourcecode-1.28.0 → sourcecode-1.29.0}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/autocoberturas/application/service/FindAutocoberturasService.java +0 -0
  106. {sourcecode-1.28.0 → sourcecode-1.29.0}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/autocoberturas/domain/entities/Autocoberturas.java +0 -0
  107. {sourcecode-1.28.0 → sourcecode-1.29.0}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/autocoberturas/infrastructure/rest/AutocoberturasRestController.java +0 -0
  108. {sourcecode-1.28.0 → sourcecode-1.29.0}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/calendarioTrabajador/application/service/FindCalendarioTrabajadorService.java +0 -0
  109. {sourcecode-1.28.0 → sourcecode-1.29.0}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/calendarioTrabajador/domain/entities/CalendarioTrabajador.java +0 -0
  110. {sourcecode-1.28.0 → sourcecode-1.29.0}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/calendarioTrabajador/infrastructure/rest/CalendarioTrabajadorRestController.java +0 -0
  111. {sourcecode-1.28.0 → sourcecode-1.29.0}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/departamento/application/service/FindDepartamentoService.java +0 -0
  112. {sourcecode-1.28.0 → sourcecode-1.29.0}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/departamento/domain/entities/Departamento.java +0 -0
  113. {sourcecode-1.28.0 → sourcecode-1.29.0}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/departamento/infrastructure/rest/DepartamentoRestController.java +0 -0
  114. {sourcecode-1.28.0 → sourcecode-1.29.0}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/empleado/application/service/FindEmpleadoService.java +0 -0
  115. {sourcecode-1.28.0 → sourcecode-1.29.0}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/empleado/domain/entities/Empleado.java +0 -0
  116. {sourcecode-1.28.0 → sourcecode-1.29.0}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/empleado/infrastructure/rest/EmpleadoRestController.java +0 -0
  117. {sourcecode-1.28.0 → sourcecode-1.29.0}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/demo/DemoApplication.java +0 -0
  118. {sourcecode-1.28.0 → sourcecode-1.29.0}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/demo/config/FilterConfig.java +0 -0
  119. {sourcecode-1.28.0 → sourcecode-1.29.0}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/demo/domain/Health.java +0 -0
  120. {sourcecode-1.28.0 → sourcecode-1.29.0}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/demo/mapper/HealthMapper.java +0 -0
  121. {sourcecode-1.28.0 → sourcecode-1.29.0}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/demo/repository/HealthRepository.java +0 -0
  122. {sourcecode-1.28.0 → sourcecode-1.29.0}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/demo/service/HealthService.java +0 -0
  123. {sourcecode-1.28.0 → sourcecode-1.29.0}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/demo/web/HealthRestController.java +0 -0
  124. {sourcecode-1.28.0 → sourcecode-1.29.0}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/demo/web/NominaRestController.java +0 -0
  125. {sourcecode-1.28.0 → sourcecode-1.29.0}/tests/fixtures/spring_boot_minimal/src/main/resources/application-dev.yml +0 -0
  126. {sourcecode-1.28.0 → sourcecode-1.29.0}/tests/fixtures/spring_boot_minimal/src/main/resources/application.yml +0 -0
  127. {sourcecode-1.28.0 → sourcecode-1.29.0}/tests/fixtures/spring_boot_minimal/src/main/resources/mapper/HealthMapper.xml +0 -0
  128. {sourcecode-1.28.0 → sourcecode-1.29.0}/tests/test_architecture_analyzer.py +0 -0
  129. {sourcecode-1.28.0 → sourcecode-1.29.0}/tests/test_architecture_summary.py +0 -0
  130. {sourcecode-1.28.0 → sourcecode-1.29.0}/tests/test_ast_extractor.py +0 -0
  131. {sourcecode-1.28.0 → sourcecode-1.29.0}/tests/test_block1_reliability.py +0 -0
  132. {sourcecode-1.28.0 → sourcecode-1.29.0}/tests/test_block2_coverage.py +0 -0
  133. {sourcecode-1.28.0 → sourcecode-1.29.0}/tests/test_block5_quality.py +0 -0
  134. {sourcecode-1.28.0 → sourcecode-1.29.0}/tests/test_bug_fixes_v16.py +0 -0
  135. {sourcecode-1.28.0 → sourcecode-1.29.0}/tests/test_classifier.py +0 -0
  136. {sourcecode-1.28.0 → sourcecode-1.29.0}/tests/test_cli.py +0 -0
  137. {sourcecode-1.28.0 → sourcecode-1.29.0}/tests/test_code_notes_analyzer.py +0 -0
  138. {sourcecode-1.28.0 → sourcecode-1.29.0}/tests/test_context_scorer.py +0 -0
  139. {sourcecode-1.28.0 → sourcecode-1.29.0}/tests/test_contract_pipeline.py +0 -0
  140. {sourcecode-1.28.0 → sourcecode-1.29.0}/tests/test_coverage_parser.py +0 -0
  141. {sourcecode-1.28.0 → sourcecode-1.29.0}/tests/test_cross_consistency.py +0 -0
  142. {sourcecode-1.28.0 → sourcecode-1.29.0}/tests/test_dependency_analyzer_node_python.py +0 -0
  143. {sourcecode-1.28.0 → sourcecode-1.29.0}/tests/test_dependency_analyzer_polyglot.py +0 -0
  144. {sourcecode-1.28.0 → sourcecode-1.29.0}/tests/test_dependency_schema.py +0 -0
  145. {sourcecode-1.28.0 → sourcecode-1.29.0}/tests/test_detector_dotnet.py +0 -0
  146. {sourcecode-1.28.0 → sourcecode-1.29.0}/tests/test_detector_go_rust_java.py +0 -0
  147. {sourcecode-1.28.0 → sourcecode-1.29.0}/tests/test_detector_nodejs.py +0 -0
  148. {sourcecode-1.28.0 → sourcecode-1.29.0}/tests/test_detector_php_ruby_dart.py +0 -0
  149. {sourcecode-1.28.0 → sourcecode-1.29.0}/tests/test_detector_python.py +0 -0
  150. {sourcecode-1.28.0 → sourcecode-1.29.0}/tests/test_detector_universal_managed.py +0 -0
  151. {sourcecode-1.28.0 → sourcecode-1.29.0}/tests/test_detector_universal_systems.py +0 -0
  152. {sourcecode-1.28.0 → sourcecode-1.29.0}/tests/test_detectors_base.py +0 -0
  153. {sourcecode-1.28.0 → sourcecode-1.29.0}/tests/test_doc_analyzer_jsdom.py +0 -0
  154. {sourcecode-1.28.0 → sourcecode-1.29.0}/tests/test_doc_analyzer_python.py +0 -0
  155. {sourcecode-1.28.0 → sourcecode-1.29.0}/tests/test_encoding_regression.py +0 -0
  156. {sourcecode-1.28.0 → sourcecode-1.29.0}/tests/test_graph_analyzer_polyglot.py +0 -0
  157. {sourcecode-1.28.0 → sourcecode-1.29.0}/tests/test_graph_analyzer_python_node.py +0 -0
  158. {sourcecode-1.28.0 → sourcecode-1.29.0}/tests/test_graph_schema.py +0 -0
  159. {sourcecode-1.28.0 → sourcecode-1.29.0}/tests/test_hybrid_inference.py +0 -0
  160. {sourcecode-1.28.0 → sourcecode-1.29.0}/tests/test_integration.py +0 -0
  161. {sourcecode-1.28.0 → sourcecode-1.29.0}/tests/test_integration_dependencies.py +0 -0
  162. {sourcecode-1.28.0 → sourcecode-1.29.0}/tests/test_integration_detection.py +0 -0
  163. {sourcecode-1.28.0 → sourcecode-1.29.0}/tests/test_integration_docs.py +0 -0
  164. {sourcecode-1.28.0 → sourcecode-1.29.0}/tests/test_integration_graph_modules.py +0 -0
  165. {sourcecode-1.28.0 → sourcecode-1.29.0}/tests/test_integration_lqn.py +0 -0
  166. {sourcecode-1.28.0 → sourcecode-1.29.0}/tests/test_integration_metrics.py +0 -0
  167. {sourcecode-1.28.0 → sourcecode-1.29.0}/tests/test_integration_multistack.py +0 -0
  168. {sourcecode-1.28.0 → sourcecode-1.29.0}/tests/test_integration_semantics.py +0 -0
  169. {sourcecode-1.28.0 → sourcecode-1.29.0}/tests/test_integration_universal.py +0 -0
  170. {sourcecode-1.28.0 → sourcecode-1.29.0}/tests/test_java_spring_integration.py +0 -0
  171. {sourcecode-1.28.0 → sourcecode-1.29.0}/tests/test_metrics_analyzer.py +0 -0
  172. {sourcecode-1.28.0 → sourcecode-1.29.0}/tests/test_packaging.py +0 -0
  173. {sourcecode-1.28.0 → sourcecode-1.29.0}/tests/test_phase1_improvements.py +0 -0
  174. {sourcecode-1.28.0 → sourcecode-1.29.0}/tests/test_pipeline_integrity.py +0 -0
  175. {sourcecode-1.28.0 → sourcecode-1.29.0}/tests/test_real_projects.py +0 -0
  176. {sourcecode-1.28.0 → sourcecode-1.29.0}/tests/test_redactor.py +0 -0
  177. {sourcecode-1.28.0 → sourcecode-1.29.0}/tests/test_scanner.py +0 -0
  178. {sourcecode-1.28.0 → sourcecode-1.29.0}/tests/test_schema.py +0 -0
  179. {sourcecode-1.28.0 → sourcecode-1.29.0}/tests/test_schema_normalization.py +0 -0
  180. {sourcecode-1.28.0 → sourcecode-1.29.0}/tests/test_semantic_analyzer_node.py +0 -0
  181. {sourcecode-1.28.0 → sourcecode-1.29.0}/tests/test_semantic_analyzer_python.py +0 -0
  182. {sourcecode-1.28.0 → sourcecode-1.29.0}/tests/test_semantic_import_resolution.py +0 -0
  183. {sourcecode-1.28.0 → sourcecode-1.29.0}/tests/test_semantic_schema.py +0 -0
  184. {sourcecode-1.28.0 → sourcecode-1.29.0}/tests/test_signal_hierarchy.py +0 -0
  185. {sourcecode-1.28.0 → sourcecode-1.29.0}/tests/test_summarizer.py +0 -0
  186. {sourcecode-1.28.0 → sourcecode-1.29.0}/tests/test_surface_honesty.py +0 -0
  187. {sourcecode-1.28.0 → sourcecode-1.29.0}/tests/test_task_differentiation.py +0 -0
  188. {sourcecode-1.28.0 → sourcecode-1.29.0}/tests/test_telemetry.py +0 -0
  189. {sourcecode-1.28.0 → sourcecode-1.29.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.28.0
3
+ Version: 1.29.0
4
4
  Summary: Deterministic codebase context for AI coding agents
5
5
  License: Apache License
6
6
  Version 2.0, January 2004
@@ -221,7 +221,7 @@ Description-Content-Type: text/markdown
221
221
 
222
222
  **Compressed AI-ready context for Java/Spring enterprise codebases.**
223
223
 
224
- ![Version](https://img.shields.io/badge/version-1.28.0-blue)
224
+ ![Version](https://img.shields.io/badge/version-1.29.0-blue)
225
225
  ![Python](https://img.shields.io/badge/python-3.10%2B-green)
226
226
 
227
227
  ---
@@ -255,7 +255,7 @@ pipx install sourcecode
255
255
 
256
256
  ```bash
257
257
  sourcecode version
258
- # sourcecode 1.28.0
258
+ # sourcecode 1.29.0
259
259
  ```
260
260
 
261
261
  ---
@@ -2,7 +2,7 @@
2
2
 
3
3
  **Compressed AI-ready context for Java/Spring enterprise codebases.**
4
4
 
5
- ![Version](https://img.shields.io/badge/version-1.28.0-blue)
5
+ ![Version](https://img.shields.io/badge/version-1.29.0-blue)
6
6
  ![Python](https://img.shields.io/badge/python-3.10%2B-green)
7
7
 
8
8
  ---
@@ -36,7 +36,7 @@ pipx install sourcecode
36
36
 
37
37
  ```bash
38
38
  sourcecode version
39
- # sourcecode 1.28.0
39
+ # sourcecode 1.29.0
40
40
  ```
41
41
 
42
42
  ---
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "sourcecode"
7
- version = "1.28.0"
7
+ version = "1.29.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.28.0"
3
+ __version__ = "1.29.0"
@@ -1633,7 +1633,7 @@ def prepare_context_cmd(
1633
1633
  refactor Structural issues, improvement opportunities
1634
1634
  generate-tests Untested source files, test gap analysis
1635
1635
  onboard Full project context for new agents/developers
1636
- review-pr Changed files + architectural impact
1636
+ review-pr PR diff: changed files, security/transactional impact, test gaps (requires git diff or --since)
1637
1637
  delta Incremental context: git-changed files only
1638
1638
 
1639
1639
  \b
@@ -1642,6 +1642,8 @@ def prepare_context_cmd(
1642
1642
  sourcecode prepare-context explain /path/to/repo
1643
1643
  sourcecode prepare-context fix-bug
1644
1644
  sourcecode prepare-context delta --since main
1645
+ sourcecode prepare-context review-pr --since origin/main
1646
+ sourcecode prepare-context review-pr . --since main --output review.json
1645
1647
  sourcecode prepare-context onboard --llm-prompt
1646
1648
  sourcecode prepare-context --task-help
1647
1649
  """
@@ -1734,6 +1736,14 @@ def prepare_context_cmd(
1734
1736
  "test_gaps": False, "code_notes_summary": False,
1735
1737
  "changed_files": True, "affected_entry_points": True,
1736
1738
  },
1739
+ "review-pr": {
1740
+ "project_summary": False, "architecture_summary": False,
1741
+ "relevant_files": True, "key_dependencies": False,
1742
+ "gaps": True, "confidence": False,
1743
+ "suspected_areas": False, "improvement_opportunities": False,
1744
+ "test_gaps": False, "code_notes_summary": False,
1745
+ "changed_files": True, "affected_entry_points": True,
1746
+ },
1737
1747
  }
1738
1748
  _content_filter = _TASK_CONTENT_MAP.get(task, {})
1739
1749
 
@@ -1813,6 +1823,53 @@ def prepare_context_cmd(
1813
1823
  out["dependency_graph_summary"] = output.dependency_graph_summary
1814
1824
  if output.impact_score_per_file:
1815
1825
  out["impact_score_per_file"] = output.impact_score_per_file
1826
+ # review-pr specific fields
1827
+ if task == "review-pr":
1828
+ if output.error_code:
1829
+ _err_out: dict[str, Any] = {
1830
+ "task": output.task,
1831
+ "ci_decision": output.ci_decision or "error",
1832
+ "error": output.error_code,
1833
+ "message": output.error_message,
1834
+ }
1835
+ if output.since:
1836
+ _err_out["since"] = output.since
1837
+ if output.error_hints:
1838
+ _err_out["hint"] = output.error_hints
1839
+ _err_json = json.dumps(_err_out, indent=2, ensure_ascii=False)
1840
+ if output_path is not None:
1841
+ output_path.write_text(_err_json, encoding="utf-8")
1842
+ else:
1843
+ import sys as _sys
1844
+ _sys.stdout.buffer.write(_err_json.encode("utf-8"))
1845
+ _sys.stdout.buffer.write(b"\n")
1846
+ _sys.stdout.buffer.flush()
1847
+ raise typer.Exit(code=1)
1848
+ out["review_type"] = "pull_request"
1849
+ if output.ci_decision:
1850
+ out["ci_decision"] = output.ci_decision
1851
+ if output.base_ref:
1852
+ out["base_ref"] = output.base_ref
1853
+ if output.since:
1854
+ out["since"] = output.since
1855
+ if output.affected_modules:
1856
+ out["affected_modules"] = output.affected_modules
1857
+ if output.security_impact:
1858
+ out["security_impact"] = output.security_impact
1859
+ if output.transactional_impact:
1860
+ out["transactional_impact"] = output.transactional_impact
1861
+ if output.configuration_impact:
1862
+ out["configuration_impact"] = output.configuration_impact
1863
+ if output.test_coverage_risk:
1864
+ out["test_coverage_risk"] = output.test_coverage_risk
1865
+ if output.review_hotspots:
1866
+ out["review_hotspots"] = output.review_hotspots
1867
+ if output.suggested_review_order:
1868
+ out["suggested_review_order"] = output.suggested_review_order
1869
+ if output.impact_summary:
1870
+ out["impact_summary"] = output.impact_summary
1871
+ if output.why_these_files:
1872
+ out["reasoning"] = output.why_these_files
1816
1873
  if output.limitations:
1817
1874
  out["limitations"] = output.limitations
1818
1875
  if output.symptom:
@@ -338,11 +338,19 @@ class TaskOutput:
338
338
  error_message: Optional[str] = None
339
339
  error_hints: list[str] = field(default_factory=list)
340
340
  # CI decision state machine — machine-decidable signal
341
- ci_decision: Optional[str] = None # "no_changes" | "analysis_success" | "git_ref_error"
341
+ ci_decision: Optional[str] = None # "no_changes" | "analysis_success" | "git_ref_error" | "no_git_repo"
342
342
  # git baseline resolution metadata
343
343
  resolved_since_ref: Optional[str] = None # actual ref/hash used for the diff
344
344
  resolution_path: Optional[str] = None # "exact_local_ref"|"remote_tracking_ref"|"symbolic_ref"|"head_minus_1_fallback"|"uncommitted_changes"|"unresolvable"
345
345
  diff_validation_status: Optional[str] = None # "valid_non_empty"|"valid_empty"|"invalid_ref"
346
+ # review-pr specific impact sections
347
+ base_ref: Optional[str] = None
348
+ security_impact: dict = field(default_factory=dict)
349
+ transactional_impact: dict = field(default_factory=dict)
350
+ configuration_impact: dict = field(default_factory=dict)
351
+ test_coverage_risk: dict = field(default_factory=dict)
352
+ review_hotspots: list[str] = field(default_factory=list)
353
+ suggested_review_order: list[str] = field(default_factory=list)
346
354
 
347
355
 
348
356
  # ─────────────────────────────────────────────────────────────────────────────
@@ -659,6 +667,58 @@ class TaskContextBuilder:
659
667
  elif _delta_raw:
660
668
  _delta_files = set(_delta_raw)
661
669
 
670
+ # ── 5d. review-pr: git-first gate ──────────────────────────────────────
671
+ if task_name == "review-pr":
672
+ if not self._is_git_repo():
673
+ return TaskOutput(
674
+ task="review-pr", goal=spec.goal,
675
+ project_summary=None, architecture_summary=None,
676
+ relevant_files=[], suspected_areas=[],
677
+ improvement_opportunities=[], test_gaps=[],
678
+ key_dependencies=[], code_notes_summary=None,
679
+ limitations=[], confidence="low",
680
+ error_code="no_git_repo",
681
+ error_message="review-pr requires a git repository.",
682
+ ci_decision="no_git_repo",
683
+ )
684
+ _pr_raw = self._get_git_changed_files(since=since)
685
+ if _pr_raw is None:
686
+ _avail_pr, _sug_pr = self._get_available_refs(since or "")
687
+ _pr_hints: list[str] = []
688
+ if _sug_pr:
689
+ _pr_hints.append(f"Did you mean '{_sug_pr}'?")
690
+ if _avail_pr:
691
+ _pr_hints.append(f"Available refs: {', '.join(_avail_pr[:8])}")
692
+ return TaskOutput(
693
+ task="review-pr", goal=spec.goal,
694
+ project_summary=None, architecture_summary=None,
695
+ relevant_files=[], suspected_areas=[],
696
+ improvement_opportunities=[], test_gaps=[],
697
+ key_dependencies=[], code_notes_summary=None,
698
+ limitations=[], confidence="low",
699
+ since=since,
700
+ error_code="git_ref_not_found",
701
+ error_message=f"Base ref '{since}' not found in this repository.",
702
+ error_hints=_pr_hints,
703
+ gaps=[f"Cannot compute PR diff: git ref '{since}' not found."] + _pr_hints,
704
+ ci_decision="git_ref_error",
705
+ )
706
+ if not _pr_raw:
707
+ _no_diff_hint = "review-pr requires changed files or --since <ref>."
708
+ return TaskOutput(
709
+ task="review-pr", goal=spec.goal,
710
+ project_summary=None, architecture_summary=None,
711
+ relevant_files=[], suspected_areas=[],
712
+ improvement_opportunities=[], test_gaps=[],
713
+ key_dependencies=[], code_notes_summary=None,
714
+ limitations=[], confidence="low",
715
+ error_code="no_diff",
716
+ error_message=f"No PR diff detected. {_no_diff_hint}",
717
+ gaps=[f"No PR diff detected. {_no_diff_hint}"],
718
+ ci_decision="no_changes",
719
+ )
720
+ _delta_files = set(_pr_raw)
721
+
662
722
  # ── 5c. review-pr suspected_areas (needs git uncommitted_files) ──────
663
723
  if task_name == "review-pr" and spec.enable_code_notes:
664
724
  pr_areas: dict[str, int] = {}
@@ -698,7 +758,7 @@ class TaskContextBuilder:
698
758
  _delta_dep_graph_summary: dict = {}
699
759
  _delta_impact_score_per_file: dict = {}
700
760
 
701
- if task_name == "delta":
761
+ if task_name in ("delta", "review-pr"):
702
762
  _delta_changed_list: list[str] = sorted(_delta_files) if _delta_files else []
703
763
  (
704
764
  relevant_files,
@@ -727,7 +787,88 @@ class TaskContextBuilder:
727
787
  delta_files=None,
728
788
  )
729
789
 
730
- # ── 6b. Symptom keyword boost + related notes (fix-bug + --symptom) ──
790
+ # ── 6b. review-pr: derive PR-specific impact sections from delta analysis ──
791
+ _pr_security_impact: dict = {}
792
+ _pr_transactional_impact: dict = {}
793
+ _pr_configuration_impact: dict = {}
794
+ _pr_test_coverage_risk: dict = {}
795
+ _pr_review_hotspots: list[str] = []
796
+ _pr_suggested_review_order: list[str] = []
797
+ _pr_base_ref: Optional[str] = None
798
+
799
+ if task_name == "review-pr":
800
+ _pr_base_ref = since or "HEAD"
801
+ _sys_risk_areas = _delta_system_impact.get("risk_areas", [])
802
+
803
+ _security_files = [
804
+ f for ra in _sys_risk_areas if ra["area"] == "security"
805
+ for f in ra["affected_files"]
806
+ ]
807
+ _transaction_files = [
808
+ f for ra in _sys_risk_areas if ra["area"] in ("transactions", "business_logic")
809
+ for f in ra["affected_files"]
810
+ ]
811
+ _config_files = [
812
+ f for ra in _sys_risk_areas if ra["area"] in ("api", "config")
813
+ for f in ra["affected_files"]
814
+ if any(kw in f.lower() for kw in ("config", "properties", "yml", "yaml", "xml", "spring"))
815
+ ]
816
+
817
+ if _security_files:
818
+ _pr_security_impact = {
819
+ "affected_resources": _security_files,
820
+ "risk_level": "high",
821
+ }
822
+ if _transaction_files:
823
+ _pr_transactional_impact = {
824
+ "affected_transactions": _transaction_files,
825
+ "risk": "possible transaction boundary change",
826
+ }
827
+ if _config_files:
828
+ _pr_configuration_impact = {"changed_configs": _config_files}
829
+
830
+ # Test coverage risk scoped to changed source files only
831
+ _changed_src = [
832
+ f for f in sorted(_delta_files or set())
833
+ if not self._is_test(f) and self._is_source(f)
834
+ ]
835
+ _test_stems = {Path(p).stem for p in test_set}
836
+ _untested_changed = [f for f in _changed_src if Path(f).stem not in _test_stems]
837
+ _test_risk_level = (
838
+ "high" if len(_untested_changed) > 3
839
+ else "medium" if _untested_changed
840
+ else "low"
841
+ )
842
+ _pr_test_coverage_risk = {
843
+ "changed_files_without_tests": _untested_changed[:10],
844
+ "risk_level": _test_risk_level,
845
+ }
846
+
847
+ # Review hotspots: top changed files ranked by impact score
848
+ _pr_review_hotspots = sorted(
849
+ _delta_files or set(),
850
+ key=lambda f: _delta_impact_score_per_file.get(f, 0.0),
851
+ reverse=True,
852
+ )[:8]
853
+
854
+ # Suggested review order: security first, then api → service → persistence → config
855
+ _ORDER_TYPES = ["security", "controller", "service", "repository", "mapper",
856
+ "spring_config", "config", "domain_model", "dto"]
857
+ _seen_order: set[str] = set()
858
+ for _otype in _ORDER_TYPES:
859
+ for _ra in _delta_risk_areas:
860
+ for _f in _ra.get("affected_files", []):
861
+ if _f not in _seen_order:
862
+ _cls = self._classify_changed_file(_f)
863
+ if _cls["artifact_type"] == _otype:
864
+ _pr_suggested_review_order.append(_f)
865
+ _seen_order.add(_f)
866
+ for _f in _pr_review_hotspots:
867
+ if _f not in _seen_order:
868
+ _pr_suggested_review_order.append(_f)
869
+ _seen_order.add(_f)
870
+
871
+ # ── 6c. Symptom keyword boost + related notes (fix-bug + --symptom) ──
731
872
  symptom_keywords: list[str] = []
732
873
  related_notes: list[dict] = []
733
874
  symptom_note: Optional[str] = None
@@ -883,7 +1024,7 @@ class TaskContextBuilder:
883
1024
 
884
1025
  conf_summary, analysis_gaps = ConfidenceAnalyzer().analyze(sm_for_conf)
885
1026
  confidence = conf_summary.overall
886
- if task_name == "delta":
1027
+ if task_name in ("delta", "review-pr"):
887
1028
  # Use delta-specific gaps; ConfidenceAnalyzer gaps are about full-repo
888
1029
  # detection quality and are not meaningful for an incremental diff.
889
1030
  gaps = _delta_analysis_gaps
@@ -895,16 +1036,16 @@ class TaskContextBuilder:
895
1036
  gaps.append(_mybatis_warning["reason"])
896
1037
 
897
1038
  # ── 9. why_these_files ────────────────────────────────────────────────
898
- if task_name == "delta":
1039
+ if task_name in ("delta", "review-pr"):
899
1040
  why_these_files = _delta_why
900
1041
  else:
901
1042
  why_these_files = {rf.path: rf.reason for rf in relevant_files}
902
1043
 
903
- # ── 10. Delta: git changed files + entry points ───────────────────────
1044
+ # ── 10. Delta / review-pr: git changed files + entry points ──────────
904
1045
  changed_files: list[str] = []
905
1046
  affected_entry_points: list[str] = []
906
- if task_name == "delta":
907
- changed_files = sorted(_delta_files) if _delta_files else self._get_git_changed_files(since=since)
1047
+ if task_name in ("delta", "review-pr"):
1048
+ changed_files = sorted(_delta_files) if _delta_files else (self._get_git_changed_files(since=since) or [])
908
1049
  _ep_set = {ep.path for ep in entry_points}
909
1050
  # include framework-detected entry points AND files classified as
910
1051
  # entrypoint/controller/security by artifact taxonomy
@@ -939,16 +1080,24 @@ class TaskContextBuilder:
939
1080
  impact_summary=_delta_impact_summary,
940
1081
  affected_modules=_delta_affected_modules,
941
1082
  risk_areas=_delta_risk_areas,
942
- since=since if task_name == "delta" else None,
1083
+ since=since if task_name in ("delta", "review-pr") else None,
943
1084
  system_impact=_delta_system_impact,
944
1085
  change_type=_delta_change_type,
945
1086
  dependency_graph_summary=_delta_dep_graph_summary,
946
1087
  impact_score_per_file=_delta_impact_score_per_file,
947
1088
  ci_decision=(
948
1089
  "no_changes" if task_name == "delta" and not changed_files
949
- else "analysis_success" if task_name == "delta"
1090
+ else "analysis_success" if task_name in ("delta", "review-pr")
950
1091
  else None
951
1092
  ),
1093
+ # review-pr specific
1094
+ base_ref=_pr_base_ref,
1095
+ security_impact=_pr_security_impact,
1096
+ transactional_impact=_pr_transactional_impact,
1097
+ configuration_impact=_pr_configuration_impact,
1098
+ test_coverage_risk=_pr_test_coverage_risk,
1099
+ review_hotspots=_pr_review_hotspots,
1100
+ suggested_review_order=_pr_suggested_review_order,
952
1101
  )
953
1102
 
954
1103
  def render_prompt(self, output: TaskOutput) -> str:
@@ -1240,6 +1389,19 @@ class TaskContextBuilder:
1240
1389
  def _is_source(self, path: str) -> bool:
1241
1390
  return Path(path).suffix.lower() in _SOURCE_EXTENSIONS
1242
1391
 
1392
+ def _is_git_repo(self) -> bool:
1393
+ import subprocess
1394
+ try:
1395
+ r = subprocess.run(
1396
+ ["git", "rev-parse", "--git-dir"],
1397
+ cwd=str(self.root),
1398
+ capture_output=True, text=True,
1399
+ encoding="utf-8", errors="replace", timeout=5,
1400
+ )
1401
+ return r.returncode == 0
1402
+ except (subprocess.TimeoutExpired, FileNotFoundError):
1403
+ return False
1404
+
1243
1405
  # ── Delta impact analysis ─────────────────────────────────────────────────
1244
1406
 
1245
1407
  @staticmethod
@@ -530,27 +530,53 @@ class TestArchitecturePatternHeuristic:
530
530
  # ===========================================================================
531
531
 
532
532
  class TestReviewPrSuspectedAreas:
533
+ """review-pr now requires a git diff — generic fallback removed."""
533
534
 
534
- def test_review_pr_runs_without_error(self):
535
+ def test_review_pr_requires_git_diff(self):
536
+ # FIXTURE has no uncommitted changes (or no git repo) — must exit 1 with structured error.
537
+ # When running inside the atlas-cli git tree with no staged changes, error is "no_diff".
538
+ # When running outside any git repo, error is "no_git_repo". Both are valid.
535
539
  result = _invoke("prepare-context", "review-pr", str(FIXTURE))
536
- assert result.exit_code == 0, result.output
540
+ assert result.exit_code == 1, result.output
541
+ data = _json(result)
542
+ _git_errors = {"no_git_repo", "no_diff", "git_ref_not_found"}
543
+ assert data.get("error") in _git_errors, f"Expected git error, got: {data}"
544
+ assert "ci_decision" in data
537
545
 
538
- def test_review_pr_json_has_suspected_areas_when_files_exist(self):
546
+ def test_review_pr_error_json_is_machine_readable(self):
539
547
  result = _invoke("prepare-context", "review-pr", str(FIXTURE))
540
- assert result.exit_code == 0, result.output
548
+ assert result.exit_code == 1
541
549
  data = _json(result)
542
- # suspected_areas is populated from controller/service/repository adjacency
543
- # Even with no uncommitted files, boosted stems drive the list
544
- assert "suspected_areas" in data, \
545
- f"review-pr must include suspected_areas. Keys: {list(data.keys())}"
546
-
547
- def test_review_pr_suspected_areas_contain_controllers(self):
550
+ assert "error" in data
551
+ assert "message" in data
552
+ assert "ci_decision" in data
553
+
554
+ def test_review_pr_no_diff_error_when_git_but_no_changes(self, monkeypatch):
555
+ # Simulate: is_git_repo=True but no changed files
556
+ from sourcecode import prepare_context as _pc
557
+ monkeypatch.setattr(_pc.TaskContextBuilder, "_is_git_repo", lambda self: True)
558
+ monkeypatch.setattr(_pc.TaskContextBuilder, "_get_git_changed_files", lambda self, since=None: [])
559
+ result = _invoke("prepare-context", "review-pr", str(FIXTURE))
560
+ assert result.exit_code == 1
561
+ data = _json(result)
562
+ assert data.get("error") == "no_diff"
563
+ assert data.get("ci_decision") == "no_changes"
564
+
565
+ def test_review_pr_with_mocked_diff_returns_pr_fields(self, monkeypatch):
566
+ # Simulate: valid git repo with one changed controller file
567
+ from sourcecode import prepare_context as _pc
568
+ monkeypatch.setattr(_pc.TaskContextBuilder, "_is_git_repo", lambda self: True)
569
+ monkeypatch.setattr(
570
+ _pc.TaskContextBuilder, "_get_git_changed_files",
571
+ lambda self, since=None: ["src/main/java/com/example/UserController.java"],
572
+ )
548
573
  result = _invoke("prepare-context", "review-pr", str(FIXTURE))
549
574
  assert result.exit_code == 0, result.output
550
575
  data = _json(result)
551
- areas = data.get("suspected_areas", [])
552
- has_controller = any("Controller" in a or "Service" in a or "Mapper" in a for a in areas)
553
- assert has_controller, f"Expected controller/service/mapper in suspected_areas: {areas}"
576
+ assert data.get("review_type") == "pull_request"
577
+ assert "changed_files" in data
578
+ assert "test_coverage_risk" in data
579
+ assert data.get("ci_decision") == "analysis_success"
554
580
 
555
581
  def test_fix_bug_still_uses_annotation_density(self):
556
582
  result = _invoke("prepare-context", "fix-bug", str(FIXTURE))
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes