sourcecode 1.30.16__tar.gz → 1.30.18__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 (194) hide show
  1. sourcecode-1.30.18/.continue-here.md +150 -0
  2. {sourcecode-1.30.16 → sourcecode-1.30.18}/PKG-INFO +3 -3
  3. {sourcecode-1.30.16 → sourcecode-1.30.18}/README.md +2 -2
  4. {sourcecode-1.30.16 → sourcecode-1.30.18}/pyproject.toml +1 -1
  5. {sourcecode-1.30.16 → sourcecode-1.30.18}/src/sourcecode/__init__.py +1 -1
  6. {sourcecode-1.30.16 → sourcecode-1.30.18}/src/sourcecode/contract_pipeline.py +2 -0
  7. {sourcecode-1.30.16 → sourcecode-1.30.18}/src/sourcecode/prepare_context.py +98 -29
  8. {sourcecode-1.30.16 → sourcecode-1.30.18}/src/sourcecode/repository_ir.py +2 -0
  9. sourcecode-1.30.16/.continue-here.md +0 -231
  10. {sourcecode-1.30.16 → sourcecode-1.30.18}/.agents/skills/source-command-gsd-join-discord/SKILL.md +0 -0
  11. {sourcecode-1.30.16 → sourcecode-1.30.18}/.agents/skills/source-command-gsd-review-backlog/SKILL.md +0 -0
  12. {sourcecode-1.30.16 → sourcecode-1.30.18}/.agents/skills/source-command-gsd-workstreams/SKILL.md +0 -0
  13. {sourcecode-1.30.16 → sourcecode-1.30.18}/.github/workflows/build-windows.yml +0 -0
  14. {sourcecode-1.30.16 → sourcecode-1.30.18}/.gitignore +0 -0
  15. {sourcecode-1.30.16 → sourcecode-1.30.18}/.ruff.toml +0 -0
  16. {sourcecode-1.30.16 → sourcecode-1.30.18}/CONTRIBUTING.md +0 -0
  17. {sourcecode-1.30.16 → sourcecode-1.30.18}/LICENSE +0 -0
  18. {sourcecode-1.30.16 → sourcecode-1.30.18}/SECURITY.md +0 -0
  19. {sourcecode-1.30.16 → sourcecode-1.30.18}/docs/privacy.md +0 -0
  20. {sourcecode-1.30.16 → sourcecode-1.30.18}/docs/schema.md +0 -0
  21. {sourcecode-1.30.16 → sourcecode-1.30.18}/raw +0 -0
  22. {sourcecode-1.30.16 → sourcecode-1.30.18}/run_cli.py +0 -0
  23. {sourcecode-1.30.16 → sourcecode-1.30.18}/src/sourcecode/adaptive_scanner.py +0 -0
  24. {sourcecode-1.30.16 → sourcecode-1.30.18}/src/sourcecode/architecture_analyzer.py +0 -0
  25. {sourcecode-1.30.16 → sourcecode-1.30.18}/src/sourcecode/architecture_summary.py +0 -0
  26. {sourcecode-1.30.16 → sourcecode-1.30.18}/src/sourcecode/ast_extractor.py +0 -0
  27. {sourcecode-1.30.16 → sourcecode-1.30.18}/src/sourcecode/classifier.py +0 -0
  28. {sourcecode-1.30.16 → sourcecode-1.30.18}/src/sourcecode/cli.py +0 -0
  29. {sourcecode-1.30.16 → sourcecode-1.30.18}/src/sourcecode/code_notes_analyzer.py +0 -0
  30. {sourcecode-1.30.16 → sourcecode-1.30.18}/src/sourcecode/confidence_analyzer.py +0 -0
  31. {sourcecode-1.30.16 → sourcecode-1.30.18}/src/sourcecode/context_scorer.py +0 -0
  32. {sourcecode-1.30.16 → sourcecode-1.30.18}/src/sourcecode/context_summarizer.py +0 -0
  33. {sourcecode-1.30.16 → sourcecode-1.30.18}/src/sourcecode/contract_model.py +0 -0
  34. {sourcecode-1.30.16 → sourcecode-1.30.18}/src/sourcecode/coverage_parser.py +0 -0
  35. {sourcecode-1.30.16 → sourcecode-1.30.18}/src/sourcecode/dependency_analyzer.py +0 -0
  36. {sourcecode-1.30.16 → sourcecode-1.30.18}/src/sourcecode/detectors/__init__.py +0 -0
  37. {sourcecode-1.30.16 → sourcecode-1.30.18}/src/sourcecode/detectors/base.py +0 -0
  38. {sourcecode-1.30.16 → sourcecode-1.30.18}/src/sourcecode/detectors/csproj_parser.py +0 -0
  39. {sourcecode-1.30.16 → sourcecode-1.30.18}/src/sourcecode/detectors/dart.py +0 -0
  40. {sourcecode-1.30.16 → sourcecode-1.30.18}/src/sourcecode/detectors/dotnet.py +0 -0
  41. {sourcecode-1.30.16 → sourcecode-1.30.18}/src/sourcecode/detectors/elixir.py +0 -0
  42. {sourcecode-1.30.16 → sourcecode-1.30.18}/src/sourcecode/detectors/go.py +0 -0
  43. {sourcecode-1.30.16 → sourcecode-1.30.18}/src/sourcecode/detectors/heuristic.py +0 -0
  44. {sourcecode-1.30.16 → sourcecode-1.30.18}/src/sourcecode/detectors/hybrid.py +0 -0
  45. {sourcecode-1.30.16 → sourcecode-1.30.18}/src/sourcecode/detectors/java.py +0 -0
  46. {sourcecode-1.30.16 → sourcecode-1.30.18}/src/sourcecode/detectors/jvm_ext.py +0 -0
  47. {sourcecode-1.30.16 → sourcecode-1.30.18}/src/sourcecode/detectors/nodejs.py +0 -0
  48. {sourcecode-1.30.16 → sourcecode-1.30.18}/src/sourcecode/detectors/parsers.py +0 -0
  49. {sourcecode-1.30.16 → sourcecode-1.30.18}/src/sourcecode/detectors/php.py +0 -0
  50. {sourcecode-1.30.16 → sourcecode-1.30.18}/src/sourcecode/detectors/project.py +0 -0
  51. {sourcecode-1.30.16 → sourcecode-1.30.18}/src/sourcecode/detectors/python.py +0 -0
  52. {sourcecode-1.30.16 → sourcecode-1.30.18}/src/sourcecode/detectors/ruby.py +0 -0
  53. {sourcecode-1.30.16 → sourcecode-1.30.18}/src/sourcecode/detectors/rust.py +0 -0
  54. {sourcecode-1.30.16 → sourcecode-1.30.18}/src/sourcecode/detectors/systems.py +0 -0
  55. {sourcecode-1.30.16 → sourcecode-1.30.18}/src/sourcecode/detectors/terraform.py +0 -0
  56. {sourcecode-1.30.16 → sourcecode-1.30.18}/src/sourcecode/detectors/tooling.py +0 -0
  57. {sourcecode-1.30.16 → sourcecode-1.30.18}/src/sourcecode/doc_analyzer.py +0 -0
  58. {sourcecode-1.30.16 → sourcecode-1.30.18}/src/sourcecode/entrypoint_classifier.py +0 -0
  59. {sourcecode-1.30.16 → sourcecode-1.30.18}/src/sourcecode/env_analyzer.py +0 -0
  60. {sourcecode-1.30.16 → sourcecode-1.30.18}/src/sourcecode/file_classifier.py +0 -0
  61. {sourcecode-1.30.16 → sourcecode-1.30.18}/src/sourcecode/flow_analyzer.py +0 -0
  62. {sourcecode-1.30.16 → sourcecode-1.30.18}/src/sourcecode/git_analyzer.py +0 -0
  63. {sourcecode-1.30.16 → sourcecode-1.30.18}/src/sourcecode/graph_analyzer.py +0 -0
  64. {sourcecode-1.30.16 → sourcecode-1.30.18}/src/sourcecode/metrics_analyzer.py +0 -0
  65. {sourcecode-1.30.16 → sourcecode-1.30.18}/src/sourcecode/pr_comment_renderer.py +0 -0
  66. {sourcecode-1.30.16 → sourcecode-1.30.18}/src/sourcecode/progress.py +0 -0
  67. {sourcecode-1.30.16 → sourcecode-1.30.18}/src/sourcecode/ranking_engine.py +0 -0
  68. {sourcecode-1.30.16 → sourcecode-1.30.18}/src/sourcecode/redactor.py +0 -0
  69. {sourcecode-1.30.16 → sourcecode-1.30.18}/src/sourcecode/relevance_scorer.py +0 -0
  70. {sourcecode-1.30.16 → sourcecode-1.30.18}/src/sourcecode/repo_classifier.py +0 -0
  71. {sourcecode-1.30.16 → sourcecode-1.30.18}/src/sourcecode/runtime_classifier.py +0 -0
  72. {sourcecode-1.30.16 → sourcecode-1.30.18}/src/sourcecode/scanner.py +0 -0
  73. {sourcecode-1.30.16 → sourcecode-1.30.18}/src/sourcecode/schema.py +0 -0
  74. {sourcecode-1.30.16 → sourcecode-1.30.18}/src/sourcecode/semantic_analyzer.py +0 -0
  75. {sourcecode-1.30.16 → sourcecode-1.30.18}/src/sourcecode/serializer.py +0 -0
  76. {sourcecode-1.30.16 → sourcecode-1.30.18}/src/sourcecode/summarizer.py +0 -0
  77. {sourcecode-1.30.16 → sourcecode-1.30.18}/src/sourcecode/telemetry/__init__.py +0 -0
  78. {sourcecode-1.30.16 → sourcecode-1.30.18}/src/sourcecode/telemetry/config.py +0 -0
  79. {sourcecode-1.30.16 → sourcecode-1.30.18}/src/sourcecode/telemetry/consent.py +0 -0
  80. {sourcecode-1.30.16 → sourcecode-1.30.18}/src/sourcecode/telemetry/events.py +0 -0
  81. {sourcecode-1.30.16 → sourcecode-1.30.18}/src/sourcecode/telemetry/filters.py +0 -0
  82. {sourcecode-1.30.16 → sourcecode-1.30.18}/src/sourcecode/telemetry/transport.py +0 -0
  83. {sourcecode-1.30.16 → sourcecode-1.30.18}/src/sourcecode/tree_utils.py +0 -0
  84. {sourcecode-1.30.16 → sourcecode-1.30.18}/src/sourcecode/workspace.py +0 -0
  85. {sourcecode-1.30.16 → sourcecode-1.30.18}/tests/__init__.py +0 -0
  86. {sourcecode-1.30.16 → sourcecode-1.30.18}/tests/conftest.py +0 -0
  87. {sourcecode-1.30.16 → sourcecode-1.30.18}/tests/fixtures/coverage.xml +0 -0
  88. {sourcecode-1.30.16 → sourcecode-1.30.18}/tests/fixtures/fastapi_app/pyproject.toml +0 -0
  89. {sourcecode-1.30.16 → sourcecode-1.30.18}/tests/fixtures/fastapi_app/src/main.py +0 -0
  90. {sourcecode-1.30.16 → sourcecode-1.30.18}/tests/fixtures/go_service/cmd/api/main.go +0 -0
  91. {sourcecode-1.30.16 → sourcecode-1.30.18}/tests/fixtures/go_service/go.mod +0 -0
  92. {sourcecode-1.30.16 → sourcecode-1.30.18}/tests/fixtures/jacoco.xml +0 -0
  93. {sourcecode-1.30.16 → sourcecode-1.30.18}/tests/fixtures/latin1_sample.java +0 -0
  94. {sourcecode-1.30.16 → sourcecode-1.30.18}/tests/fixtures/latin1_sample_iso.java +0 -0
  95. {sourcecode-1.30.16 → sourcecode-1.30.18}/tests/fixtures/lcov.info +0 -0
  96. {sourcecode-1.30.16 → sourcecode-1.30.18}/tests/fixtures/nextjs_app/app/page.tsx +0 -0
  97. {sourcecode-1.30.16 → sourcecode-1.30.18}/tests/fixtures/nextjs_app/package.json +0 -0
  98. {sourcecode-1.30.16 → sourcecode-1.30.18}/tests/fixtures/nextjs_app/pnpm-lock.yaml +0 -0
  99. {sourcecode-1.30.16 → sourcecode-1.30.18}/tests/fixtures/pnpm_monorepo/apps/web/app/page.tsx +0 -0
  100. {sourcecode-1.30.16 → sourcecode-1.30.18}/tests/fixtures/pnpm_monorepo/apps/web/package.json +0 -0
  101. {sourcecode-1.30.16 → sourcecode-1.30.18}/tests/fixtures/pnpm_monorepo/packages/api/main.py +0 -0
  102. {sourcecode-1.30.16 → sourcecode-1.30.18}/tests/fixtures/pnpm_monorepo/packages/api/pyproject.toml +0 -0
  103. {sourcecode-1.30.16 → sourcecode-1.30.18}/tests/fixtures/pnpm_monorepo/pnpm-workspace.yaml +0 -0
  104. {sourcecode-1.30.16 → sourcecode-1.30.18}/tests/fixtures/spring_boot_minimal/pom.xml +0 -0
  105. {sourcecode-1.30.16 → sourcecode-1.30.18}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/ausente/application/service/FindAusenteService.java +0 -0
  106. {sourcecode-1.30.16 → sourcecode-1.30.18}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/ausente/domain/entities/Ausente.java +0 -0
  107. {sourcecode-1.30.16 → sourcecode-1.30.18}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/ausente/infrastructure/rest/AusenteRestController.java +0 -0
  108. {sourcecode-1.30.16 → sourcecode-1.30.18}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/autocoberturas/application/service/FindAutocoberturasService.java +0 -0
  109. {sourcecode-1.30.16 → sourcecode-1.30.18}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/autocoberturas/domain/entities/Autocoberturas.java +0 -0
  110. {sourcecode-1.30.16 → sourcecode-1.30.18}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/autocoberturas/infrastructure/rest/AutocoberturasRestController.java +0 -0
  111. {sourcecode-1.30.16 → sourcecode-1.30.18}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/calendarioTrabajador/application/service/FindCalendarioTrabajadorService.java +0 -0
  112. {sourcecode-1.30.16 → sourcecode-1.30.18}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/calendarioTrabajador/domain/entities/CalendarioTrabajador.java +0 -0
  113. {sourcecode-1.30.16 → sourcecode-1.30.18}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/calendarioTrabajador/infrastructure/rest/CalendarioTrabajadorRestController.java +0 -0
  114. {sourcecode-1.30.16 → sourcecode-1.30.18}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/departamento/application/service/FindDepartamentoService.java +0 -0
  115. {sourcecode-1.30.16 → sourcecode-1.30.18}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/departamento/domain/entities/Departamento.java +0 -0
  116. {sourcecode-1.30.16 → sourcecode-1.30.18}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/departamento/infrastructure/rest/DepartamentoRestController.java +0 -0
  117. {sourcecode-1.30.16 → sourcecode-1.30.18}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/empleado/application/service/FindEmpleadoService.java +0 -0
  118. {sourcecode-1.30.16 → sourcecode-1.30.18}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/empleado/domain/entities/Empleado.java +0 -0
  119. {sourcecode-1.30.16 → sourcecode-1.30.18}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/empleado/infrastructure/rest/EmpleadoRestController.java +0 -0
  120. {sourcecode-1.30.16 → sourcecode-1.30.18}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/demo/DemoApplication.java +0 -0
  121. {sourcecode-1.30.16 → sourcecode-1.30.18}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/demo/config/FilterConfig.java +0 -0
  122. {sourcecode-1.30.16 → sourcecode-1.30.18}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/demo/domain/Health.java +0 -0
  123. {sourcecode-1.30.16 → sourcecode-1.30.18}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/demo/mapper/HealthMapper.java +0 -0
  124. {sourcecode-1.30.16 → sourcecode-1.30.18}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/demo/repository/HealthRepository.java +0 -0
  125. {sourcecode-1.30.16 → sourcecode-1.30.18}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/demo/service/HealthService.java +0 -0
  126. {sourcecode-1.30.16 → sourcecode-1.30.18}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/demo/web/HealthRestController.java +0 -0
  127. {sourcecode-1.30.16 → sourcecode-1.30.18}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/demo/web/NominaRestController.java +0 -0
  128. {sourcecode-1.30.16 → sourcecode-1.30.18}/tests/fixtures/spring_boot_minimal/src/main/resources/application-dev.yml +0 -0
  129. {sourcecode-1.30.16 → sourcecode-1.30.18}/tests/fixtures/spring_boot_minimal/src/main/resources/application.yml +0 -0
  130. {sourcecode-1.30.16 → sourcecode-1.30.18}/tests/fixtures/spring_boot_minimal/src/main/resources/mapper/HealthMapper.xml +0 -0
  131. {sourcecode-1.30.16 → sourcecode-1.30.18}/tests/test_architecture_analyzer.py +0 -0
  132. {sourcecode-1.30.16 → sourcecode-1.30.18}/tests/test_architecture_summary.py +0 -0
  133. {sourcecode-1.30.16 → sourcecode-1.30.18}/tests/test_ast_extractor.py +0 -0
  134. {sourcecode-1.30.16 → sourcecode-1.30.18}/tests/test_block1_reliability.py +0 -0
  135. {sourcecode-1.30.16 → sourcecode-1.30.18}/tests/test_block2_coverage.py +0 -0
  136. {sourcecode-1.30.16 → sourcecode-1.30.18}/tests/test_block5_quality.py +0 -0
  137. {sourcecode-1.30.16 → sourcecode-1.30.18}/tests/test_bug_fixes_v16.py +0 -0
  138. {sourcecode-1.30.16 → sourcecode-1.30.18}/tests/test_classifier.py +0 -0
  139. {sourcecode-1.30.16 → sourcecode-1.30.18}/tests/test_cli.py +0 -0
  140. {sourcecode-1.30.16 → sourcecode-1.30.18}/tests/test_code_notes_analyzer.py +0 -0
  141. {sourcecode-1.30.16 → sourcecode-1.30.18}/tests/test_context_scorer.py +0 -0
  142. {sourcecode-1.30.16 → sourcecode-1.30.18}/tests/test_contract_pipeline.py +0 -0
  143. {sourcecode-1.30.16 → sourcecode-1.30.18}/tests/test_coverage_parser.py +0 -0
  144. {sourcecode-1.30.16 → sourcecode-1.30.18}/tests/test_cross_consistency.py +0 -0
  145. {sourcecode-1.30.16 → sourcecode-1.30.18}/tests/test_dependency_analyzer_node_python.py +0 -0
  146. {sourcecode-1.30.16 → sourcecode-1.30.18}/tests/test_dependency_analyzer_polyglot.py +0 -0
  147. {sourcecode-1.30.16 → sourcecode-1.30.18}/tests/test_dependency_schema.py +0 -0
  148. {sourcecode-1.30.16 → sourcecode-1.30.18}/tests/test_detector_dotnet.py +0 -0
  149. {sourcecode-1.30.16 → sourcecode-1.30.18}/tests/test_detector_go_rust_java.py +0 -0
  150. {sourcecode-1.30.16 → sourcecode-1.30.18}/tests/test_detector_nodejs.py +0 -0
  151. {sourcecode-1.30.16 → sourcecode-1.30.18}/tests/test_detector_php_ruby_dart.py +0 -0
  152. {sourcecode-1.30.16 → sourcecode-1.30.18}/tests/test_detector_python.py +0 -0
  153. {sourcecode-1.30.16 → sourcecode-1.30.18}/tests/test_detector_universal_managed.py +0 -0
  154. {sourcecode-1.30.16 → sourcecode-1.30.18}/tests/test_detector_universal_systems.py +0 -0
  155. {sourcecode-1.30.16 → sourcecode-1.30.18}/tests/test_detectors_base.py +0 -0
  156. {sourcecode-1.30.16 → sourcecode-1.30.18}/tests/test_doc_analyzer_jsdom.py +0 -0
  157. {sourcecode-1.30.16 → sourcecode-1.30.18}/tests/test_doc_analyzer_python.py +0 -0
  158. {sourcecode-1.30.16 → sourcecode-1.30.18}/tests/test_encoding_regression.py +0 -0
  159. {sourcecode-1.30.16 → sourcecode-1.30.18}/tests/test_graph_analyzer_polyglot.py +0 -0
  160. {sourcecode-1.30.16 → sourcecode-1.30.18}/tests/test_graph_analyzer_python_node.py +0 -0
  161. {sourcecode-1.30.16 → sourcecode-1.30.18}/tests/test_graph_schema.py +0 -0
  162. {sourcecode-1.30.16 → sourcecode-1.30.18}/tests/test_hybrid_inference.py +0 -0
  163. {sourcecode-1.30.16 → sourcecode-1.30.18}/tests/test_integration.py +0 -0
  164. {sourcecode-1.30.16 → sourcecode-1.30.18}/tests/test_integration_dependencies.py +0 -0
  165. {sourcecode-1.30.16 → sourcecode-1.30.18}/tests/test_integration_detection.py +0 -0
  166. {sourcecode-1.30.16 → sourcecode-1.30.18}/tests/test_integration_docs.py +0 -0
  167. {sourcecode-1.30.16 → sourcecode-1.30.18}/tests/test_integration_graph_modules.py +0 -0
  168. {sourcecode-1.30.16 → sourcecode-1.30.18}/tests/test_integration_lqn.py +0 -0
  169. {sourcecode-1.30.16 → sourcecode-1.30.18}/tests/test_integration_metrics.py +0 -0
  170. {sourcecode-1.30.16 → sourcecode-1.30.18}/tests/test_integration_multistack.py +0 -0
  171. {sourcecode-1.30.16 → sourcecode-1.30.18}/tests/test_integration_semantics.py +0 -0
  172. {sourcecode-1.30.16 → sourcecode-1.30.18}/tests/test_integration_universal.py +0 -0
  173. {sourcecode-1.30.16 → sourcecode-1.30.18}/tests/test_java_spring_integration.py +0 -0
  174. {sourcecode-1.30.16 → sourcecode-1.30.18}/tests/test_metrics_analyzer.py +0 -0
  175. {sourcecode-1.30.16 → sourcecode-1.30.18}/tests/test_packaging.py +0 -0
  176. {sourcecode-1.30.16 → sourcecode-1.30.18}/tests/test_phase1_improvements.py +0 -0
  177. {sourcecode-1.30.16 → sourcecode-1.30.18}/tests/test_pipeline_integrity.py +0 -0
  178. {sourcecode-1.30.16 → sourcecode-1.30.18}/tests/test_real_projects.py +0 -0
  179. {sourcecode-1.30.16 → sourcecode-1.30.18}/tests/test_redactor.py +0 -0
  180. {sourcecode-1.30.16 → sourcecode-1.30.18}/tests/test_repository_ir.py +0 -0
  181. {sourcecode-1.30.16 → sourcecode-1.30.18}/tests/test_scanner.py +0 -0
  182. {sourcecode-1.30.16 → sourcecode-1.30.18}/tests/test_schema.py +0 -0
  183. {sourcecode-1.30.16 → sourcecode-1.30.18}/tests/test_schema_normalization.py +0 -0
  184. {sourcecode-1.30.16 → sourcecode-1.30.18}/tests/test_semantic_analyzer_node.py +0 -0
  185. {sourcecode-1.30.16 → sourcecode-1.30.18}/tests/test_semantic_analyzer_python.py +0 -0
  186. {sourcecode-1.30.16 → sourcecode-1.30.18}/tests/test_semantic_import_resolution.py +0 -0
  187. {sourcecode-1.30.16 → sourcecode-1.30.18}/tests/test_semantic_schema.py +0 -0
  188. {sourcecode-1.30.16 → sourcecode-1.30.18}/tests/test_signal_hierarchy.py +0 -0
  189. {sourcecode-1.30.16 → sourcecode-1.30.18}/tests/test_summarizer.py +0 -0
  190. {sourcecode-1.30.16 → sourcecode-1.30.18}/tests/test_surface_honesty.py +0 -0
  191. {sourcecode-1.30.16 → sourcecode-1.30.18}/tests/test_task_differentiation.py +0 -0
  192. {sourcecode-1.30.16 → sourcecode-1.30.18}/tests/test_telemetry.py +0 -0
  193. {sourcecode-1.30.16 → sourcecode-1.30.18}/tests/test_v1_10_regressions.py +0 -0
  194. {sourcecode-1.30.16 → sourcecode-1.30.18}/tests/test_workspace_analyzer.py +0 -0
