sourcecode 1.30.11__tar.gz → 1.30.12__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 (193) hide show
  1. sourcecode-1.30.12/.continue-here.md +166 -0
  2. {sourcecode-1.30.11 → sourcecode-1.30.12}/PKG-INFO +3 -3
  3. {sourcecode-1.30.11 → sourcecode-1.30.12}/README.md +2 -2
  4. {sourcecode-1.30.11 → sourcecode-1.30.12}/pyproject.toml +1 -1
  5. {sourcecode-1.30.11 → sourcecode-1.30.12}/src/sourcecode/__init__.py +1 -1
  6. {sourcecode-1.30.11 → sourcecode-1.30.12}/src/sourcecode/cli.py +83 -0
  7. {sourcecode-1.30.11 → sourcecode-1.30.12}/src/sourcecode/prepare_context.py +115 -65
  8. sourcecode-1.30.12/src/sourcecode/repository_ir.py +803 -0
  9. sourcecode-1.30.12/tests/test_repository_ir.py +451 -0
  10. sourcecode-1.30.11/.continue-here.md +0 -173
  11. {sourcecode-1.30.11 → sourcecode-1.30.12}/.agents/skills/source-command-gsd-join-discord/SKILL.md +0 -0
  12. {sourcecode-1.30.11 → sourcecode-1.30.12}/.agents/skills/source-command-gsd-review-backlog/SKILL.md +0 -0
  13. {sourcecode-1.30.11 → sourcecode-1.30.12}/.agents/skills/source-command-gsd-workstreams/SKILL.md +0 -0
  14. {sourcecode-1.30.11 → sourcecode-1.30.12}/.github/workflows/build-windows.yml +0 -0
  15. {sourcecode-1.30.11 → sourcecode-1.30.12}/.gitignore +0 -0
  16. {sourcecode-1.30.11 → sourcecode-1.30.12}/.ruff.toml +0 -0
  17. {sourcecode-1.30.11 → sourcecode-1.30.12}/CONTRIBUTING.md +0 -0
  18. {sourcecode-1.30.11 → sourcecode-1.30.12}/LICENSE +0 -0
  19. {sourcecode-1.30.11 → sourcecode-1.30.12}/SECURITY.md +0 -0
  20. {sourcecode-1.30.11 → sourcecode-1.30.12}/docs/privacy.md +0 -0
  21. {sourcecode-1.30.11 → sourcecode-1.30.12}/docs/schema.md +0 -0
  22. {sourcecode-1.30.11 → sourcecode-1.30.12}/raw +0 -0
  23. {sourcecode-1.30.11 → sourcecode-1.30.12}/run_cli.py +0 -0
  24. {sourcecode-1.30.11 → sourcecode-1.30.12}/src/sourcecode/adaptive_scanner.py +0 -0
  25. {sourcecode-1.30.11 → sourcecode-1.30.12}/src/sourcecode/architecture_analyzer.py +0 -0
  26. {sourcecode-1.30.11 → sourcecode-1.30.12}/src/sourcecode/architecture_summary.py +0 -0
  27. {sourcecode-1.30.11 → sourcecode-1.30.12}/src/sourcecode/ast_extractor.py +0 -0
  28. {sourcecode-1.30.11 → sourcecode-1.30.12}/src/sourcecode/classifier.py +0 -0
  29. {sourcecode-1.30.11 → sourcecode-1.30.12}/src/sourcecode/code_notes_analyzer.py +0 -0
  30. {sourcecode-1.30.11 → sourcecode-1.30.12}/src/sourcecode/confidence_analyzer.py +0 -0
  31. {sourcecode-1.30.11 → sourcecode-1.30.12}/src/sourcecode/context_scorer.py +0 -0
  32. {sourcecode-1.30.11 → sourcecode-1.30.12}/src/sourcecode/context_summarizer.py +0 -0
  33. {sourcecode-1.30.11 → sourcecode-1.30.12}/src/sourcecode/contract_model.py +0 -0
  34. {sourcecode-1.30.11 → sourcecode-1.30.12}/src/sourcecode/contract_pipeline.py +0 -0
  35. {sourcecode-1.30.11 → sourcecode-1.30.12}/src/sourcecode/coverage_parser.py +0 -0
  36. {sourcecode-1.30.11 → sourcecode-1.30.12}/src/sourcecode/dependency_analyzer.py +0 -0
  37. {sourcecode-1.30.11 → sourcecode-1.30.12}/src/sourcecode/detectors/__init__.py +0 -0
  38. {sourcecode-1.30.11 → sourcecode-1.30.12}/src/sourcecode/detectors/base.py +0 -0
  39. {sourcecode-1.30.11 → sourcecode-1.30.12}/src/sourcecode/detectors/csproj_parser.py +0 -0
  40. {sourcecode-1.30.11 → sourcecode-1.30.12}/src/sourcecode/detectors/dart.py +0 -0
  41. {sourcecode-1.30.11 → sourcecode-1.30.12}/src/sourcecode/detectors/dotnet.py +0 -0
  42. {sourcecode-1.30.11 → sourcecode-1.30.12}/src/sourcecode/detectors/elixir.py +0 -0
  43. {sourcecode-1.30.11 → sourcecode-1.30.12}/src/sourcecode/detectors/go.py +0 -0
  44. {sourcecode-1.30.11 → sourcecode-1.30.12}/src/sourcecode/detectors/heuristic.py +0 -0
  45. {sourcecode-1.30.11 → sourcecode-1.30.12}/src/sourcecode/detectors/hybrid.py +0 -0
  46. {sourcecode-1.30.11 → sourcecode-1.30.12}/src/sourcecode/detectors/java.py +0 -0
  47. {sourcecode-1.30.11 → sourcecode-1.30.12}/src/sourcecode/detectors/jvm_ext.py +0 -0
  48. {sourcecode-1.30.11 → sourcecode-1.30.12}/src/sourcecode/detectors/nodejs.py +0 -0
  49. {sourcecode-1.30.11 → sourcecode-1.30.12}/src/sourcecode/detectors/parsers.py +0 -0
  50. {sourcecode-1.30.11 → sourcecode-1.30.12}/src/sourcecode/detectors/php.py +0 -0
  51. {sourcecode-1.30.11 → sourcecode-1.30.12}/src/sourcecode/detectors/project.py +0 -0
  52. {sourcecode-1.30.11 → sourcecode-1.30.12}/src/sourcecode/detectors/python.py +0 -0
  53. {sourcecode-1.30.11 → sourcecode-1.30.12}/src/sourcecode/detectors/ruby.py +0 -0
  54. {sourcecode-1.30.11 → sourcecode-1.30.12}/src/sourcecode/detectors/rust.py +0 -0
  55. {sourcecode-1.30.11 → sourcecode-1.30.12}/src/sourcecode/detectors/systems.py +0 -0
  56. {sourcecode-1.30.11 → sourcecode-1.30.12}/src/sourcecode/detectors/terraform.py +0 -0
  57. {sourcecode-1.30.11 → sourcecode-1.30.12}/src/sourcecode/detectors/tooling.py +0 -0
  58. {sourcecode-1.30.11 → sourcecode-1.30.12}/src/sourcecode/doc_analyzer.py +0 -0
  59. {sourcecode-1.30.11 → sourcecode-1.30.12}/src/sourcecode/entrypoint_classifier.py +0 -0
  60. {sourcecode-1.30.11 → sourcecode-1.30.12}/src/sourcecode/env_analyzer.py +0 -0
  61. {sourcecode-1.30.11 → sourcecode-1.30.12}/src/sourcecode/file_classifier.py +0 -0
  62. {sourcecode-1.30.11 → sourcecode-1.30.12}/src/sourcecode/flow_analyzer.py +0 -0
  63. {sourcecode-1.30.11 → sourcecode-1.30.12}/src/sourcecode/git_analyzer.py +0 -0
  64. {sourcecode-1.30.11 → sourcecode-1.30.12}/src/sourcecode/graph_analyzer.py +0 -0
  65. {sourcecode-1.30.11 → sourcecode-1.30.12}/src/sourcecode/metrics_analyzer.py +0 -0
  66. {sourcecode-1.30.11 → sourcecode-1.30.12}/src/sourcecode/progress.py +0 -0
  67. {sourcecode-1.30.11 → sourcecode-1.30.12}/src/sourcecode/ranking_engine.py +0 -0
  68. {sourcecode-1.30.11 → sourcecode-1.30.12}/src/sourcecode/redactor.py +0 -0
  69. {sourcecode-1.30.11 → sourcecode-1.30.12}/src/sourcecode/relevance_scorer.py +0 -0
  70. {sourcecode-1.30.11 → sourcecode-1.30.12}/src/sourcecode/repo_classifier.py +0 -0
  71. {sourcecode-1.30.11 → sourcecode-1.30.12}/src/sourcecode/runtime_classifier.py +0 -0
  72. {sourcecode-1.30.11 → sourcecode-1.30.12}/src/sourcecode/scanner.py +0 -0
  73. {sourcecode-1.30.11 → sourcecode-1.30.12}/src/sourcecode/schema.py +0 -0
  74. {sourcecode-1.30.11 → sourcecode-1.30.12}/src/sourcecode/semantic_analyzer.py +0 -0
  75. {sourcecode-1.30.11 → sourcecode-1.30.12}/src/sourcecode/serializer.py +0 -0
  76. {sourcecode-1.30.11 → sourcecode-1.30.12}/src/sourcecode/summarizer.py +0 -0
  77. {sourcecode-1.30.11 → sourcecode-1.30.12}/src/sourcecode/telemetry/__init__.py +0 -0
  78. {sourcecode-1.30.11 → sourcecode-1.30.12}/src/sourcecode/telemetry/config.py +0 -0
  79. {sourcecode-1.30.11 → sourcecode-1.30.12}/src/sourcecode/telemetry/consent.py +0 -0
  80. {sourcecode-1.30.11 → sourcecode-1.30.12}/src/sourcecode/telemetry/events.py +0 -0
  81. {sourcecode-1.30.11 → sourcecode-1.30.12}/src/sourcecode/telemetry/filters.py +0 -0
  82. {sourcecode-1.30.11 → sourcecode-1.30.12}/src/sourcecode/telemetry/transport.py +0 -0
  83. {sourcecode-1.30.11 → sourcecode-1.30.12}/src/sourcecode/tree_utils.py +0 -0
  84. {sourcecode-1.30.11 → sourcecode-1.30.12}/src/sourcecode/workspace.py +0 -0
  85. {sourcecode-1.30.11 → sourcecode-1.30.12}/tests/__init__.py +0 -0
  86. {sourcecode-1.30.11 → sourcecode-1.30.12}/tests/conftest.py +0 -0
  87. {sourcecode-1.30.11 → sourcecode-1.30.12}/tests/fixtures/coverage.xml +0 -0
  88. {sourcecode-1.30.11 → sourcecode-1.30.12}/tests/fixtures/fastapi_app/pyproject.toml +0 -0
  89. {sourcecode-1.30.11 → sourcecode-1.30.12}/tests/fixtures/fastapi_app/src/main.py +0 -0
  90. {sourcecode-1.30.11 → sourcecode-1.30.12}/tests/fixtures/go_service/cmd/api/main.go +0 -0
  91. {sourcecode-1.30.11 → sourcecode-1.30.12}/tests/fixtures/go_service/go.mod +0 -0
  92. {sourcecode-1.30.11 → sourcecode-1.30.12}/tests/fixtures/jacoco.xml +0 -0
  93. {sourcecode-1.30.11 → sourcecode-1.30.12}/tests/fixtures/latin1_sample.java +0 -0
  94. {sourcecode-1.30.11 → sourcecode-1.30.12}/tests/fixtures/latin1_sample_iso.java +0 -0
  95. {sourcecode-1.30.11 → sourcecode-1.30.12}/tests/fixtures/lcov.info +0 -0
  96. {sourcecode-1.30.11 → sourcecode-1.30.12}/tests/fixtures/nextjs_app/app/page.tsx +0 -0
  97. {sourcecode-1.30.11 → sourcecode-1.30.12}/tests/fixtures/nextjs_app/package.json +0 -0
  98. {sourcecode-1.30.11 → sourcecode-1.30.12}/tests/fixtures/nextjs_app/pnpm-lock.yaml +0 -0
  99. {sourcecode-1.30.11 → sourcecode-1.30.12}/tests/fixtures/pnpm_monorepo/apps/web/app/page.tsx +0 -0
  100. {sourcecode-1.30.11 → sourcecode-1.30.12}/tests/fixtures/pnpm_monorepo/apps/web/package.json +0 -0
  101. {sourcecode-1.30.11 → sourcecode-1.30.12}/tests/fixtures/pnpm_monorepo/packages/api/main.py +0 -0
  102. {sourcecode-1.30.11 → sourcecode-1.30.12}/tests/fixtures/pnpm_monorepo/packages/api/pyproject.toml +0 -0
  103. {sourcecode-1.30.11 → sourcecode-1.30.12}/tests/fixtures/pnpm_monorepo/pnpm-workspace.yaml +0 -0
  104. {sourcecode-1.30.11 → sourcecode-1.30.12}/tests/fixtures/spring_boot_minimal/pom.xml +0 -0
  105. {sourcecode-1.30.11 → sourcecode-1.30.12}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/ausente/application/service/FindAusenteService.java +0 -0
  106. {sourcecode-1.30.11 → sourcecode-1.30.12}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/ausente/domain/entities/Ausente.java +0 -0
  107. {sourcecode-1.30.11 → sourcecode-1.30.12}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/ausente/infrastructure/rest/AusenteRestController.java +0 -0
  108. {sourcecode-1.30.11 → sourcecode-1.30.12}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/autocoberturas/application/service/FindAutocoberturasService.java +0 -0
  109. {sourcecode-1.30.11 → sourcecode-1.30.12}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/autocoberturas/domain/entities/Autocoberturas.java +0 -0
  110. {sourcecode-1.30.11 → sourcecode-1.30.12}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/autocoberturas/infrastructure/rest/AutocoberturasRestController.java +0 -0
  111. {sourcecode-1.30.11 → sourcecode-1.30.12}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/calendarioTrabajador/application/service/FindCalendarioTrabajadorService.java +0 -0
  112. {sourcecode-1.30.11 → sourcecode-1.30.12}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/calendarioTrabajador/domain/entities/CalendarioTrabajador.java +0 -0
  113. {sourcecode-1.30.11 → sourcecode-1.30.12}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/calendarioTrabajador/infrastructure/rest/CalendarioTrabajadorRestController.java +0 -0
  114. {sourcecode-1.30.11 → sourcecode-1.30.12}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/departamento/application/service/FindDepartamentoService.java +0 -0
  115. {sourcecode-1.30.11 → sourcecode-1.30.12}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/departamento/domain/entities/Departamento.java +0 -0
  116. {sourcecode-1.30.11 → sourcecode-1.30.12}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/departamento/infrastructure/rest/DepartamentoRestController.java +0 -0
  117. {sourcecode-1.30.11 → sourcecode-1.30.12}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/empleado/application/service/FindEmpleadoService.java +0 -0
  118. {sourcecode-1.30.11 → sourcecode-1.30.12}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/empleado/domain/entities/Empleado.java +0 -0
  119. {sourcecode-1.30.11 → sourcecode-1.30.12}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/empleado/infrastructure/rest/EmpleadoRestController.java +0 -0
  120. {sourcecode-1.30.11 → sourcecode-1.30.12}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/demo/DemoApplication.java +0 -0
  121. {sourcecode-1.30.11 → sourcecode-1.30.12}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/demo/config/FilterConfig.java +0 -0
  122. {sourcecode-1.30.11 → sourcecode-1.30.12}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/demo/domain/Health.java +0 -0
  123. {sourcecode-1.30.11 → sourcecode-1.30.12}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/demo/mapper/HealthMapper.java +0 -0
  124. {sourcecode-1.30.11 → sourcecode-1.30.12}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/demo/repository/HealthRepository.java +0 -0
  125. {sourcecode-1.30.11 → sourcecode-1.30.12}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/demo/service/HealthService.java +0 -0
  126. {sourcecode-1.30.11 → sourcecode-1.30.12}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/demo/web/HealthRestController.java +0 -0
  127. {sourcecode-1.30.11 → sourcecode-1.30.12}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/demo/web/NominaRestController.java +0 -0
  128. {sourcecode-1.30.11 → sourcecode-1.30.12}/tests/fixtures/spring_boot_minimal/src/main/resources/application-dev.yml +0 -0
  129. {sourcecode-1.30.11 → sourcecode-1.30.12}/tests/fixtures/spring_boot_minimal/src/main/resources/application.yml +0 -0
  130. {sourcecode-1.30.11 → sourcecode-1.30.12}/tests/fixtures/spring_boot_minimal/src/main/resources/mapper/HealthMapper.xml +0 -0
  131. {sourcecode-1.30.11 → sourcecode-1.30.12}/tests/test_architecture_analyzer.py +0 -0
  132. {sourcecode-1.30.11 → sourcecode-1.30.12}/tests/test_architecture_summary.py +0 -0
  133. {sourcecode-1.30.11 → sourcecode-1.30.12}/tests/test_ast_extractor.py +0 -0
  134. {sourcecode-1.30.11 → sourcecode-1.30.12}/tests/test_block1_reliability.py +0 -0
  135. {sourcecode-1.30.11 → sourcecode-1.30.12}/tests/test_block2_coverage.py +0 -0
  136. {sourcecode-1.30.11 → sourcecode-1.30.12}/tests/test_block5_quality.py +0 -0
  137. {sourcecode-1.30.11 → sourcecode-1.30.12}/tests/test_bug_fixes_v16.py +0 -0
  138. {sourcecode-1.30.11 → sourcecode-1.30.12}/tests/test_classifier.py +0 -0
  139. {sourcecode-1.30.11 → sourcecode-1.30.12}/tests/test_cli.py +0 -0
  140. {sourcecode-1.30.11 → sourcecode-1.30.12}/tests/test_code_notes_analyzer.py +0 -0
  141. {sourcecode-1.30.11 → sourcecode-1.30.12}/tests/test_context_scorer.py +0 -0
  142. {sourcecode-1.30.11 → sourcecode-1.30.12}/tests/test_contract_pipeline.py +0 -0
  143. {sourcecode-1.30.11 → sourcecode-1.30.12}/tests/test_coverage_parser.py +0 -0
  144. {sourcecode-1.30.11 → sourcecode-1.30.12}/tests/test_cross_consistency.py +0 -0
  145. {sourcecode-1.30.11 → sourcecode-1.30.12}/tests/test_dependency_analyzer_node_python.py +0 -0
  146. {sourcecode-1.30.11 → sourcecode-1.30.12}/tests/test_dependency_analyzer_polyglot.py +0 -0
  147. {sourcecode-1.30.11 → sourcecode-1.30.12}/tests/test_dependency_schema.py +0 -0
  148. {sourcecode-1.30.11 → sourcecode-1.30.12}/tests/test_detector_dotnet.py +0 -0
  149. {sourcecode-1.30.11 → sourcecode-1.30.12}/tests/test_detector_go_rust_java.py +0 -0
  150. {sourcecode-1.30.11 → sourcecode-1.30.12}/tests/test_detector_nodejs.py +0 -0
  151. {sourcecode-1.30.11 → sourcecode-1.30.12}/tests/test_detector_php_ruby_dart.py +0 -0
  152. {sourcecode-1.30.11 → sourcecode-1.30.12}/tests/test_detector_python.py +0 -0
  153. {sourcecode-1.30.11 → sourcecode-1.30.12}/tests/test_detector_universal_managed.py +0 -0
  154. {sourcecode-1.30.11 → sourcecode-1.30.12}/tests/test_detector_universal_systems.py +0 -0
  155. {sourcecode-1.30.11 → sourcecode-1.30.12}/tests/test_detectors_base.py +0 -0
  156. {sourcecode-1.30.11 → sourcecode-1.30.12}/tests/test_doc_analyzer_jsdom.py +0 -0
  157. {sourcecode-1.30.11 → sourcecode-1.30.12}/tests/test_doc_analyzer_python.py +0 -0
  158. {sourcecode-1.30.11 → sourcecode-1.30.12}/tests/test_encoding_regression.py +0 -0
  159. {sourcecode-1.30.11 → sourcecode-1.30.12}/tests/test_graph_analyzer_polyglot.py +0 -0
  160. {sourcecode-1.30.11 → sourcecode-1.30.12}/tests/test_graph_analyzer_python_node.py +0 -0
  161. {sourcecode-1.30.11 → sourcecode-1.30.12}/tests/test_graph_schema.py +0 -0
  162. {sourcecode-1.30.11 → sourcecode-1.30.12}/tests/test_hybrid_inference.py +0 -0
  163. {sourcecode-1.30.11 → sourcecode-1.30.12}/tests/test_integration.py +0 -0
  164. {sourcecode-1.30.11 → sourcecode-1.30.12}/tests/test_integration_dependencies.py +0 -0
  165. {sourcecode-1.30.11 → sourcecode-1.30.12}/tests/test_integration_detection.py +0 -0
  166. {sourcecode-1.30.11 → sourcecode-1.30.12}/tests/test_integration_docs.py +0 -0
  167. {sourcecode-1.30.11 → sourcecode-1.30.12}/tests/test_integration_graph_modules.py +0 -0
  168. {sourcecode-1.30.11 → sourcecode-1.30.12}/tests/test_integration_lqn.py +0 -0
  169. {sourcecode-1.30.11 → sourcecode-1.30.12}/tests/test_integration_metrics.py +0 -0
  170. {sourcecode-1.30.11 → sourcecode-1.30.12}/tests/test_integration_multistack.py +0 -0
  171. {sourcecode-1.30.11 → sourcecode-1.30.12}/tests/test_integration_semantics.py +0 -0
  172. {sourcecode-1.30.11 → sourcecode-1.30.12}/tests/test_integration_universal.py +0 -0
  173. {sourcecode-1.30.11 → sourcecode-1.30.12}/tests/test_java_spring_integration.py +0 -0
  174. {sourcecode-1.30.11 → sourcecode-1.30.12}/tests/test_metrics_analyzer.py +0 -0
  175. {sourcecode-1.30.11 → sourcecode-1.30.12}/tests/test_packaging.py +0 -0
  176. {sourcecode-1.30.11 → sourcecode-1.30.12}/tests/test_phase1_improvements.py +0 -0
  177. {sourcecode-1.30.11 → sourcecode-1.30.12}/tests/test_pipeline_integrity.py +0 -0
  178. {sourcecode-1.30.11 → sourcecode-1.30.12}/tests/test_real_projects.py +0 -0
  179. {sourcecode-1.30.11 → sourcecode-1.30.12}/tests/test_redactor.py +0 -0
  180. {sourcecode-1.30.11 → sourcecode-1.30.12}/tests/test_scanner.py +0 -0
  181. {sourcecode-1.30.11 → sourcecode-1.30.12}/tests/test_schema.py +0 -0
  182. {sourcecode-1.30.11 → sourcecode-1.30.12}/tests/test_schema_normalization.py +0 -0
  183. {sourcecode-1.30.11 → sourcecode-1.30.12}/tests/test_semantic_analyzer_node.py +0 -0
  184. {sourcecode-1.30.11 → sourcecode-1.30.12}/tests/test_semantic_analyzer_python.py +0 -0
  185. {sourcecode-1.30.11 → sourcecode-1.30.12}/tests/test_semantic_import_resolution.py +0 -0
  186. {sourcecode-1.30.11 → sourcecode-1.30.12}/tests/test_semantic_schema.py +0 -0
  187. {sourcecode-1.30.11 → sourcecode-1.30.12}/tests/test_signal_hierarchy.py +0 -0
  188. {sourcecode-1.30.11 → sourcecode-1.30.12}/tests/test_summarizer.py +0 -0
  189. {sourcecode-1.30.11 → sourcecode-1.30.12}/tests/test_surface_honesty.py +0 -0
  190. {sourcecode-1.30.11 → sourcecode-1.30.12}/tests/test_task_differentiation.py +0 -0
  191. {sourcecode-1.30.11 → sourcecode-1.30.12}/tests/test_telemetry.py +0 -0
  192. {sourcecode-1.30.11 → sourcecode-1.30.12}/tests/test_v1_10_regressions.py +0 -0
  193. {sourcecode-1.30.11 → sourcecode-1.30.12}/tests/test_workspace_analyzer.py +0 -0
@@ -0,0 +1,166 @@
1
+ # Continue Here — atlas-cli sesión 11
2
+
3
+ **Paused:** 2026-05-16 (sesión 11)
4
+ **Repo:** `/Users/user/Downloads/atlas-cli`
5
+ **Branch:** master
6
+ **Último commit:** `dc157fa` — (fix) mejorando honestidad prepare-context pr
7
+ **Working tree:** `prepare_context.py` modificado (semantic engine fixes — NO committed)
8
+
9
+ ---
10
+
11
+ ## Trabajo de esta sesión
12
+
13
+ ### Bloque 1: Strict Diff Source Model
14
+
15
+ **Qué se hizo:**
16
+ - `DiffSourceType` enum añadido (`WORKTREE_UNSTAGED`, `WORKTREE_STAGED`, `GIT_SINCE_REF`, `GIT_RANGE`)
17
+ - `_get_pr_scope_files` reescrito → retorna 4-tuple `(all_files, scope_source, committed_files, uncommitted_files)`. Sin fallback a HEAD~1. Committed solo si `--since` explícito.
18
+ - `_get_git_changed_files` → sin default HEAD~1. Sin `--since`: WORKTREE_UNSTAGED (`git diff --name-only`). Con `--since`: GIT_SINCE_REF.
19
+ - `_FOLDER_TYPE_MAP` eliminado — path/folder no es evidencia.
20
+ - `TaskOutput` nuevos campos: `committed_changes`, `uncommitted_changes`, `analysis_scope`
21
+ - Cada entry `runtime_changes` incluye `diff_source` (GIT_RANGE vs WORKTREE_UNSTAGED)
22
+ - `changed-only` en cli.py: excluye untracked, solo staged+unstaged
23
+ - Tests `test_v1_10_regressions.py`: mocks actualizados a 4-tuple
24
+
25
+ **Committed en:** `dc157fa`
26
+
27
+ ---
28
+
29
+ ### Bloque 2: Evidence-Gated Semantic Engine (NO COMMITTED)
30
+
31
+ **Fichero con cambios:** `src/sourcecode/prepare_context.py` (unstaged)
32
+
33
+ **Qué se cambió:**
34
+
35
+ 1. **`_ARTIFACT_CHANGE_TYPES["source"]` → `[]`**
36
+ - Antes: `["behavioral_change"]`. Ahora: ninguno.
37
+ - `behavioral_change` solo se emite si `diff_severities` devuelve `api_change` o `security_change`
38
+
39
+ 2. **`_DIFF_SEVERITY_CHANGE_TYPES` nuevo dict**
40
+ - `api_change` → `["behavioral_change"]`
41
+ - `security_change` → `["behavioral_change", "security_change"]`
42
+ - `field_change` → `["structural_change"]`
43
+ - `unknown/trivial` → `[]`
44
+
45
+ 3. **`_ATYPE_IMPACT_AREA["source"]` → `"application_layer"` (antes: `"transaction_boundary"`)**
46
+ - `"service"` también → `"application_layer"` (sin evidencia transaccional)
47
+ - `"transaction_boundary"` ya no se emite para archivos no clasificados
48
+
49
+ 4. **`_role_in_system` default → `"unclassified"` (antes: `"core_service"`)**
50
+ - `"service"` anotado → `"service"` (no `"core_service"`)
51
+
52
+ 5. **`_structured_why` evidence-gated**
53
+ - Solo emite `role_in_system`, `impact_area`, `propagation_risk` si tipo no es `source`/`unclassified`
54
+ - Añade `classification_confidence`
55
+
56
+ 6. **`_score_to_confidence(score)` helper**
57
+ - `>= 0.60` → `"high"`, `>= 0.40` → `"medium"`, else → `"low"`
58
+
59
+ 7. **`impact_score_per_file` ahora es dict estructurado**
60
+ ```json
61
+ {
62
+ "score": 0.145,
63
+ "confidence": "low",
64
+ "score_breakdown": { "artifact_base": 0.125, ... },
65
+ "change_types": [],
66
+ "diff_severity": "trivial"
67
+ }
68
+ ```
69
+
70
+ 8. **`behavioral_changes`** — gateado en `diff_severities`, no en artifact type
71
+
72
+ 9. **`changed_subsystems`** — excluye `source`/`unclassified`; eliminado `"transaction_layer"` del mapa
73
+
74
+ 10. **`dependency_graph_summary.propagation_depth`** → `None` cuando no hay graph edges (no `0`)
75
+
76
+ 11. **`_runtime_impact`** — eliminado mensaje de "verify transaction scope" para service sin evidencia anotacional
77
+
78
+ **Resultado verificado:**
79
+ ```
80
+ changed_subsystems: []
81
+ behavioral_changes: []
82
+ role: unclassified
83
+ why: artifact_type: source | classification_confidence: low | change_effect: ...
84
+ # Sin: core_service, transaction_boundary, transaction_layer, propagation_risk
85
+ ```
86
+
87
+ **Tests:** 765 passed, 3 skipped (sin nuevos fallos)
88
+
89
+ ---
90
+
91
+ ## Estado de tests
92
+
93
+ ```
94
+ 765 passed, 3 skipped
95
+ ```
96
+
97
+ Pre-existing failures (no relacionados):
98
+ - `tests/test_block2_coverage.py` — DocRecord bug en `doc_analyzer.py`
99
+ - `tests/test_dependency_analyzer_node_python.py::test_python_requirements_without_lockfile_keeps_declared_versions`
100
+
101
+ ---
102
+
103
+ ## PENDIENTE (antes de próximo commit)
104
+
105
+ 1. **Commit semantic engine fixes** en `prepare_context.py`
106
+ ```bash
107
+ git add src/sourcecode/prepare_context.py
108
+ git commit -m "fix: evidence-gated semantic engine — remove unsupported behavioral/transaction claims"
109
+ ```
110
+
111
+ 2. **Smoke test en repo spring-boot real**
112
+ ```bash
113
+ cd ~/Documents/workspace/spring-boot-realworld-example-app
114
+ sourcecode prepare-context delta --since HEAD~1 2>/dev/null | python3 -c "
115
+ import json, sys
116
+ d = json.load(sys.stdin)
117
+ si = d.get('system_impact', {})
118
+ print('subsystems:', si.get('changed_subsystems'))
119
+ print('behavioral:', si.get('behavioral_changes'))
120
+ for f, v in d.get('impact_score_per_file', {}).items():
121
+ print(f'{f}: conf={v[\"confidence\"]} sev={v[\"diff_severity\"]}')
122
+ "
123
+ ```
124
+
125
+ 3. **Smoke test behavioral_impact** (pendiente de sesión anterior):
126
+ ```bash
127
+ cd ~/Documents/workspace/spring-boot-realworld-example-app
128
+ sourcecode prepare-context review-pr . 2>/dev/null | python3 -c "
129
+ import json, sys
130
+ d = json.load(sys.stdin)
131
+ for bi in d.get('behavioral_impact', []):
132
+ print('entry:', bi['entry_point'])
133
+ print('confidence:', bi['confidence'])
134
+ print('trace:', bi['trace'])
135
+ print()
136
+ "
137
+ ```
138
+
139
+ 4. **Tests unitarios para `_classify_diff_severity`** — aún sin cobertura
140
+
141
+ 5. **`User.java` clasificado como `"source"` no `"domain_model"`** — fix opcional
142
+
143
+ 6. **Evaluar si `execution_paths` sigue siendo útil** o si `behavioral_impact` lo reemplaza
144
+
145
+ ---
146
+
147
+ ## Para retomar
148
+
149
+ ```bash
150
+ cd /Users/user/Downloads/atlas-cli
151
+ git status # debe mostrar: prepare_context.py modified
152
+
153
+ python3 -m pytest tests/ \
154
+ --ignore=tests/test_block2_coverage.py \
155
+ --ignore=tests/test_dependency_analyzer_node_python.py \
156
+ -q
157
+ # Expected: 765 passed, 3 skipped
158
+
159
+ # Luego commit el semantic engine:
160
+ git add src/sourcecode/prepare_context.py
161
+ git commit -m "fix: evidence-gated semantic engine — remove unsupported behavioral/transaction claims"
162
+ ```
163
+
164
+ ---
165
+
166
+ *Pausado 2026-05-16 sesión 11 — gsd:pause-work*
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: sourcecode
3
- Version: 1.30.11
3
+ Version: 1.30.12
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
  **Deterministic, behavior-aware codebase context for AI agents and PR review.**