@@ -0,0 +1,150 @@
1
+ # Continue Here — atlas-cli sesión 15
2
+
3
+ **Paused:** 2026-05-18 (sesión 15)
4
+ **Repo:** `/Users/user/Downloads/atlas-cli`
5
+ **Branch:** master
6
+ **Working tree:** 3 ficheros modificados, SIN commit
7
+
8
+ ---
9
+
10
+ ## Trabajo de esta sesión
11
+
12
+ ### Ya commiteado (66db10b)
13
+
14
+ `fix(cli): three flag-routing bugs in compact/repo-ir paths`
15
+
16
+ | Bug | Fichero | Fix |
17
+ |---|---|---|
18
+ | `--changed-only` = `--compact` (byte idéntico) | `cli.py` | Filtrar `sm.file_paths`, `entry_points`, `code_notes` antes de `compact_view`; `_allowed_changed_files` se computaba pero nunca se aplicaba porque `compact` forzaba `mode=raw` |
19
+ | `--compact --format yaml` ignorado | `cli.py` | Rama compact hardcodeaba `json.dumps`; añadir bloque `if format == "yaml"` igual al de contract_view |
20
+ | `sourcecode repo-ir .` → "No such command '.'" | `cli.py` | `"repo-ir"` ausente de `_SUBCOMMANDS`; preprocessor consumía token como PATH antes de que Click pudiera dispatchar |
21
+
22
+ ---
23
+
24
+ ### Pendiente de commit (3 ficheros modificados)
25
+
26
+ **Para commitear (primera acción al retomar):**
27
+
28
+ ```bash
29
+ cd /Users/user/Downloads/atlas-cli
30
+ git add src/sourcecode/contract_pipeline.py \
31
+ src/sourcecode/repository_ir.py \
32
+ src/sourcecode/prepare_context.py
33
+
34
+ git commit -m "fix(encoding): utf-8 en subprocess + symptom boost por commit messages
35
+
36
+ - repository_ir.py _get_git_old_content: añadir encoding='utf-8', errors='replace'
37
+ al subprocess.run de git show — causa raíz del UnicodeDecodeError cp1252 en Windows
38
+ - contract_pipeline.py grep -rl: mismo fix (fallback Python en Windows, defensivo)
39
+ - prepare_context.py: symptom boost refactor en 6 passes
40
+ - Nuevo: _recent_commits_for_symptom extraído en bloque 5b (sin coste extra)
41
+ - Nuevo: commit message index (file → n commits con keyword en mensaje)
42
+ - Nuevo: inyección desde commit index para ficheros no en candidate pool
43
+ - Fix: content scan +0.05/hit, cap +0.50 (era +0.02, cap +0.30)
44
+ - Fix: code notes matching → back-propagate score al fichero (+0.20/note)
45
+ - Fix: path-kw boost aplicado a candidatos pre-existentes (no solo inyectados)
46
+ - Multi-signal boost en un solo file-read pass; reason string explica cada boost"
47
+ ```
48
+
49
+ ---
50
+
51
+ ## Qué hace cada cambio pendiente
52
+
53
+ ### `repository_ir.py` + `contract_pipeline.py` — encoding fix
54
+
55
+ ```python
56
+ # Antes (crash en Windows cp1252):
57
+ result = subprocess.run([...], text=True, timeout=5)
58
+
59
+ # Después:
60
+ result = subprocess.run([...], text=True, encoding="utf-8", errors="replace", timeout=5)
61
+ ```
62
+
63
+ Causa raíz del bug reportado: `sourcecode repo-ir . --since HEAD~3` en Windows 11 Python 3.10
64
+ crasheaba con `UnicodeDecodeError: 'charmap' codec can't decode byte 0x81` porque
65
+ `subprocess` hereda `cp1252` como encoding por defecto en Windows.
66
+
67
+ ### `prepare_context.py` — symptom boost overhaul
68
+
69
+ **Problema original:** `--symptom "sesiones"` = output idéntico al baseline porque:
70
+ - Ningún path Java contiene "sesiones" (clases no se nombran en español)
71
+ - Content scan era demasiado débil (+0.02/hit → max +0.20 para 10 hits)
72
+ - Git commit messages no se escaneaban
73
+
74
+ **Nuevo pipeline (6 passes):**
75
+
76
+ | Pass | Señal | Boost | Cap |
77
+ |---|---|---|---|
78
+ | 1 | Code notes text match → `related_notes` + `_note_matched_paths` | — | — |
79
+ | 2 | **Commit index**: `file → n_commits` con keyword en mensaje | — | — |
80
+ | 3 | **Inyección desde commit index** (ficheros no en pool) | +0.15/commit desde 0.5 | 0.85 |
81
+ | 4 | Path injection (sin cambios lógicos) | +0.20/kw desde 0.5 | 1.0 |
82
+ | 5 | **Multi-signal boost** en 1 file-read: commit (+0.25/commit, cap+0.40), note (+0.20/note, cap+0.30), path-kw (+0.20/kw), content (+0.05/hit, cap+0.50) | acumulativo | 1.0 |
83
+ | 6 | Cross-layer synonym frontend→backend (sin cambios) | sin cambios | — |
84
+
85
+ **Before/after verificado** en BroadleafCommerce:
86
+ - `--symptom "pagination"`: top 10 pasa de servicios genéricos (0.67) a `PageDao.java` (0.90, role=`symptom_match`, reason="commit-msg symptom ×1 (+0.25)")
87
+ - `--symptom "zookeeper"`: `pom.xml` (1.00, 2 commit hits), `ZookeeperUtil.java` (1.00, path+content)
88
+
89
+ ---
90
+
91
+ ## Estado de tests
92
+
93
+ ```
94
+ 920 passed, 3 skipped
95
+ ```
96
+
97
+ Pre-existing failures (no tocar):
98
+ - `tests/test_block2_coverage.py` — bug `DocRecord` en `doc_analyzer.py`
99
+ - `tests/test_dependency_analyzer_node_python.py::test_python_requirements_without_lockfile_keeps_declared_versions`
100
+
101
+ ---
102
+
103
+ ## Pendientes (próxima sesión)
104
+
105
+ ### Heredados de sesión 14 (aún vigentes)
106
+
107
+ 1. **Spring bean wiring graph** — `_build_relations` emite `injects` edges para `@Autowired`. Falta: trazar `@Configuration → @Bean → @Autowired` completo, exponer como `wiring_graph`.
108
+
109
+ 2. **Smoke test en repo spring-boot real:**
110
+ ```bash
111
+ cd ~/Documents/workspace/spring-boot-realworld-example-app
112
+ sourcecode repo-ir . --since HEAD~1 2>/dev/null | python3 -c "
113
+ import json, sys; d=json.load(sys.stdin)
114
+ print('nodes:', len(d['graph']['nodes']))
115
+ print('route_surface:', d.get('route_surface', []))
116
+ print('reverse_graph keys:', len(d.get('reverse_graph', {})))
117
+ "
118
+ ```
119
+
120
+ 3. **Transaction boundary tracking** — `@Transactional` detectado. Falta: emitir `transactional_boundary` edges.
121
+
122
+ 4. **`_diff_routes` para `@RequestMapping` en clase** — class-level mapping change debería propagarse a todos los endpoints del controller.
123
+
124
+ ### Nuevos de sesión 15
125
+
126
+ 5. **Tests para el symptom fix** — validar que `--symptom "sesiones"` con commits mock que contengan "sesiones" en mensaje produce ranking diferente al baseline. Cobertura en `tests/test_prepare_context_symptom.py` o similar.
127
+
128
+ 6. **`_FRONTEND_SYMPTOM_MAP`** — añadir "sesiones"/"session" como frontend keyword con backend terms `["httpsession", "sessionmanager", "sessionservice", "sessionrepository"]`.
129
+
130
+ ---
131
+
132
+ ## Para retomar
133
+
134
+ ```bash
135
+ cd /Users/user/Downloads/atlas-cli
136
+ git log --oneline -3 # debe mostrar 66db10b como más reciente
137
+ git status # 3 ficheros M: contract_pipeline, prepare_context, repository_ir
138
+
139
+ # Primera acción: commitear (comando arriba)
140
+
141
+ python3 -m pytest tests/ \
142
+ --ignore=tests/test_block2_coverage.py \
143
+ --ignore=tests/test_dependency_analyzer_node_python.py \
144
+ -q
145
+ # Expected: 920 passed, 3 skipped
146
+ ```
147
+
148
+ ---
149
+
150
+ *Pausado 2026-05-18 sesión 15 — gsd:pause-work*
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: sourcecode
3
- Version: 1.30.16
3
+ Version: 1.30.18
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.16-blue)
224
+ ![Version](https://img.shields.io/badge/version-1.30.18-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.16
260
+ # sourcecode 1.30.18
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.16-blue)
5
+ ![Version](https://img.shields.io/badge/version-1.30.18-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.16
41
+ # sourcecode 1.30.18
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.16"
7
+ version = "1.30.18"
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.16"
3
+ __version__ = "1.30.18"
@@ -623,6 +623,8 @@ def _find_symbol_files(
623
623
  cwd=str(root),
624
624
  capture_output=True,
625
625
  text=True,
626
+ encoding="utf-8",
627
+ errors="replace",
626
628
  timeout=20,
627
629
  )
628
630
  for line in result.stdout.splitlines():
@@ -561,17 +561,23 @@ _ARTIFACT_CHANGE_EFFECT: dict[str, str] = {
561
561
  # Maps frontend symptom keywords → backend terms likely to contain the root cause.
562
562
  # Used to boost service/interceptor files when the symptom is UI-only.
563
563
  _FRONTEND_SYMPTOM_MAP: dict[str, list[str]] = {
564
- "spinner": ["loading", "setloading", "finalize", "httpinterceptor", "interceptor", "service"],
565
- "loading": ["loading", "setloading", "finalize", "httpinterceptor", "interceptor", "service"],
566
- "login": ["authcontroller", "securityconfig", "filterconfig", "jwtfilter", "auth", "authentication"],
567
- "logout": ["authcontroller", "securityconfig", "jwtfilter", "auth", "session"],
568
- "dropdown": ["getmapping", "findall", "obtenertodos", "listall", "findby"],
569
- "modal": ["controller", "getmapping", "findby", "search"],
570
- "popup": ["controller", "getmapping", "findby", "search"],
571
- "table": ["paginated", "findby", "search", "getmapping", "listall"],
572
- "grid": ["paginated", "findby", "search", "getmapping"],
573
- "button": ["postmapping", "putmapping", "deletemapping", "controller", "service"],
574
- "form": ["postmapping", "putmapping", "controller", "service", "dto"],
564
+ "spinner": ["loading", "setloading", "finalize", "httpinterceptor", "interceptor", "service"],
565
+ "loading": ["loading", "setloading", "finalize", "httpinterceptor", "interceptor", "service"],
566
+ "login": ["authcontroller", "securityconfig", "filterconfig", "jwtfilter", "auth", "authentication"],
567
+ "logout": ["authcontroller", "securityconfig", "jwtfilter", "auth", "session"],
568
+ "dropdown": ["getmapping", "findall", "obtenertodos", "listall", "findby"],
569
+ "modal": ["controller", "getmapping", "findby", "search"],
570
+ "popup": ["controller", "getmapping", "findby", "search"],
571
+ "table": ["paginated", "findby", "search", "getmapping", "listall"],
572
+ "grid": ["paginated", "findby", "search", "getmapping"],
573
+ "button": ["postmapping", "putmapping", "deletemapping", "controller", "service"],
574
+ "form": ["postmapping", "putmapping", "controller", "service", "dto"],
575
+ # session-related symptoms (Spanish + English)
576
+ "sesion": ["httpsession", "sessionmanager", "sessionservice", "sessionrepository", "sessionfactory", "authentication"],
577
+ "sesiones": ["httpsession", "sessionmanager", "sessionservice", "sessionrepository", "sessionfactory", "authentication"],
578
+ "session": ["httpsession", "sessionmanager", "sessionservice", "sessionrepository", "sessionfactory", "authentication"],
579
+ # worker/assignment domain terms (common in RRHH/HR systems)
580
+ "trabajador": ["trabajador", "empleado", "worker", "asignacion", "trabajadordao", "trabajadorservice"],
575
581
  }
576
582
 
577
583
 
@@ -826,12 +832,14 @@ class TaskContextBuilder:
826
832
  # ── 5b. Git signals for ranking ────────────────────────────────────
827
833
  git_hotspots: dict[str, int] = {}
828
834
  uncommitted_files: set[str] = set()
835
+ _recent_commits_for_symptom: list = []
829
836
  try:
830
837
  from sourcecode.git_analyzer import GitAnalyzer
831
838
  _gc = GitAnalyzer().analyze(self.root, depth=30, days=90)
832
839
  _bad = {"no_git_repo", "git_not_found", "git_timeout"}
833
840
  if _gc and not (_bad & set(_gc.limitations)):
834
841
  git_hotspots = {h.file: h.commit_count for h in _gc.change_hotspots}
842
+ _recent_commits_for_symptom = list(_gc.recent_commits)
835
843
  if _gc.uncommitted_changes:
836
844
  _uc = _gc.uncommitted_changes
837
845
  uncommitted_files = set(_uc.staged) | set(_uc.unstaged)
@@ -1208,19 +1216,52 @@ class TaskContextBuilder:
1208
1216
  if len(w) > 2
1209
1217
  ]
1210
1218
  if symptom_keywords:
1211
- # Surface code notes whose text contains any keyword
1219
+ # Pass 1: surface code notes whose text contains any keyword
1220
+ # Also track which file paths have matching notes (for score boost below).
1221
+ _note_matched_paths: dict[str, int] = {} # path → count of matching notes
1212
1222
  for _n in cn_notes_for_ranking:
1213
1223
  _text = (getattr(_n, "text", "") or "").lower()
1214
1224
  if any(kw in _text for kw in symptom_keywords):
1225
+ _np = getattr(_n, "path", "")
1215
1226
  related_notes.append({
1216
1227
  "kind": getattr(_n, "kind", ""),
1217
- "path": getattr(_n, "path", ""),
1228
+ "path": _np,
1218
1229
  "line": getattr(_n, "line", None),
1219
1230
  "text": getattr(_n, "text", ""),
1220
1231
  })
1221
- # Secondary pass: inject files whose path matches symptom keywords
1222
- # but weren't in the candidate pool (no structural/git signals).
1232
+ _note_matched_paths[_np] = _note_matched_paths.get(_np, 0) + 1
1233
+
1234
+ # Pass 2: build commit message index — files touched in commits whose
1235
+ # message matches a symptom keyword get a strong recency signal.
1236
+ # This is the primary signal for functional keywords like "sesiones"
1237
+ # that don't appear in file paths but do appear in commit messages.
1238
+ _commit_file_hits: dict[str, int] = {} # path → n matching commits
1239
+ for _cr in _recent_commits_for_symptom:
1240
+ _msg_lower = (_cr.message or "").lower()
1241
+ if any(kw in _msg_lower for kw in symptom_keywords):
1242
+ for _cf in (_cr.files_changed or []):
1243
+ _cf_norm = _cf.replace("\\", "/")
1244
+ _commit_file_hits[_cf_norm] = _commit_file_hits.get(_cf_norm, 0) + 1
1245
+
1246
+ # Pass 3: inject files from commit index not yet in candidate pool
1223
1247
  _existing_paths = {rf.path for rf in relevant_files}
1248
+ for _cp, _nhits in _commit_file_hits.items():
1249
+ if _cp in _existing_paths:
1250
+ continue
1251
+ if Path(_cp).suffix.lower() not in _ALL_EXTENSIONS:
1252
+ continue
1253
+ _ci_score = round(min(0.5 + 0.15 * _nhits, 0.85), 2)
1254
+ relevant_files.append(RelevantFile(
1255
+ path=_cp,
1256
+ role="symptom_match",
1257
+ score=_ci_score,
1258
+ reason=f"commit message matches symptom ({_nhits} commit{'s' if _nhits > 1 else ''})",
1259
+ why=f"symptom commit-index: {', '.join(symptom_keywords)}",
1260
+ ))
1261
+ _existing_paths.add(_cp)
1262
+
1263
+ # Pass 4: inject files whose path matches symptom keywords
1264
+ # but weren't in the candidate pool (no structural/git signals).
1224
1265
  for _p in all_paths:
1225
1266
  if _p in _existing_paths:
1226
1267
  continue
@@ -1242,17 +1283,38 @@ class TaskContextBuilder:
1242
1283
  ))
1243
1284
  _existing_paths.add(_p)
1244
1285
 
1245
- # Re-rank all relevant_files: boost files whose path matches keywords
1246
- def _symptom_score(rf: "RelevantFile") -> float:
1247
- path_lower = rf.path.lower()
1248
- return rf.score + 0.2 * sum(1.0 for kw in symptom_keywords if kw in path_lower)
1249
- relevant_files = sorted(relevant_files, key=lambda rf: -_symptom_score(rf))
1250
-
1251
- # Content scan boost: read file body for symptom keywords
1286
+ # Pass 5: multi-signal boost apply commit, note, content, and path
1287
+ # signals in one pass to avoid redundant file reads.
1252
1288
  _src_exts = frozenset({".java", ".py", ".ts", ".js", ".kt", ".go"})
1253
- _content_boosted: list[RelevantFile] = []
1289
+ _boosted: list[RelevantFile] = []
1254
1290
  for _rf in relevant_files:
1255
1291
  _extra = 0.0
1292
+ _reasons: list[str] = []
1293
+ _p_lower = _rf.path.lower()
1294
+
1295
+ # Commit message boost: +0.25/commit, cap +0.40
1296
+ _c_hits = _commit_file_hits.get(_rf.path, 0)
1297
+ if _c_hits:
1298
+ _cb = min(0.40, _c_hits * 0.25)
1299
+ _extra += _cb
1300
+ _reasons.append(f"commit-msg symptom ×{_c_hits} (+{_cb:.2f})")
1301
+
1302
+ # Code note boost: +0.20/note, cap +0.30
1303
+ _n_hits = _note_matched_paths.get(_rf.path, 0)
1304
+ if _n_hits:
1305
+ _nb = min(0.30, _n_hits * 0.20)
1306
+ _extra += _nb
1307
+ _reasons.append(f"note-match symptom ×{_n_hits} (+{_nb:.2f})")
1308
+
1309
+ # Path keyword boost: +0.20/keyword already in score for injected
1310
+ # files; re-apply for pre-existing candidates whose path matches.
1311
+ _path_kws = [kw for kw in symptom_keywords if kw in _p_lower]
1312
+ if _path_kws and _rf.role != "symptom_match":
1313
+ _pb = 0.20 * len(_path_kws)
1314
+ _extra += _pb
1315
+ _reasons.append(f"path-kw symptom ({', '.join(_path_kws)}) (+{_pb:.2f})")
1316
+
1317
+ # Content scan boost: +0.05/hit, cap +0.50 (was +0.02, cap +0.30)
1256
1318
  if Path(_rf.path).suffix.lower() in _src_exts:
1257
1319
  try:
1258
1320
  _lines = (self.root / _rf.path).read_text(
@@ -1260,26 +1322,33 @@ class TaskContextBuilder:
1260
1322
  ).splitlines()[:300]
1261
1323
  _body = "\n".join(_lines).lower()
1262
1324
  _hits = sum(_body.count(kw) for kw in symptom_keywords)
1263
- _extra = min(0.30, _hits * 0.02)
1325
+ _content_b = min(0.50, _hits * 0.05)
1326
+ if _content_b > 0:
1327
+ _extra += _content_b
1328
+ _reasons.append(f"content-match symptom ×{_hits} (+{_content_b:.2f})")
1264
1329
  except OSError:
1265
1330
  pass
1266
- _content_boosted.append(RelevantFile(
1331
+
1332
+ _new_reason = _rf.reason
1333
+ if _reasons:
1334
+ _new_reason = _rf.reason + ", " + ", ".join(_reasons)
1335
+ _boosted.append(RelevantFile(
1267
1336
  path=_rf.path,
1268
1337
  role=_rf.role,
1269
1338
  score=round(min(_rf.score + _extra, 1.0), 2),
1270
- reason=_rf.reason + (f", content-match symptom (+{_extra:.2f})" if _extra > 0 else ""),
1339
+ reason=_new_reason,
1271
1340
  why=_rf.why,
1272
1341
  ))
1273
- relevant_files = sorted(_content_boosted, key=lambda rf: -rf.score)
1342
+ relevant_files = sorted(_boosted, key=lambda rf: -rf.score)
1274
1343
 
1275
- # Cross-layer synonym boost: frontend keywords → backend equivalents
1344
+ # Pass 6: cross-layer synonym boost frontend keywords → backend equivalents
1276
1345
  _synonym_note: Optional[str] = None
1277
1346
  _frontend_kws = [kw for kw in symptom_keywords if kw in _FRONTEND_SYMPTOM_MAP]
1278
1347
  if _frontend_kws:
1279
1348
  _backend_terms: list[str] = []
1280
1349
  for _fkw in _frontend_kws:
1281
1350
  _backend_terms.extend(_FRONTEND_SYMPTOM_MAP[_fkw])
1282
- _backend_terms_set = list(dict.fromkeys(_backend_terms)) # dedup, preserve order
1351
+ _backend_terms_set = list(dict.fromkeys(_backend_terms))
1283
1352
  _synonym_boosted: list[RelevantFile] = []
1284
1353
  for _rf in relevant_files:
1285
1354
  _extra_syn = 0.0
@@ -997,6 +997,8 @@ def _get_git_old_content(git_root: Path, rel_path: str, since: str) -> Optional[
997
997
  cwd=str(git_root),
998
998
  capture_output=True,
999
999
  text=True,
1000
+ encoding="utf-8",
1001
+ errors="replace",
1000
1002
  timeout=5,
1001
1003
  )
1002
1004
  if result.returncode == 0:
@@ -1,231 +0,0 @@
1
- # Continue Here — atlas-cli sesión 14
2
-
3
- **Paused:** 2026-05-17 (sesión 14)
4
- **Repo:** `/Users/user/Downloads/atlas-cli`
5
- **Branch:** master
6
- **Working tree:** 4 ficheros modificados, SIN commit (trabajo listo para commit)
7
-
8
- ---
9
-
10
- ## Trabajo de esta sesión (NO commiteado)
11
-
12
- Esta sesión completó 3 tareas sobre `repository_ir.py`. Todo el trabajo incluye la sesión 13 (stable IDs) + sesión 14 (route diffing + reverse graph). Hacer UN solo commit con todo.
13
-
14
- ---
15
-
16
- ### Tarea 1 (sesión 13): Rearchitecture Directive — eliminar lenguaje especulativo
17
-
18
- **Ficheros:** `src/sourcecode/prepare_context.py`, `src/sourcecode/flow_analyzer.py`
19
-
20
- | Eliminado | Reemplazado con |
21
- |---|---|
22
- | `_ARTIFACT_CHANGE_EFFECT` con "may affect/inferred from role" | Labels estructurales: `"HTTP routing layer (request-to-handler mapping)"` |
23
- | `"type": "inferred"` en `_role_obj` | `{basis, has_annotation_signal, has_symbol_signal}` |
24
- | `"confidence": _f_conf` en runtime change entries | `"evidence_completeness"` del impact dict |
25
- | `_score_to_confidence()` function | Deleted completely |
26
- | `"confidence": score_band` en `impact_score_per_file` | `"evidence": {has_reverse_edges, has_route_diff, has_security_diff, has_wiring_evidence}` |
27
- | `behavioral_changes` sin graph evidence | Gateado en `has_graph_evidence == True` |
28
-
29
- ---
30
-
31
- ### Tarea 2 (sesión 13): Stable Symbol Identities
32
-
33
- **Ficheros:** `src/sourcecode/repository_ir.py`, `tests/test_repository_ir.py`
34
-
35
- **Nuevas funciones helper:**
36
- - `_normalize_type_name(raw)` — strip annotations/modifiers/param names → solo tipo
37
- - `_parse_param_types(params_str)` — `"Long id, String name"` → `["Long", "String"]` (depth-aware, maneja generics)
38
- - `_compute_stable_id(package, class_simple, kind, name, param_types, return_type)` — ID determinista
39
-
40
- **`SymbolRecord`** — 8 nuevos campos: `stable_id`, `symbol_kind`, `canonical_name`, `source_file`, `signature`, `param_types`, `return_type`, `annotation_values`
41
-
42
- **`symbol_kind` values:** `enum`, `annotation`, `endpoint`, `bean`, `constructor` (además de `class`, `interface`, `method`, `field`)
43
-
44
- **Formato stable_id:**
45
- ```
46
- {package}:{class_simple}:{kind}:{name}[:{(param_types)}[:{return_type}]]
47
- ```
48
-
49
- ---
50
-
51
- ### Tarea 3 (sesión 14): Spring Route-Surface Diffing
52
-
53
- **Ficheros:** `src/sourcecode/repository_ir.py`, `tests/test_repository_ir.py`
54
-
55
- **Qué se implementó:**
56
-
57
- | Componente | Cambio |
58
- |---|---|
59
- | `_ANN_WITH_ARGS_RE` | Captura args de anotaciones (`@GetMapping("/path")`) |
60
- | `SymbolRecord.annotation_values` | `dict[str, str]` — ann_name → raw args string |
61
- | `_HTTP_METHOD_MAP` | `@GetMapping → GET` etc. |
62
- | `_parse_route_path/http_method/extras` | Extraen path, method, produces/consumes |
63
- | `_is_route_symbol / _route_annotation_name / _enclosing_class` | Helpers de routes |
64
- | `_symbol_fingerprint` | Incluye valores de route annotations — cambio de path → fingerprint cambia |
65
- | `_diff_symbols` | Detecta `route_surface_change` antes de `annotation_change` genérico |
66
- | `_DIFF_INTENSITY_MAP` | `route_surface_change: 1.0` |
67
- | `_diff_routes` | Diff estructurado: old/new path, HTTP method, produces/consumes, evidence dict |
68
- | `_assemble` | Emite `route_surface: [...]` |
69
-
70
- **Output cuando route cambia:**
71
- ```json
72
- {
73
- "route_surface": [{
74
- "symbol": "com.example.HealthController#health",
75
- "controller": "com.example.HealthController",
76
- "route_surface_changed": true,
77
- "old_route": "/health",
78
- "new_route": "/health/v3",
79
- "stable_id": "com.example:HealthController:endpoint:health:():String",
80
- "evidence": {
81
- "annotation_value_changed": true,
82
- "mapping_annotation": "RequestMapping",
83
- "old_value": "/health",
84
- "new_value": "/health/v3"
85
- }
86
- }]
87
- }
88
- ```
89
-
90
- ---
91
-
92
- ### Tarea 4 (sesión 14): Reverse Impact Graph
93
-
94
- **Ficheros:** `src/sourcecode/repository_ir.py`, `tests/test_repository_ir.py`
95
-
96
- **Problema raíz resuelto:** `_propagate_impact` traversaba grafo hacia ADELANTE (si A cambia → impacta B que A usa). Incorrecto. Impact analysis necesita grafo INVERSO (si A cambia → impacta quién DEPENDE de A).
97
-
98
- **Qué se implementó:**
99
-
100
- | Componente | Cambio |
101
- |---|---|
102
- | `contained_in` edges | `_build_relations` emite `method/field → enclosing class` |
103
- | `_build_reverse_adjacency` | Invierte todas las relaciones (excluye `annotated_with`, `mapped_to`) |
104
- | `_EDGE_REASON_TEMPLATES` + `_edge_reason` | Edge → string legible |
105
- | `_bfs_impact_with_paths` | Reemplaza `_propagate_impact`. BFS en grafo inverso con path tracking |
106
- | `enclosing_seeds` param | Omite `contained_in` edges al sembrar desde clase enclosing para no incluir métodos hermanos |
107
- | `reverse_graph` en output | `{target_fqn: {edge_type: [from_fqn, ...]}}` — índice para agentes |
108
-
109
- **Cadena de propagación funcional:**
110
- ```
111
- UserRepository#findById cambia →
112
- [1] UserService ← "UserService depends on UserRepository (import)"
113
- [2] UserService#getUser ← "... is a member of UserService"
114
- [2] OrderController ← "OrderController depends on UserService (import)"
115
- [3] OrderController#getUser ← "... is a member of OrderController"
116
- ```
117
-
118
- `UserRepository#save` (hermano, sin cambios) correctamente excluido.
119
-
120
- **Cada entidad impactada expone:**
121
- ```json
122
- {
123
- "entity": "com.example.web.OrderController",
124
- "depth": 2,
125
- "impact_score": 0.0113,
126
- "via": "com.example.service.UserService",
127
- "graph_path": ["com.example.repo.UserRepository", "com.example.service.UserService", "com.example.web.OrderController"],
128
- "included_because": [
129
- "com.example.service.UserService depends on com.example.repo.UserRepository (import)",
130
- "com.example.web.OrderController depends on com.example.service.UserService (import)"
131
- ]
132
- }
133
- ```
134
-
135
- ---
136
-
137
- ## Estado de tests
138
-
139
- ```
140
- 920 passed, 3 skipped (era 885 antes de sesión 13)
141
- ```
142
-
143
- Pre-existing failures (no tocar):
144
- - `tests/test_block2_coverage.py` — bug `DocRecord` en `doc_analyzer.py`
145
- - `tests/test_dependency_analyzer_node_python.py::test_python_requirements_without_lockfile_keeps_declared_versions`
146
-
147
- ---
148
-
149
- ## Cambios sin commitear
150
-
151
- ```
152
- src/sourcecode/flow_analyzer.py | 22 +-
153
- src/sourcecode/prepare_context.py | 113 ++++---
154
- src/sourcecode/repository_ir.py | 522 +++++++++++++++++++++++++++++--
155
- tests/test_repository_ir.py | 635 +++++++++++++++++++++++++++++++++++++-
156
- ```
157
-
158
- **Para commitear TODO (primera acción al retomar):**
159
- ```bash
160
- cd /Users/user/Downloads/atlas-cli
161
- git add src/sourcecode/flow_analyzer.py \
162
- src/sourcecode/prepare_context.py \
163
- src/sourcecode/repository_ir.py \
164
- tests/test_repository_ir.py
165
-
166
- git commit -m "feat: stable IDs + route-surface diffing + reverse impact graph
167
-
168
- - Stable deterministic IDs for all symbol kinds (class/interface/enum/
169
- method/constructor/field/endpoint/bean) — survives formatting/body changes
170
- - symbol_kind, canonical_name, signature, annotation_values on all graph nodes
171
- - Replace heuristic confidence scoring with evidence completeness dicts
172
- - Remove speculative behavioral prose (may affect / inferred from role)
173
- - Gate behavioral_changes on has_graph_evidence
174
- - Route-surface diffing: annotation value changes detected as route_surface_change;
175
- evidence dict with old/new path, HTTP method, produces/consumes
176
- - Reverse impact graph: BFS on inverted graph; each impacted symbol carries
177
- graph_path + included_because explaining the dependency chain
178
- - contained_in edges expose method/field → class membership for propagation
179
- - reverse_graph output: {target: {edge_type: [from_fqns]}} for agent queries
180
- - 35 new acceptance tests (920 total passing)"
181
- ```
182
-
183
- ---
184
-
185
- ## Pendientes (próxima sesión)
186
-
187
- ### Prioridad alta
188
- 1. **Spring bean wiring graph** — `_build_relations` ya emite `injects` edges para `@Autowired` fields. Falta: trazar grafo completo `@Configuration → @Bean → @Autowired` y exponer como `wiring_graph` en IR output.
189
-
190
- 2. **Smoke test en repo spring-boot real:**
191
- ```bash
192
- cd ~/Documents/workspace/spring-boot-realworld-example-app
193
- sourcecode repo-ir . --since HEAD~1 2>/dev/null | python3 -c "
194
- import json, sys
195
- d = json.load(sys.stdin)
196
- print('schema:', d['schema_version'])
197
- print('nodes:', len(d['graph']['nodes']))
198
- print('route_surface:', d.get('route_surface', []))
199
- rg = d.get('reverse_graph', {})
200
- print('reverse_graph keys:', len(rg))
201
- "
202
- ```
203
-
204
- 3. **Transaction boundary tracking** — `@Transactional` ya detectado. Falta: emitir `transactional_boundary` edges.
205
-
206
- ### Prioridad media
207
- 4. **`_diff_routes` para `@RequestMapping` en clase** — si class-level mapping cambia (`/api/v1` → `/api/v2`), debería propagarse a todos los endpoints del controller.
208
-
209
- 5. **Tests unitarios para `_classify_diff_severity`** — sin cobertura
210
-
211
- ---
212
-
213
- ## Para retomar
214
-
215
- ```bash
216
- cd /Users/user/Downloads/atlas-cli
217
- git log --oneline -5 # último commit: 31aa91a
218
- git status # debe mostrar 4 ficheros modificados sin trackear
219
-
220
- python3 -m pytest tests/ \
221
- --ignore=tests/test_block2_coverage.py \
222
- --ignore=tests/test_dependency_analyzer_node_python.py \
223
- -q
224
- # Expected: 920 passed, 3 skipped
225
-
226
- # Primera acción: commitear (comando arriba)
227
- ```
228
-
229
- ---
230
-
231
- *Pausado 2026-05-17 sesión 14 — gsd:pause-work*