223
223
 
224
- ![Version](https://img.shields.io/badge/version-1.30.11-blue)
224
+ ![Version](https://img.shields.io/badge/version-1.30.12-blue)
225
225
  ![Python](https://img.shields.io/badge/python-3.10%2B-green)
226
226
 
227
227
  ---
@@ -257,7 +257,7 @@ pipx install sourcecode
257
257
 
258
258
  ```bash
259
259
  sourcecode version
260
- # sourcecode 1.30.11
260
+ # sourcecode 1.30.12
261
261
  ```
262
262
 
263
263
  ---
@@ -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.30.11-blue)
5
+ ![Version](https://img.shields.io/badge/version-1.30.12-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.30.11
41
+ # sourcecode 1.30.12
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.30.11"
7
+ version = "1.30.12"
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.30.11"
3
+ __version__ = "1.30.12"
@@ -1952,6 +1952,89 @@ def telemetry_disable() -> None:
1952
1952
  typer.echo("Re-enable at any time: sourcecode telemetry enable")
1953
1953
 
1954
1954
 
1955
+ # ── repo-ir ───────────────────────────────────────────────────────────────────
1956
+
1957
+ @app.command("repo-ir")
1958
+ def repo_ir_cmd(
1959
+ path: Path = typer.Argument(
1960
+ Path("."),
1961
+ help="Repository root to analyze (default: current directory)",
1962
+ ),
1963
+ since: Optional[str] = typer.Option(
1964
+ None,
1965
+ "--since",
1966
+ help="Git ref for symbol-level diff (e.g. HEAD~1, main)",
1967
+ ),
1968
+ files: Optional[str] = typer.Option(
1969
+ None,
1970
+ "--files",
1971
+ help="Comma-separated list of Java files (relative to path) to analyze",
1972
+ ),
1973
+ output_path: Optional[Path] = typer.Option(
1974
+ None,
1975
+ "--output",
1976
+ "-o",
1977
+ help="Write output to a file instead of stdout",
1978
+ ),
1979
+ include_tests: bool = typer.Option(
1980
+ False,
1981
+ "--include-tests",
1982
+ help="Include test files in analysis (excluded by default)",
1983
+ ),
1984
+ ) -> None:
1985
+ """Deterministic symbol-level IR for Java repositories.
1986
+
1987
+ \b
1988
+ Extracts symbols, relations, Spring roles, and (with --since) symbol-level diffs.
1989
+ Output is JSON: symbols[], relations[], changed_symbols[], spring_summary, graph_metadata.
1990
+
1991
+ \b
1992
+ Examples:
1993
+ sourcecode repo-ir
1994
+ sourcecode repo-ir /path/to/repo --since HEAD~1
1995
+ sourcecode repo-ir --files src/main/java/UserService.java
1996
+ sourcecode repo-ir --since main --output ir.json
1997
+ """
1998
+ import json as _json
1999
+ import sys as _sys
2000
+
2001
+ from sourcecode.repository_ir import build_repo_ir, find_java_files
2002
+
2003
+ root = path.resolve()
2004
+ if not root.is_dir():
2005
+ typer.echo(f"Error: {root} is not a directory", err=True)
2006
+ raise typer.Exit(1)
2007
+
2008
+ if files:
2009
+ file_list = [f.strip() for f in files.split(",") if f.strip()]
2010
+ else:
2011
+ file_list = find_java_files(root)
2012
+ if not include_tests:
2013
+ file_list = [f for f in file_list if "/test/" not in f and "/tests/" not in f]
2014
+
2015
+ if not file_list:
2016
+ typer.echo(
2017
+ _json.dumps({
2018
+ "symbols": [],
2019
+ "relations": [],
2020
+ "changed_symbols": [],
2021
+ "spring_summary": {},
2022
+ "graph_metadata": {"node_count": 0, "edge_count": 0, "has_call_graph": False},
2023
+ }, indent=2)
2024
+ )
2025
+ return
2026
+
2027
+ ir = build_repo_ir(file_list, root, since=since)
2028
+ output = _json.dumps(ir, indent=2, ensure_ascii=False)
2029
+
2030
+ if output_path:
2031
+ output_path.write_text(output, encoding="utf-8")
2032
+ typer.echo(f"IR written to {output_path}", err=True)
2033
+ else:
2034
+ _sys.stdout.write(output)
2035
+ _sys.stdout.write("\n")
2036
+
2037
+
1955
2038
  # ── version ───────────────────────────────────────────────────────────────────
1956
2039
 
1957
2040
  @app.command("version")
@@ -1037,7 +1037,7 @@ class TaskContextBuilder:
1037
1037
  _pr_review_hotspots = sorted(
1038
1038
  [f for f, cls in _pr_changed_cls.items()
1039
1039
  if not cls["is_noise"] and cls["artifact_type"] != "build_manifest"],
1040
- key=lambda f: _delta_impact_score_per_file.get(f, 0.0),
1040
+ key=lambda f: (_delta_impact_score_per_file.get(f) or {}).get("score", 0.0),
1041
1041
  reverse=True,
1042
1042
  )[:8]
1043
1043
 
@@ -1130,9 +1130,9 @@ class TaskContextBuilder:
1130
1130
  "basis": _role_basis,
1131
1131
  }
1132
1132
 
1133
- # File confidence: replaces numeric score
1134
- _impact_s = _delta_impact_score_per_file.get(_f, 0.45)
1135
- _f_conf = "high" if _impact_s >= 0.60 else ("medium" if _impact_s >= 0.40 else "low")
1133
+ # File confidence: from structured impact entry
1134
+ _impact_entry = _delta_impact_score_per_file.get(_f) or {}
1135
+ _f_conf = _impact_entry.get("confidence", "low")
1136
1136
  _diff_source = (
1137
1137
  DiffSourceType.GIT_RANGE.value if _f in _committed_set
1138
1138
  else DiffSourceType.WORKTREE_UNSTAGED.value if _f in _uncommitted_set
@@ -2237,14 +2237,17 @@ class TaskContextBuilder:
2237
2237
  # use module-level constant (single source of truth)
2238
2238
  _CHANGE_EFFECT = _ARTIFACT_CHANGE_EFFECT
2239
2239
 
2240
- # change_type taxonomy — closed set, derived from artifact type
2240
+ # change_type taxonomy — evidence-gated.
2241
+ # "source" → no change_type: unclassified file has no confirmed executable role.
2242
+ # behavioral_change requires semantic diff evidence (api_change/security_change),
2243
+ # not just artifact type — gate applied in Step 3d using diff_severities.
2241
2244
  _ARTIFACT_CHANGE_TYPES: dict[str, list[str]] = {
2242
- "entrypoint": ["behavioral_change", "structural_change"],
2243
- "security": ["behavioral_change", "security_change"],
2244
- "controller": ["behavioral_change", "structural_change"],
2245
- "service": ["behavioral_change"],
2246
- "repository": ["behavioral_change"],
2247
- "mapper": ["behavioral_change"],
2245
+ "entrypoint": ["structural_change"], # behavioral only if diff confirms
2246
+ "security": ["security_change"],
2247
+ "controller": ["structural_change"], # behavioral only if diff confirms
2248
+ "service": [], # behavioral only if @Transactional or diff confirms
2249
+ "repository": [], # behavioral only if query/ORM diff confirms
2250
+ "mapper": [],
2248
2251
  "spring_config": ["configuration_change"],
2249
2252
  "spring_profile": ["configuration_change"],
2250
2253
  "config": ["configuration_change"],
@@ -2252,22 +2255,34 @@ class TaskContextBuilder:
2252
2255
  "db_migration": ["structural_change"],
2253
2256
  "domain_model": ["structural_change"],
2254
2257
  "dto": ["structural_change"],
2255
- "source": ["behavioral_change"],
2258
+ "source": [], # no claim without content evidence
2256
2259
  "test": [],
2257
2260
  "documentation": [],
2258
2261
  "ide_noise": [],
2259
2262
  }
2260
2263
 
2264
+ # Semantic diff → change_type supplement (gated on actual diff content)
2265
+ # applied per-file in Step 3d alongside diff_severities
2266
+ _DIFF_SEVERITY_CHANGE_TYPES: dict[str, list[str]] = {
2267
+ "api_change": ["behavioral_change"],
2268
+ "security_change": ["behavioral_change", "security_change"],
2269
+ "field_change": ["structural_change"],
2270
+ "trivial": [],
2271
+ "unknown": [], # no claim — unknown diff content
2272
+ }
2273
+
2261
2274
  _SEV_ORDER = ["noise", "low", "medium", "high", "critical"]
2262
2275
 
2263
- # Closed impact_area taxonomy — 9 categories, no "unknown"
2276
+ # impact_area taxonomy — evidence-gated.
2277
+ # "source" → "application_layer" (neutral). transaction_boundary only for
2278
+ # evidence-confirmed service/transactional artifacts.
2264
2279
  _ATYPE_IMPACT_AREA: dict[str, str] = {
2265
2280
  "entrypoint": "api_surface",
2266
2281
  "controller": "api_surface",
2267
2282
  "dto": "api_surface",
2268
2283
  "security": "security_layer",
2269
2284
  "spring_config": "dependency_injection",
2270
- "service": "transaction_boundary",
2285
+ "service": "application_layer", # transaction_boundary only if @Transactional evidence
2271
2286
  "repository": "persistence_layer",
2272
2287
  "mapper": "persistence_layer",
2273
2288
  "db_migration": "persistence_layer",
@@ -2275,7 +2290,7 @@ class TaskContextBuilder:
2275
2290
  "config": "configuration",
2276
2291
  "spring_profile": "configuration",
2277
2292
  "build_manifest": "build_system",
2278
- "source": "transaction_boundary",
2293
+ "source": "application_layer", # neutral — no transaction claim without evidence
2279
2294
  "test": "configuration",
2280
2295
  "documentation": "configuration",
2281
2296
  "ide_noise": "configuration",
@@ -2287,18 +2302,18 @@ class TaskContextBuilder:
2287
2302
  path_lower = path.lower()
2288
2303
  suffix = Path(path).suffix.lower()
2289
2304
  path_segs = set(path_lower.replace("\\", "/").split("/"))
2290
- # UI layer: frontend file extensions or frontend directory segments
2291
2305
  if suffix in (".tsx", ".jsx", ".vue") or (
2292
2306
  suffix in (".ts", ".js") and bool(path_segs & _UI_PATH_SEGS)
2293
2307
  ):
2294
2308
  return "ui_layer"
2295
- # Integration layer: external service clients and adapters
2296
2309
  stem_lower = Path(path).stem.lower()
2297
2310
  if any(kw in stem_lower for kw in _INTEGRATION_STEMS):
2298
2311
  return "integration_layer"
2299
- return _ATYPE_IMPACT_AREA.get(atype, "transaction_boundary")
2312
+ return _ATYPE_IMPACT_AREA.get(atype, "application_layer")
2300
2313
 
2301
- # Closed role_in_system taxonomy 8 roles, no "leaf"/"dependency"
2314
+ # role_in_system — evidence-gated.
2315
+ # Default is "unclassified" not "core_service": unclassified source files
2316
+ # have no confirmed architectural role.
2302
2317
  def _role_in_system(path: str, atype: str, in_ep_paths: bool) -> str:
2303
2318
  if atype == "build_manifest":
2304
2319
  return "build_artifact"
@@ -2317,19 +2332,30 @@ class TaskContextBuilder:
2317
2332
  return "configuration"
2318
2333
  if atype in ("repository", "mapper", "db_migration"):
2319
2334
  return "data_access"
2320
- return "core_service"
2321
-
2322
- def _structured_why(path: str, atype: str, module: str, role: str, risk_areas: list[str]) -> str:
2335
+ if atype == "service":
2336
+ return "service" # annotation-confirmed — not "core_service" (overclaim)
2337
+ return "unclassified" # no role claim without evidence
2338
+
2339
+ def _score_to_confidence(score: float) -> str:
2340
+ if score >= 0.60:
2341
+ return "high"
2342
+ if score >= 0.40:
2343
+ return "medium"
2344
+ return "low"
2345
+
2346
+ def _structured_why(path: str, atype: str, module: str, role: str, risk_areas: list[str], cls_confidence: str = "low") -> str:
2323
2347
  area = _classify_impact_area(path, risk_areas, atype)
2324
- prop = _PROPAGATION_RISK.get(atype, "low")
2325
- effect = _CHANGE_EFFECT.get(atype, "modifies application logic")
2326
- parts = [
2327
- f"artifact_type: {atype}",
2328
- f"role_in_system: {role}",
2329
- f"impact_area: {area}",
2330
- f"propagation_risk: {prop}",
2331
- f"change_effect: {effect}",
2332
- ]
2348
+ prop = _PROPAGATION_RISK.get(atype, "low") if atype != "source" else "unknown"
2349
+ effect = _CHANGE_EFFECT.get(atype, "may modify application logic (role unconfirmed)")
2350
+ parts = [f"artifact_type: {atype}", f"classification_confidence: {cls_confidence}"]
2351
+ # Only emit role/area/propagation when there is confirmed evidence (not source/unclassified)
2352
+ if role not in ("unclassified",):
2353
+ parts.append(f"role_in_system: {role}")
2354
+ if area not in ("application_layer",):
2355
+ parts.append(f"impact_area: {area}")
2356
+ if atype not in ("source",) and prop != "unknown":
2357
+ parts.append(f"propagation_risk: {prop}")
2358
+ parts.append(f"change_effect: {effect}")
2333
2359
  if module:
2334
2360
  parts.append(f"module: {module}")
2335
2361
  return " | ".join(parts)
@@ -2403,8 +2429,10 @@ class TaskContextBuilder:
2403
2429
 
2404
2430
  in_ep = path in ep_paths
2405
2431
  role = _role_in_system(path, atype, in_ep)
2406
- why_str = _structured_why(path, atype, module, role, cls["risk_areas"])
2407
- reason = f"changed since {ref_label} | artifact: {atype} | score: {score:.2f}"
2432
+ cls_conf = cls.get("confidence", "low")
2433
+ why_str = _structured_why(path, atype, module, role, cls["risk_areas"], cls_conf)
2434
+ confidence = _score_to_confidence(score)
2435
+ reason = f"changed since {ref_label} | artifact: {atype} | confidence: {confidence}"
2408
2436
 
2409
2437
  relevant.append(RelevantFile(path=path, role=role, score=round(score, 2), reason=reason, why=why_str))
2410
2438
  why[path] = why_str
@@ -2453,15 +2481,11 @@ class TaskContextBuilder:
2453
2481
  ]
2454
2482
  in_ep = path in ep_paths
2455
2483
  role = _role_in_system(path, rel_atype, in_ep)
2456
- why_str = (
2457
- f"artifact_type: {rel_atype} | role_in_system: {role}"
2458
- f" | impact_area: {_classify_impact_area(path, rel_cls['risk_areas'], rel_atype)}"
2459
- f" | propagation_risk: {_PROPAGATION_RISK.get(rel_atype, 'low')}"
2460
- f" | change_effect: {_CHANGE_EFFECT.get(rel_atype, 'modifies application logic')}"
2461
- f" | pulled_by: type-aware expansion from {ctx_type} '{ctx_val}'"
2462
- f" | triggered_by: {', '.join(triggers[:3])}"
2463
- )
2464
- reason = f"expansion: {ctx_type} '{ctx_val}' | artifact: {rel_atype} | score: {rel_score:.2f}"
2484
+ rel_conf = rel_cls.get("confidence", "low")
2485
+ why_str = _structured_why(path, rel_atype, _extract_ddd_domain(path), role, rel_cls["risk_areas"], rel_conf)
2486
+ why_str += f" | pulled_by: type-aware expansion from {ctx_type} '{ctx_val}'"
2487
+ why_str += f" | triggered_by: {', '.join(triggers[:3])}"
2488
+ reason = f"expansion: {ctx_type} '{ctx_val}' | artifact: {rel_atype} | confidence: {_score_to_confidence(rel_score)}"
2465
2489
  related.append((rel_score, path, RelevantFile(
2466
2490
  path=path, role=role, score=rel_score, reason=reason, why=why_str
2467
2491
  )))
@@ -2563,16 +2587,15 @@ class TaskContextBuilder:
2563
2587
  _dep_score = round(_dep_score_base * (0.70 ** _hop_num) * _cross_module_factor, 2)
2564
2588
  _dep_role = _role_in_system(_dep_path, _dep_atype, _dep_path in ep_paths)
2565
2589
 
2566
- _why_str = (
2567
- f"artifact_type: {_dep_atype} | role_in_system: {_dep_role}"
2568
- f" | impact_area: {_classify_impact_area(_dep_path, _dep_cls['risk_areas'], _dep_atype)}"
2569
- f" | propagation_risk: {_PROPAGATION_RISK.get(_dep_atype, 'low')}"
2570
- f" | change_effect: {_CHANGE_EFFECT.get(_dep_atype, 'modifies application logic')}"
2571
- f" | pulled_by: hop-{_hop_num} import from {Path(_seed_path).name}"
2590
+ _dep_conf = _dep_cls.get("confidence", "low")
2591
+ _why_str = _structured_why(
2592
+ _dep_path, _dep_atype, _dep_module, _dep_role,
2593
+ _dep_cls["risk_areas"], _dep_conf
2572
2594
  )
2595
+ _why_str += f" | pulled_by: hop-{_hop_num} import from {Path(_seed_path).name}"
2573
2596
  _reason = (
2574
2597
  f"hop-{_hop_num} import-dependent of {Path(_seed_path).name}"
2575
- f" ({_seed_atype}) | score: {_dep_score:.2f}"
2598
+ f" ({_seed_atype}) | confidence: {_score_to_confidence(_dep_score)}"
2576
2599
  )
2577
2600
  why[_dep_path] = _why_str
2578
2601
  # Tests import production code but are not structural dependencies —
@@ -2621,13 +2644,18 @@ class TaskContextBuilder:
2621
2644
  if _edge["from"] in _downstream_count:
2622
2645
  _downstream_count[_edge["from"]] += 1
2623
2646
 
2624
- impact_score_per_file: dict[str, float] = {}
2647
+ impact_score_per_file: dict[str, Any] = {}
2625
2648
  all_change_types: set[str] = set()
2626
2649
  for _path in changed_files:
2627
2650
  _cls = classifications[_path]
2628
2651
  _atype = _cls["artifact_type"]
2629
- _file_ctypes = _ARTIFACT_CHANGE_TYPES.get(_atype, [])
2652
+ # Base change types from artifact classification
2653
+ _file_ctypes: set[str] = set(_ARTIFACT_CHANGE_TYPES.get(_atype, []))
2654
+ # Supplement with semantic diff evidence — behavioral_change ONLY from diff
2655
+ _diff_sev = diff_severities.get(_path, "unknown")
2656
+ _file_ctypes.update(_DIFF_SEVERITY_CHANGE_TYPES.get(_diff_sev, []))
2630
2657
  all_change_types.update(_file_ctypes)
2658
+
2631
2659
  _base = _ARTIFACT_SCORE.get(_atype, 0.45)
2632
2660
  _sec_w = 0.20 if (_atype == "security" or "security" in _cls["risk_areas"]) else 0.0
2633
2661
  _fw = (
@@ -2641,58 +2669,78 @@ class TaskContextBuilder:
2641
2669
  0.05 if any(ct in ("structural_change", "dependency_change") for ct in _file_ctypes) else
2642
2670
  0.02
2643
2671
  )
2644
- impact_score_per_file[_path] = round(min(1.0, _base * 0.50 + _sec_w + _fw + _fanout + _ctw), 3)
2672
+ _raw_score = round(min(1.0, _base * 0.50 + _sec_w + _fw + _fanout + _ctw), 3)
2673
+ impact_score_per_file[_path] = {
2674
+ "score": _raw_score,
2675
+ "confidence": _score_to_confidence(_raw_score),
2676
+ "score_breakdown": {
2677
+ "artifact_base": round(_base * 0.50, 3),
2678
+ "security_weight": _sec_w,
2679
+ "framework_weight": _fw,
2680
+ "fanout_weight": round(_fanout, 3),
2681
+ "change_type_weight": _ctw,
2682
+ },
2683
+ "change_types": sorted(_file_ctypes),
2684
+ "diff_severity": _diff_sev,
2685
+ }
2645
2686
 
2646
2687
  _CT_ORDER = ["security_change", "behavioral_change", "structural_change",
2647
2688
  "configuration_change", "dependency_change", "ui_change"]
2648
2689
  aggregate_change_type = [ct for ct in _CT_ORDER if ct in all_change_types]
2649
2690
 
2650
- # system_impact block
2691
+ # system_impact: only evidence-backed subsystems.
2692
+ # application_layer → not emitted as subsystem (no architectural claim without evidence).
2693
+ # transaction_layer → removed: transaction_boundary no longer mapped to source/service.
2651
2694
  _IMPACT_AREA_TO_SUBSYSTEM = {
2652
2695
  "api_surface": "api_layer",
2653
2696
  "security_layer": "security_layer",
2654
2697
  "dependency_injection": "spring_di_layer",
2655
2698
  "persistence_layer": "persistence_layer",
2656
- "transaction_boundary": "transaction_layer",
2657
2699
  "configuration": "configuration_layer",
2658
2700
  "build_system": "build_system",
2659
2701
  "ui_layer": "ui_layer",
2660
2702
  "integration_layer": "integration_layer",
2703
+ # application_layer intentionally omitted — no subsystem claim for unclassified files
2661
2704
  }
2662
2705
  _seen_subsys: set[str] = set()
2663
2706
  changed_subsystems: list[str] = []
2664
2707
  for _p, _cls in classifications.items():
2665
- if not _cls["is_noise"]:
2666
- _area = _classify_impact_area(_p, _cls["risk_areas"], _cls["artifact_type"])
2708
+ _p_atype = _cls["artifact_type"]
2709
+ # Only emit subsystem for evidence-backed classifications (not source/unclassified)
2710
+ if not _cls["is_noise"] and _p_atype not in ("source", "ide_noise"):
2711
+ _area = _classify_impact_area(_p, _cls["risk_areas"], _p_atype)
2667
2712
  _subsys = _IMPACT_AREA_TO_SUBSYSTEM.get(_area)
2668
2713
  if _subsys and _subsys not in _seen_subsys:
2669
2714
  changed_subsystems.append(_subsys)
2670
2715
  _seen_subsys.add(_subsys)
2671
2716
 
2717
+ # behavioral_changes: gated on semantic diff evidence (api_change/security_change),
2718
+ # NOT on artifact type alone. Avoids false behavioral claims for validator/util files.
2672
2719
  behavioral_changes: list[str] = [
2673
- f"{Path(_p).name}: {_CHANGE_EFFECT[_cls['artifact_type']]}"
2720
+ f"{Path(_p).name}: {_CHANGE_EFFECT.get(_cls['artifact_type'], 'may modify application logic')}"
2674
2721
  for _p, _cls in classifications.items()
2675
2722
  if not _cls["is_noise"]
2676
- and any(ct in ("behavioral_change", "security_change")
2677
- for ct in _ARTIFACT_CHANGE_TYPES.get(_cls["artifact_type"], []))
2723
+ and diff_severities.get(_p, "unknown") in ("api_change", "security_change")
2678
2724
  ]
2679
2725
 
2680
2726
  def _runtime_impact(tc: dict[str, int]) -> list[str]:
2681
2727
  _ri: list[str] = []
2728
+ # Only emit claims that are evidence-backed (annotation-confirmed roles)
2682
2729
  if "entrypoint" in tc:
2683
- _ri.append("Entrypoint-classified file modified — may require full context restart before deploy (role inferred from path)")
2730
+ _ri.append("Entrypoint-classified file modified — may require full context restart before deploy")
2684
2731
  if "spring_config" in tc:
2685
- _ri.append("Spring config-classified file modified — wired beans may be rewired on restart (role inferred from path)")
2732
+ _ri.append("Spring config-classified file modified — wired beans may be rewired on restart")
2686
2733
  if "security" in tc:
2687
- _ri.append("Security-classified file modified — secured endpoints may be affected after restart (role inferred from path)")
2734
+ _ri.append("Security-classified file modified — secured endpoints may be affected after restart")
2688
2735
  if "db_migration" in tc:
2689
2736
  _ri.append("Database schema migration pending — execute before deploying application")
2737
+ # service transactional claim: only if @Service annotation confirmed (not source/unclassified)
2690
2738
  _svc = tc.get("service", 0)
2691
2739
  if _svc >= 2:
2692
- _ri.append(f"{_svc} service-classified file(s) modified — verify transaction scope and data consistency (role inferred from path)")
2740
+ _ri.append(f"{_svc} @Service-annotated file(s) modified — verify business logic consistency")
2693
2741
  _repo = tc.get("repository", 0) + tc.get("mapper", 0)
2694
2742
  if _repo > 0:
2695
- _ri.append(f"{_repo} persistence-classified component(s) modified — verify data access queries (role inferred from path)")
2743
+ _ri.append(f"{_repo} persistence-classified component(s) modified — verify data access queries")
2696
2744
  if "build_manifest" in tc:
2697
2745
  _ri.append("Build manifest modified — dependency resolution required before compile")
2698
2746
  return _ri
@@ -2700,7 +2748,9 @@ class TaskContextBuilder:
2700
2748
  _max_hop = max((e["hop"] for e in graph_edges), default=0)
2701
2749
  dependency_graph_summary: dict = {
2702
2750
  "edges": graph_edges[:30],
2703
- "propagation_depth": _max_hop,
2751
+ # propagation_depth is unknown when no graph edges exist — not 0
2752
+ "propagation_depth": _max_hop if graph_edges else None,
2753
+ "has_graph_evidence": bool(graph_edges),
2704
2754
  }
2705
2755
 
2706
2756
  # ── Step 4: impact summary ─────────────────────────────────────────────