sourcecode 1.27.0__tar.gz → 1.28.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (191) hide show
  1. sourcecode-1.28.0/.continue-here.md +108 -0
  2. {sourcecode-1.27.0 → sourcecode-1.28.0}/PKG-INFO +3 -3
  3. {sourcecode-1.27.0 → sourcecode-1.28.0}/README.md +2 -2
  4. {sourcecode-1.27.0 → sourcecode-1.28.0}/pyproject.toml +1 -1
  5. {sourcecode-1.27.0 → sourcecode-1.28.0}/src/sourcecode/__init__.py +1 -1
  6. {sourcecode-1.27.0 → sourcecode-1.28.0}/src/sourcecode/prepare_context.py +3 -2
  7. sourcecode-1.28.0/tests/test_encoding_regression.py +138 -0
  8. sourcecode-1.27.0/.continue-here.md +0 -173
  9. sourcecode-1.27.0/tests/test_encoding_regression.py +0 -62
  10. {sourcecode-1.27.0 → sourcecode-1.28.0}/.agents/skills/source-command-gsd-join-discord/SKILL.md +0 -0
  11. {sourcecode-1.27.0 → sourcecode-1.28.0}/.agents/skills/source-command-gsd-review-backlog/SKILL.md +0 -0
  12. {sourcecode-1.27.0 → sourcecode-1.28.0}/.agents/skills/source-command-gsd-workstreams/SKILL.md +0 -0
  13. {sourcecode-1.27.0 → sourcecode-1.28.0}/.github/workflows/build-windows.yml +0 -0
  14. {sourcecode-1.27.0 → sourcecode-1.28.0}/.gitignore +0 -0
  15. {sourcecode-1.27.0 → sourcecode-1.28.0}/.ruff.toml +0 -0
  16. {sourcecode-1.27.0 → sourcecode-1.28.0}/CONTRIBUTING.md +0 -0
  17. {sourcecode-1.27.0 → sourcecode-1.28.0}/LICENSE +0 -0
  18. {sourcecode-1.27.0 → sourcecode-1.28.0}/SECURITY.md +0 -0
  19. {sourcecode-1.27.0 → sourcecode-1.28.0}/docs/privacy.md +0 -0
  20. {sourcecode-1.27.0 → sourcecode-1.28.0}/docs/schema.md +0 -0
  21. {sourcecode-1.27.0 → sourcecode-1.28.0}/raw +0 -0
  22. {sourcecode-1.27.0 → sourcecode-1.28.0}/run_cli.py +0 -0
  23. {sourcecode-1.27.0 → sourcecode-1.28.0}/src/sourcecode/adaptive_scanner.py +0 -0
  24. {sourcecode-1.27.0 → sourcecode-1.28.0}/src/sourcecode/architecture_analyzer.py +0 -0
  25. {sourcecode-1.27.0 → sourcecode-1.28.0}/src/sourcecode/architecture_summary.py +0 -0
  26. {sourcecode-1.27.0 → sourcecode-1.28.0}/src/sourcecode/ast_extractor.py +0 -0
  27. {sourcecode-1.27.0 → sourcecode-1.28.0}/src/sourcecode/classifier.py +0 -0
  28. {sourcecode-1.27.0 → sourcecode-1.28.0}/src/sourcecode/cli.py +0 -0
  29. {sourcecode-1.27.0 → sourcecode-1.28.0}/src/sourcecode/code_notes_analyzer.py +0 -0
  30. {sourcecode-1.27.0 → sourcecode-1.28.0}/src/sourcecode/confidence_analyzer.py +0 -0
  31. {sourcecode-1.27.0 → sourcecode-1.28.0}/src/sourcecode/context_scorer.py +0 -0
  32. {sourcecode-1.27.0 → sourcecode-1.28.0}/src/sourcecode/context_summarizer.py +0 -0
  33. {sourcecode-1.27.0 → sourcecode-1.28.0}/src/sourcecode/contract_model.py +0 -0
  34. {sourcecode-1.27.0 → sourcecode-1.28.0}/src/sourcecode/contract_pipeline.py +0 -0
  35. {sourcecode-1.27.0 → sourcecode-1.28.0}/src/sourcecode/coverage_parser.py +0 -0
  36. {sourcecode-1.27.0 → sourcecode-1.28.0}/src/sourcecode/dependency_analyzer.py +0 -0
  37. {sourcecode-1.27.0 → sourcecode-1.28.0}/src/sourcecode/detectors/__init__.py +0 -0
  38. {sourcecode-1.27.0 → sourcecode-1.28.0}/src/sourcecode/detectors/base.py +0 -0
  39. {sourcecode-1.27.0 → sourcecode-1.28.0}/src/sourcecode/detectors/csproj_parser.py +0 -0
  40. {sourcecode-1.27.0 → sourcecode-1.28.0}/src/sourcecode/detectors/dart.py +0 -0
  41. {sourcecode-1.27.0 → sourcecode-1.28.0}/src/sourcecode/detectors/dotnet.py +0 -0
  42. {sourcecode-1.27.0 → sourcecode-1.28.0}/src/sourcecode/detectors/elixir.py +0 -0
  43. {sourcecode-1.27.0 → sourcecode-1.28.0}/src/sourcecode/detectors/go.py +0 -0
  44. {sourcecode-1.27.0 → sourcecode-1.28.0}/src/sourcecode/detectors/heuristic.py +0 -0
  45. {sourcecode-1.27.0 → sourcecode-1.28.0}/src/sourcecode/detectors/hybrid.py +0 -0
  46. {sourcecode-1.27.0 → sourcecode-1.28.0}/src/sourcecode/detectors/java.py +0 -0
  47. {sourcecode-1.27.0 → sourcecode-1.28.0}/src/sourcecode/detectors/jvm_ext.py +0 -0
  48. {sourcecode-1.27.0 → sourcecode-1.28.0}/src/sourcecode/detectors/nodejs.py +0 -0
  49. {sourcecode-1.27.0 → sourcecode-1.28.0}/src/sourcecode/detectors/parsers.py +0 -0
  50. {sourcecode-1.27.0 → sourcecode-1.28.0}/src/sourcecode/detectors/php.py +0 -0
  51. {sourcecode-1.27.0 → sourcecode-1.28.0}/src/sourcecode/detectors/project.py +0 -0
  52. {sourcecode-1.27.0 → sourcecode-1.28.0}/src/sourcecode/detectors/python.py +0 -0
  53. {sourcecode-1.27.0 → sourcecode-1.28.0}/src/sourcecode/detectors/ruby.py +0 -0
  54. {sourcecode-1.27.0 → sourcecode-1.28.0}/src/sourcecode/detectors/rust.py +0 -0
  55. {sourcecode-1.27.0 → sourcecode-1.28.0}/src/sourcecode/detectors/systems.py +0 -0
  56. {sourcecode-1.27.0 → sourcecode-1.28.0}/src/sourcecode/detectors/terraform.py +0 -0
  57. {sourcecode-1.27.0 → sourcecode-1.28.0}/src/sourcecode/detectors/tooling.py +0 -0
  58. {sourcecode-1.27.0 → sourcecode-1.28.0}/src/sourcecode/doc_analyzer.py +0 -0
  59. {sourcecode-1.27.0 → sourcecode-1.28.0}/src/sourcecode/entrypoint_classifier.py +0 -0
  60. {sourcecode-1.27.0 → sourcecode-1.28.0}/src/sourcecode/env_analyzer.py +0 -0
  61. {sourcecode-1.27.0 → sourcecode-1.28.0}/src/sourcecode/file_classifier.py +0 -0
  62. {sourcecode-1.27.0 → sourcecode-1.28.0}/src/sourcecode/git_analyzer.py +0 -0
  63. {sourcecode-1.27.0 → sourcecode-1.28.0}/src/sourcecode/graph_analyzer.py +0 -0
  64. {sourcecode-1.27.0 → sourcecode-1.28.0}/src/sourcecode/metrics_analyzer.py +0 -0
  65. {sourcecode-1.27.0 → sourcecode-1.28.0}/src/sourcecode/progress.py +0 -0
  66. {sourcecode-1.27.0 → sourcecode-1.28.0}/src/sourcecode/ranking_engine.py +0 -0
  67. {sourcecode-1.27.0 → sourcecode-1.28.0}/src/sourcecode/redactor.py +0 -0
  68. {sourcecode-1.27.0 → sourcecode-1.28.0}/src/sourcecode/relevance_scorer.py +0 -0
  69. {sourcecode-1.27.0 → sourcecode-1.28.0}/src/sourcecode/repo_classifier.py +0 -0
  70. {sourcecode-1.27.0 → sourcecode-1.28.0}/src/sourcecode/runtime_classifier.py +0 -0
  71. {sourcecode-1.27.0 → sourcecode-1.28.0}/src/sourcecode/scanner.py +0 -0
  72. {sourcecode-1.27.0 → sourcecode-1.28.0}/src/sourcecode/schema.py +0 -0
  73. {sourcecode-1.27.0 → sourcecode-1.28.0}/src/sourcecode/semantic_analyzer.py +0 -0
  74. {sourcecode-1.27.0 → sourcecode-1.28.0}/src/sourcecode/serializer.py +0 -0
  75. {sourcecode-1.27.0 → sourcecode-1.28.0}/src/sourcecode/summarizer.py +0 -0
  76. {sourcecode-1.27.0 → sourcecode-1.28.0}/src/sourcecode/telemetry/__init__.py +0 -0
  77. {sourcecode-1.27.0 → sourcecode-1.28.0}/src/sourcecode/telemetry/config.py +0 -0
  78. {sourcecode-1.27.0 → sourcecode-1.28.0}/src/sourcecode/telemetry/consent.py +0 -0
  79. {sourcecode-1.27.0 → sourcecode-1.28.0}/src/sourcecode/telemetry/events.py +0 -0
  80. {sourcecode-1.27.0 → sourcecode-1.28.0}/src/sourcecode/telemetry/filters.py +0 -0
  81. {sourcecode-1.27.0 → sourcecode-1.28.0}/src/sourcecode/telemetry/transport.py +0 -0
  82. {sourcecode-1.27.0 → sourcecode-1.28.0}/src/sourcecode/tree_utils.py +0 -0
  83. {sourcecode-1.27.0 → sourcecode-1.28.0}/src/sourcecode/workspace.py +0 -0
  84. {sourcecode-1.27.0 → sourcecode-1.28.0}/tests/__init__.py +0 -0
  85. {sourcecode-1.27.0 → sourcecode-1.28.0}/tests/conftest.py +0 -0
  86. {sourcecode-1.27.0 → sourcecode-1.28.0}/tests/fixtures/coverage.xml +0 -0
  87. {sourcecode-1.27.0 → sourcecode-1.28.0}/tests/fixtures/fastapi_app/pyproject.toml +0 -0
  88. {sourcecode-1.27.0 → sourcecode-1.28.0}/tests/fixtures/fastapi_app/src/main.py +0 -0
  89. {sourcecode-1.27.0 → sourcecode-1.28.0}/tests/fixtures/go_service/cmd/api/main.go +0 -0
  90. {sourcecode-1.27.0 → sourcecode-1.28.0}/tests/fixtures/go_service/go.mod +0 -0
  91. {sourcecode-1.27.0 → sourcecode-1.28.0}/tests/fixtures/jacoco.xml +0 -0
  92. {sourcecode-1.27.0 → sourcecode-1.28.0}/tests/fixtures/latin1_sample.java +0 -0
  93. {sourcecode-1.27.0 → sourcecode-1.28.0}/tests/fixtures/latin1_sample_iso.java +0 -0
  94. {sourcecode-1.27.0 → sourcecode-1.28.0}/tests/fixtures/lcov.info +0 -0
  95. {sourcecode-1.27.0 → sourcecode-1.28.0}/tests/fixtures/nextjs_app/app/page.tsx +0 -0
  96. {sourcecode-1.27.0 → sourcecode-1.28.0}/tests/fixtures/nextjs_app/package.json +0 -0
  97. {sourcecode-1.27.0 → sourcecode-1.28.0}/tests/fixtures/nextjs_app/pnpm-lock.yaml +0 -0
  98. {sourcecode-1.27.0 → sourcecode-1.28.0}/tests/fixtures/pnpm_monorepo/apps/web/app/page.tsx +0 -0
  99. {sourcecode-1.27.0 → sourcecode-1.28.0}/tests/fixtures/pnpm_monorepo/apps/web/package.json +0 -0
  100. {sourcecode-1.27.0 → sourcecode-1.28.0}/tests/fixtures/pnpm_monorepo/packages/api/main.py +0 -0
  101. {sourcecode-1.27.0 → sourcecode-1.28.0}/tests/fixtures/pnpm_monorepo/packages/api/pyproject.toml +0 -0
  102. {sourcecode-1.27.0 → sourcecode-1.28.0}/tests/fixtures/pnpm_monorepo/pnpm-workspace.yaml +0 -0
  103. {sourcecode-1.27.0 → sourcecode-1.28.0}/tests/fixtures/spring_boot_minimal/pom.xml +0 -0
  104. {sourcecode-1.27.0 → sourcecode-1.28.0}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/ausente/application/service/FindAusenteService.java +0 -0
  105. {sourcecode-1.27.0 → sourcecode-1.28.0}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/ausente/domain/entities/Ausente.java +0 -0
  106. {sourcecode-1.27.0 → sourcecode-1.28.0}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/ausente/infrastructure/rest/AusenteRestController.java +0 -0
  107. {sourcecode-1.27.0 → sourcecode-1.28.0}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/autocoberturas/application/service/FindAutocoberturasService.java +0 -0
  108. {sourcecode-1.27.0 → sourcecode-1.28.0}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/autocoberturas/domain/entities/Autocoberturas.java +0 -0
  109. {sourcecode-1.27.0 → sourcecode-1.28.0}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/autocoberturas/infrastructure/rest/AutocoberturasRestController.java +0 -0
  110. {sourcecode-1.27.0 → sourcecode-1.28.0}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/calendarioTrabajador/application/service/FindCalendarioTrabajadorService.java +0 -0
  111. {sourcecode-1.27.0 → sourcecode-1.28.0}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/calendarioTrabajador/domain/entities/CalendarioTrabajador.java +0 -0
  112. {sourcecode-1.27.0 → sourcecode-1.28.0}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/calendarioTrabajador/infrastructure/rest/CalendarioTrabajadorRestController.java +0 -0
  113. {sourcecode-1.27.0 → sourcecode-1.28.0}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/departamento/application/service/FindDepartamentoService.java +0 -0
  114. {sourcecode-1.27.0 → sourcecode-1.28.0}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/departamento/domain/entities/Departamento.java +0 -0
  115. {sourcecode-1.27.0 → sourcecode-1.28.0}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/departamento/infrastructure/rest/DepartamentoRestController.java +0 -0
  116. {sourcecode-1.27.0 → sourcecode-1.28.0}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/empleado/application/service/FindEmpleadoService.java +0 -0
  117. {sourcecode-1.27.0 → sourcecode-1.28.0}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/empleado/domain/entities/Empleado.java +0 -0
  118. {sourcecode-1.27.0 → sourcecode-1.28.0}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/empleado/infrastructure/rest/EmpleadoRestController.java +0 -0
  119. {sourcecode-1.27.0 → sourcecode-1.28.0}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/demo/DemoApplication.java +0 -0
  120. {sourcecode-1.27.0 → sourcecode-1.28.0}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/demo/config/FilterConfig.java +0 -0
  121. {sourcecode-1.27.0 → sourcecode-1.28.0}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/demo/domain/Health.java +0 -0
  122. {sourcecode-1.27.0 → sourcecode-1.28.0}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/demo/mapper/HealthMapper.java +0 -0
  123. {sourcecode-1.27.0 → sourcecode-1.28.0}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/demo/repository/HealthRepository.java +0 -0
  124. {sourcecode-1.27.0 → sourcecode-1.28.0}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/demo/service/HealthService.java +0 -0
  125. {sourcecode-1.27.0 → sourcecode-1.28.0}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/demo/web/HealthRestController.java +0 -0
  126. {sourcecode-1.27.0 → sourcecode-1.28.0}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/demo/web/NominaRestController.java +0 -0
  127. {sourcecode-1.27.0 → sourcecode-1.28.0}/tests/fixtures/spring_boot_minimal/src/main/resources/application-dev.yml +0 -0
  128. {sourcecode-1.27.0 → sourcecode-1.28.0}/tests/fixtures/spring_boot_minimal/src/main/resources/application.yml +0 -0
  129. {sourcecode-1.27.0 → sourcecode-1.28.0}/tests/fixtures/spring_boot_minimal/src/main/resources/mapper/HealthMapper.xml +0 -0
  130. {sourcecode-1.27.0 → sourcecode-1.28.0}/tests/test_architecture_analyzer.py +0 -0
  131. {sourcecode-1.27.0 → sourcecode-1.28.0}/tests/test_architecture_summary.py +0 -0
  132. {sourcecode-1.27.0 → sourcecode-1.28.0}/tests/test_ast_extractor.py +0 -0
  133. {sourcecode-1.27.0 → sourcecode-1.28.0}/tests/test_block1_reliability.py +0 -0
  134. {sourcecode-1.27.0 → sourcecode-1.28.0}/tests/test_block2_coverage.py +0 -0
  135. {sourcecode-1.27.0 → sourcecode-1.28.0}/tests/test_block5_quality.py +0 -0
  136. {sourcecode-1.27.0 → sourcecode-1.28.0}/tests/test_bug_fixes_v16.py +0 -0
  137. {sourcecode-1.27.0 → sourcecode-1.28.0}/tests/test_classifier.py +0 -0
  138. {sourcecode-1.27.0 → sourcecode-1.28.0}/tests/test_cli.py +0 -0
  139. {sourcecode-1.27.0 → sourcecode-1.28.0}/tests/test_code_notes_analyzer.py +0 -0
  140. {sourcecode-1.27.0 → sourcecode-1.28.0}/tests/test_context_scorer.py +0 -0
  141. {sourcecode-1.27.0 → sourcecode-1.28.0}/tests/test_contract_pipeline.py +0 -0
  142. {sourcecode-1.27.0 → sourcecode-1.28.0}/tests/test_coverage_parser.py +0 -0
  143. {sourcecode-1.27.0 → sourcecode-1.28.0}/tests/test_cross_consistency.py +0 -0
  144. {sourcecode-1.27.0 → sourcecode-1.28.0}/tests/test_dependency_analyzer_node_python.py +0 -0
  145. {sourcecode-1.27.0 → sourcecode-1.28.0}/tests/test_dependency_analyzer_polyglot.py +0 -0
  146. {sourcecode-1.27.0 → sourcecode-1.28.0}/tests/test_dependency_schema.py +0 -0
  147. {sourcecode-1.27.0 → sourcecode-1.28.0}/tests/test_detector_dotnet.py +0 -0
  148. {sourcecode-1.27.0 → sourcecode-1.28.0}/tests/test_detector_go_rust_java.py +0 -0
  149. {sourcecode-1.27.0 → sourcecode-1.28.0}/tests/test_detector_nodejs.py +0 -0
  150. {sourcecode-1.27.0 → sourcecode-1.28.0}/tests/test_detector_php_ruby_dart.py +0 -0
  151. {sourcecode-1.27.0 → sourcecode-1.28.0}/tests/test_detector_python.py +0 -0
  152. {sourcecode-1.27.0 → sourcecode-1.28.0}/tests/test_detector_universal_managed.py +0 -0
  153. {sourcecode-1.27.0 → sourcecode-1.28.0}/tests/test_detector_universal_systems.py +0 -0
  154. {sourcecode-1.27.0 → sourcecode-1.28.0}/tests/test_detectors_base.py +0 -0
  155. {sourcecode-1.27.0 → sourcecode-1.28.0}/tests/test_doc_analyzer_jsdom.py +0 -0
  156. {sourcecode-1.27.0 → sourcecode-1.28.0}/tests/test_doc_analyzer_python.py +0 -0
  157. {sourcecode-1.27.0 → sourcecode-1.28.0}/tests/test_graph_analyzer_polyglot.py +0 -0
  158. {sourcecode-1.27.0 → sourcecode-1.28.0}/tests/test_graph_analyzer_python_node.py +0 -0
  159. {sourcecode-1.27.0 → sourcecode-1.28.0}/tests/test_graph_schema.py +0 -0
  160. {sourcecode-1.27.0 → sourcecode-1.28.0}/tests/test_hybrid_inference.py +0 -0
  161. {sourcecode-1.27.0 → sourcecode-1.28.0}/tests/test_integration.py +0 -0
  162. {sourcecode-1.27.0 → sourcecode-1.28.0}/tests/test_integration_dependencies.py +0 -0
  163. {sourcecode-1.27.0 → sourcecode-1.28.0}/tests/test_integration_detection.py +0 -0
  164. {sourcecode-1.27.0 → sourcecode-1.28.0}/tests/test_integration_docs.py +0 -0
  165. {sourcecode-1.27.0 → sourcecode-1.28.0}/tests/test_integration_graph_modules.py +0 -0
  166. {sourcecode-1.27.0 → sourcecode-1.28.0}/tests/test_integration_lqn.py +0 -0
  167. {sourcecode-1.27.0 → sourcecode-1.28.0}/tests/test_integration_metrics.py +0 -0
  168. {sourcecode-1.27.0 → sourcecode-1.28.0}/tests/test_integration_multistack.py +0 -0
  169. {sourcecode-1.27.0 → sourcecode-1.28.0}/tests/test_integration_semantics.py +0 -0
  170. {sourcecode-1.27.0 → sourcecode-1.28.0}/tests/test_integration_universal.py +0 -0
  171. {sourcecode-1.27.0 → sourcecode-1.28.0}/tests/test_java_spring_integration.py +0 -0
  172. {sourcecode-1.27.0 → sourcecode-1.28.0}/tests/test_metrics_analyzer.py +0 -0
  173. {sourcecode-1.27.0 → sourcecode-1.28.0}/tests/test_packaging.py +0 -0
  174. {sourcecode-1.27.0 → sourcecode-1.28.0}/tests/test_phase1_improvements.py +0 -0
  175. {sourcecode-1.27.0 → sourcecode-1.28.0}/tests/test_pipeline_integrity.py +0 -0
  176. {sourcecode-1.27.0 → sourcecode-1.28.0}/tests/test_real_projects.py +0 -0
  177. {sourcecode-1.27.0 → sourcecode-1.28.0}/tests/test_redactor.py +0 -0
  178. {sourcecode-1.27.0 → sourcecode-1.28.0}/tests/test_scanner.py +0 -0
  179. {sourcecode-1.27.0 → sourcecode-1.28.0}/tests/test_schema.py +0 -0
  180. {sourcecode-1.27.0 → sourcecode-1.28.0}/tests/test_schema_normalization.py +0 -0
  181. {sourcecode-1.27.0 → sourcecode-1.28.0}/tests/test_semantic_analyzer_node.py +0 -0
  182. {sourcecode-1.27.0 → sourcecode-1.28.0}/tests/test_semantic_analyzer_python.py +0 -0
  183. {sourcecode-1.27.0 → sourcecode-1.28.0}/tests/test_semantic_import_resolution.py +0 -0
  184. {sourcecode-1.27.0 → sourcecode-1.28.0}/tests/test_semantic_schema.py +0 -0
  185. {sourcecode-1.27.0 → sourcecode-1.28.0}/tests/test_signal_hierarchy.py +0 -0
  186. {sourcecode-1.27.0 → sourcecode-1.28.0}/tests/test_summarizer.py +0 -0
  187. {sourcecode-1.27.0 → sourcecode-1.28.0}/tests/test_surface_honesty.py +0 -0
  188. {sourcecode-1.27.0 → sourcecode-1.28.0}/tests/test_task_differentiation.py +0 -0
  189. {sourcecode-1.27.0 → sourcecode-1.28.0}/tests/test_telemetry.py +0 -0
  190. {sourcecode-1.27.0 → sourcecode-1.28.0}/tests/test_v1_10_regressions.py +0 -0
  191. {sourcecode-1.27.0 → sourcecode-1.28.0}/tests/test_workspace_analyzer.py +0 -0
@@ -0,0 +1,108 @@
1
+ # Continue Here — atlas-cli --agent token reduction
2
+
3
+ **Paused:** 2026-05-16 (sesión 4)
4
+ **Repo:** `/Users/user/Downloads/atlas-cli`
5
+ **Branch:** master
6
+ **Commit:** `f1cb001 corrigiendo bug --agent que duplicaba tokens sin justificación` (committed)
7
+
8
+ ---
9
+
10
+ ## Estado actual
11
+
12
+ Sesión 4: refactorización de `agent_view()` en `serializer.py` completada. **Todo committed.** Working tree limpio.
13
+
14
+ ---
15
+
16
+ ## Qué se hizo esta sesión
17
+
18
+ ### Problema resuelto
19
+
20
+ `--agent` producía ~11.337 tokens en SAS vs ~5.885 de `--compact`, con contenido casi idéntico. Objetivo: reducir tokens significativamente manteniendo solo lo que diferencia `--agent`.
21
+
22
+ ### Cambios en `agent_view()` (`src/sourcecode/serializer.py`)
23
+
24
+ | Cambio | Impacto |
25
+ |--------|---------|
26
+ | Elimina `production_dependencies` / `dev_tools` / `test_utilities` / `build_tooling` (dep_groups asdict completo) | Mayor fuente de bloat: -3.000-5.000 tokens en repos grandes |
27
+ | `key_dependencies`: de asdict+50 items → `name+version+role+risk_flags` solo, cap 20 | -500-1.500 tokens |
28
+ | Elimina `confidence_summary.hard_signals` / `soft_signals` / `ignored_signals` | -500-1.000 tokens |
29
+ | Elimina bloque `agent_mode` (contenido estático sin señal) | -80 tokens siempre |
30
+ | Elimina `signals.env_vars.keys[]` (duplica compact `env_map`) | -300-500 tokens |
31
+ | `signals.code_notes.top` cap 10→5, strip a `kind+path+line+text` | -200 tokens |
32
+ | Entry points (no-bootstrap): strip a `path+kind+confidence` (como compact) | reducción moderada |
33
+ | Elimina `development_entry_points` (noise para agentes de producción) | pequeña |
34
+ | `architecture.layers` capado a 5 | pequeña |
35
+
36
+ **Reducción estimada para SAS:** −40–60% tokens vs `--agent` anterior.
37
+
38
+ ### Campos que permanecen únicos de `--agent`
39
+
40
+ | Campo | Por qué justifica tokens extra vs `--compact` |
41
+ |-------|----------------------------------------------|
42
+ | `file_relevance` (top-20 scored) | Compact no tiene equivalente. Agente sabe qué leer sin explorar. |
43
+ | `architecture.layers` | Compact solo tiene `architecture_summary` string. |
44
+ | `suspicious_dependencies` | Deps declarados sin import observado. Compact no lo tiene. |
45
+ | `confidence_reasons` | Explicación accionable de secciones low-confidence. Compact no lo tiene. |
46
+
47
+ ### Tests actualizados
48
+
49
+ - `tests/test_block5_quality.py` — 5 tests de `agent_mode` reemplazados por tests de las nuevas garantías (no `agent_mode`, no `hard_signals`, no `env_vars.keys`, no dep_groups)
50
+ - `tests/test_pipeline_integrity.py` — `test_agent_splits_development_and_auxiliary_eps` → verifica que dev/aux EPs NO aparecen
51
+
52
+ ---
53
+
54
+ ## Tests al pausar
55
+
56
+ Suite completa (sin fallos pre-existentes): **todo verde**
57
+
58
+ Fallos pre-existentes (no relacionados, ya presentes antes):
59
+ - `test_block2_coverage.py::test_java_marked_unsupported` — DocRecord bug en doc_analyzer.py
60
+ - `test_dependency_analyzer_node_python.py::test_python_requirements_without_lockfile` — versión typer mismatch
61
+
62
+ ---
63
+
64
+ ## Pendiente / próximos pasos opcionales
65
+
66
+ 1. **Smoke test en saint-server** para medir tokens reales antes/después:
67
+ ```bash
68
+ sourcecode saint-server --agent --output /tmp/agent_new.json
69
+ python3 -c "import json,sys; d=json.load(open('/tmp/agent_new.json')); print('agent tokens (est):', len(json.dumps(d))//4)"
70
+ ```
71
+
72
+ 2. **Verificar que `suspicious_dependencies` es útil en repos reales** — en repos Python/JS (no JVM, donde el index de imports no funciona). En JVM siempre vacío por diseño.
73
+
74
+ 3. **Ajustar caps según medición real**: si `file_relevance` (20 files) sigue siendo el mayor contribuyente de tokens, considerar reducir a 15. Medir con `--full` vs default.
75
+
76
+ 4. **Smoke tests delta pendientes** de sesión anterior — ver sección "Smoke tests sesión 3" en historial de commits.
77
+
78
+ ---
79
+
80
+ ## Para retomar
81
+
82
+ ```bash
83
+ cd /Users/user/Downloads/atlas-cli
84
+ git log --oneline -3
85
+ # debe mostrar: f1cb001 corrigiendo bug --agent que duplicaba tokens sin justificación
86
+
87
+ python3 -m pytest tests/ \
88
+ --ignore=tests/test_block2_coverage.py \
89
+ --deselect=tests/test_dependency_analyzer_node_python.py::test_python_requirements_without_lockfile_keeps_declared_versions \
90
+ -q
91
+ # Expected: todo verde
92
+
93
+ # Verificación rápida agent_view
94
+ python3 -c "
95
+ from sourcecode.serializer import agent_view
96
+ from sourcecode.schema import SourceMap, StackInfo, SourceMapMetadata
97
+ sm = SourceMap(stacks=[StackInfo(stack='python', primary=True)], project_type='python', project_summary='test')
98
+ r = agent_view(sm)
99
+ assert 'agent_mode' not in r
100
+ assert 'production_dependencies' not in r
101
+ assert 'hard_signals' not in r.get('confidence_summary', {})
102
+ print('OK — agent_mode/dep_groups/hard_signals all absent')
103
+ "
104
+ ```
105
+
106
+ ---
107
+
108
+ *Pausado 2026-05-16 sesión 4 — gsd:pause-work*
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: sourcecode
3
- Version: 1.27.0
3
+ Version: 1.28.0
4
4
  Summary: Deterministic codebase context for AI coding agents
5
5
  License: Apache License
6
6
  Version 2.0, January 2004
@@ -221,7 +221,7 @@ Description-Content-Type: text/markdown
221
221
 
222
222
  **Compressed AI-ready context for Java/Spring enterprise codebases.**
223
223
 
224
- ![Version](https://img.shields.io/badge/version-1.27.0-blue)
224
+ ![Version](https://img.shields.io/badge/version-1.28.0-blue)
225
225
  ![Python](https://img.shields.io/badge/python-3.10%2B-green)
226
226
 
227
227
  ---
@@ -255,7 +255,7 @@ pipx install sourcecode
255
255
 
256
256
  ```bash
257
257
  sourcecode version
258
- # sourcecode 1.27.0
258
+ # sourcecode 1.28.0
259
259
  ```
260
260
 
261
261
  ---
@@ -2,7 +2,7 @@
2
2
 
3
3
  **Compressed AI-ready context for Java/Spring enterprise codebases.**
4
4
 
5
- ![Version](https://img.shields.io/badge/version-1.27.0-blue)
5
+ ![Version](https://img.shields.io/badge/version-1.28.0-blue)
6
6
  ![Python](https://img.shields.io/badge/python-3.10%2B-green)
7
7
 
8
8
  ---
@@ -36,7 +36,7 @@ pipx install sourcecode
36
36
 
37
37
  ```bash
38
38
  sourcecode version
39
- # sourcecode 1.27.0
39
+ # sourcecode 1.28.0
40
40
  ```
41
41
 
42
42
  ---
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "sourcecode"
7
- version = "1.27.0"
7
+ version = "1.28.0"
8
8
  description = "Deterministic codebase context for AI coding agents"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.9"
@@ -1,3 +1,3 @@
1
1
  """sourcecode — Deterministic codebase context maps for AI coding agents."""
2
2
 
3
- __version__ = "1.27.0"
3
+ __version__ = "1.28.0"
@@ -2309,10 +2309,11 @@ class TaskContextBuilder:
2309
2309
  r = subprocess.run(
2310
2310
  ["git", "branch", "-a", "--format=%(refname:short)"],
2311
2311
  cwd=str(self.root),
2312
- capture_output=True, text=True, timeout=5,
2312
+ capture_output=True, text=True,
2313
+ encoding="utf-8", errors="replace", timeout=5,
2313
2314
  )
2314
2315
  if r.returncode == 0:
2315
- all_refs = [b.strip() for b in r.stdout.splitlines() if b.strip()]
2316
+ all_refs = [b.strip() for b in (r.stdout or "").splitlines() if b.strip()]
2316
2317
  branches = [b for b in all_refs if "HEAD" not in b][:10]
2317
2318
  ref_lower = invalid_ref.lower()
2318
2319
  if ref_lower == "master" and any(b.rstrip("/").endswith("main") for b in all_refs):
@@ -0,0 +1,138 @@
1
+ """Regression tests for C3 — UTF-8 double-encoding of accented characters.
2
+
3
+ Fixture files:
4
+ - tests/fixtures/latin1_sample_iso.java — Latin-1 encoded (bytes 0xe1, 0xf3, etc.)
5
+ - tests/fixtures/latin1_sample.java — UTF-8 encoded (multibyte sequences)
6
+
7
+ Both should decode cleanly to the correct Unicode characters.
8
+ The old code read Latin-1 files with errors='replace', producing double-encoded garbage.
9
+ """
10
+ from __future__ import annotations
11
+
12
+ from pathlib import Path
13
+
14
+ import pytest
15
+
16
+ from sourcecode.tree_utils import safe_read_text
17
+
18
+ FIXTURES = Path(__file__).parent / "fixtures"
19
+ LATIN1_FILE = FIXTURES / "latin1_sample_iso.java"
20
+ UTF8_FILE = FIXTURES / "latin1_sample.java"
21
+
22
+
23
+ class TestSafeReadText:
24
+ """safe_read_text must decode both UTF-8 and Latin-1 files correctly."""
25
+
26
+ def test_utf8_file_reads_correctly(self):
27
+ content = safe_read_text(UTF8_FILE)
28
+ # These characters must appear verbatim — not as double-encoded sequences
29
+ assert "días" in content, f"Expected 'días', got: {content[:200]!r}"
30
+ assert "ñ" in content or "función" in content or "ñoño" in content
31
+ assert "Ã" not in content, "Double-encoded: U+00C3 found (Ã). Encoding was mangled."
32
+
33
+ def test_latin1_file_reads_correctly(self):
34
+ content = safe_read_text(LATIN1_FILE)
35
+ # Latin-1 0xe1 = 'á' — must decode to the correct character
36
+ assert "á" in content, f"Expected 'á', got: {content!r}"
37
+ assert "ó" in content, f"Expected 'ó', got: {content!r}"
38
+ # No replacement chars
39
+ assert "�" not in content, "Replacement character found — file was not decoded correctly."
40
+ # No double-encoding: 'á' in double-encoded UTF-8-as-Latin-1 would appear as 'á'
41
+ assert "Ã" not in content, "Double-encoded: U+00C3 found (Ã). Latin-1 file was not decoded correctly."
42
+
43
+ def test_nonexistent_file_raises_oserror(self):
44
+ with pytest.raises(OSError):
45
+ safe_read_text(FIXTURES / "does_not_exist.java")
46
+
47
+
48
+ class TestCodeNotesEncoding:
49
+ """CodeNotesAnalyzer must extract notes from Latin-1 files without encoding corruption."""
50
+
51
+ def test_latin1_todo_extracted_cleanly(self):
52
+ from sourcecode.code_notes_analyzer import CodeNotesAnalyzer
53
+
54
+ # analyze() scans FIXTURES dir — Latin-1 file is there
55
+ analyzer = CodeNotesAnalyzer()
56
+ notes, _, _ = analyzer.analyze(FIXTURES)
57
+ # Should have extracted TODO without replacement chars
58
+ todo_texts = [n.text for n in notes if "latin1_sample_iso" in n.path]
59
+ for text in todo_texts:
60
+ assert "â" not in text, f"Double-encoded byte found in TODO text: {text!r}"
61
+ assert "Ã" not in text, f"Double-encoded char in TODO text: {text!r}"
62
+ assert "�" not in text, f"Replacement char in TODO text: {text!r}"
63
+
64
+
65
+ class TestGetAvailableRefsWindowsEncoding:
66
+ """Regression: _get_available_refs crashed on Windows due to cp1252 encoding and None stdout.
67
+
68
+ Bug: subprocess.run(text=True) without encoding= uses the OS default (cp1252 on Windows).
69
+ Git output containing byte 0x8d raises UnicodeDecodeError (not caught). If stdout is None,
70
+ r.stdout.splitlines() raises AttributeError. Both cause unhandled tracebacks.
71
+ Fix: encoding="utf-8", errors="replace", and (r.stdout or "").splitlines().
72
+ """
73
+
74
+ def _make_builder(self) -> "TaskContextBuilder":
75
+ from sourcecode.prepare_context import TaskContextBuilder
76
+ return TaskContextBuilder(FIXTURES)
77
+
78
+ def test_case_a_stdout_none_does_not_crash(self, monkeypatch):
79
+ """stdout=None must not raise AttributeError on splitlines()."""
80
+ import subprocess
81
+ import types
82
+
83
+ fake = types.SimpleNamespace(returncode=0, stdout=None, stderr="")
84
+ monkeypatch.setattr(subprocess, "run", lambda *a, **kw: fake)
85
+
86
+ builder = self._make_builder()
87
+ refs, suggested = builder._get_available_refs("main")
88
+ assert refs == []
89
+ assert suggested is None
90
+
91
+ def test_case_b_non_utf8_bytes_no_unicode_error(self, monkeypatch):
92
+ """Bytes invalid in cp1252 (e.g. 0x8d) must not raise UnicodeDecodeError.
93
+
94
+ With encoding='utf-8' + errors='replace', replacement chars appear instead.
95
+ """
96
+ import subprocess
97
+ import types
98
+
99
+ # Simulate git returning a branch name that survived errors="replace" decoding
100
+ # (the replacement char � stands in for the bad byte)
101
+ replaced = "develop\nfeature/caf�\n"
102
+ fake = types.SimpleNamespace(returncode=0, stdout=replaced, stderr="")
103
+ monkeypatch.setattr(subprocess, "run", lambda *a, **kw: fake)
104
+
105
+ builder = self._make_builder()
106
+ refs, _ = builder._get_available_refs("main")
107
+ assert "develop" in refs
108
+
109
+ def test_case_c_nonexistent_ref_returns_available_refs(self, monkeypatch):
110
+ """Non-existent --since ref must yield a list of available branches, not a crash."""
111
+ import subprocess
112
+ import types
113
+
114
+ fake = types.SimpleNamespace(
115
+ returncode=0,
116
+ stdout="develop\norigin/develop\nrelease/1.2\n",
117
+ stderr="",
118
+ )
119
+ monkeypatch.setattr(subprocess, "run", lambda *a, **kw: fake)
120
+
121
+ builder = self._make_builder()
122
+ refs, suggested = builder._get_available_refs("main")
123
+ assert "develop" in refs
124
+ # invalid_ref="main", all_refs contains no "master" → no suggestion
125
+ assert suggested is None
126
+
127
+ def test_case_d_nonzero_returncode_returns_empty(self, monkeypatch):
128
+ """returncode != 0 must not parse stdout — returns empty list silently."""
129
+ import subprocess
130
+ import types
131
+
132
+ fake = types.SimpleNamespace(returncode=128, stdout="fatal: not a git repo\n", stderr="")
133
+ monkeypatch.setattr(subprocess, "run", lambda *a, **kw: fake)
134
+
135
+ builder = self._make_builder()
136
+ refs, suggested = builder._get_available_refs("main")
137
+ assert refs == []
138
+ assert suggested is None
@@ -1,173 +0,0 @@
1
- # Continue Here — atlas-cli delta engine overhaul
2
-
3
- **Paused:** 2026-05-13 (sesión 3)
4
- **Repo:** `/Users/user/Downloads/atlas-cli`
5
- **Branch:** master
6
- **Commit:** `8258c4c implementando delta` (committed, pushed to origin/master)
7
-
8
- ---
9
-
10
- ## Estado actual
11
-
12
- Sesión 3: `prepare-context delta` completamente reimplementado como motor de contexto incremental real. **Todo committed y pusheado.** Working tree limpio (solo este fichero untracked).
13
-
14
- ---
15
-
16
- ## Qué se implementó esta sesión
17
-
18
- ### Motor delta real (`_build_delta_impact`)
19
-
20
- Reemplaza el uso de `_rank_files` para la tarea `delta`. Nuevo flujo:
21
-
22
- 1. **`_classify_changed_file(path)`** — clasificador estático determinista por ruta/nombre:
23
- - Tipos: `security`, `api_endpoint`, `business_logic`, `data_access`, `mybatis_mapper`, `spring_config`, `spring_profile`, `configuration`, `build_manifest`, `db_migration`, `domain_model`, `dto`, `test`, `ide_noise`, `unknown_source`, `unknown_config`, `documentation`
24
- - Impacto: `critical / high / medium / low / noise`
25
- - Áreas de riesgo: `security`, `api`, `transactions`, `business_logic`, `persistence`, `config`, `dependencies`, `tests`
26
- - `.idea/`, `.vscode/`, etc. → `ide_noise`, `is_noise=True`
27
-
28
- 2. **`_build_delta_impact(changed_files, all_paths, entry_points, since)`** — análisis de impacto:
29
- - Changed files siempre incluidos en `relevant_files` (nunca filtrados por score)
30
- - Expansión a ficheros relacionados: mismo módulo DDD o mismo directorio padre
31
- - Solo expande a stems de alto impacto (controller, service, repository, mapper, security, config)
32
- - Límite: 10 ficheros relacionados máximo
33
- - Returns: `(relevant_files, impact_summary, affected_modules, risk_areas, why, analysis_gaps)`
34
-
35
- 3. **Nuevos campos en `TaskOutput`** (delta only):
36
- - `impact_summary: str` — resumen textual del impacto global
37
- - `affected_modules: list[str]` — módulos DDD afectados
38
- - `risk_areas: list[dict]` — por área con severity y ficheros
39
- - `since: str` — ref usada
40
-
41
- 4. **Nuevo output delta** (cli.py):
42
- - `project_summary` suprimido (change-focused, no snapshot)
43
- - `gaps` habilitado (delta-specific gaps, no ConfidenceAnalyzer gaps)
44
- - Serializa: `since`, `impact_summary`, `affected_modules`, `risk_areas`, `reasoning`
45
-
46
- ### Bugs corregidos
47
-
48
- | Bug | Fix |
49
- |-----|-----|
50
- | `relevant_files: []` con cambios reales | Changed files usan `_build_delta_impact`, no `_rank_files`. Nunca filtrados por score. |
51
- | `.idea/vcs.xml` → `relevant_files: []` | Clasificado como `ide_noise`, score=0.1, role="noise". Aparece con mensaje explicativo. |
52
- | Output idéntico a `--compact` | Delta ya no llama `_rank_files` — lógica completamente separada. |
53
- | `relevant_files` genérico sin relación al diff | Ahora construye desde changed_files hacia afuera, no desde entrypoints hacia adentro. |
54
-
55
- ---
56
-
57
- ## Ficheros modificados esta sesión
58
-
59
- ```
60
- src/sourcecode/prepare_context.py +_classify_changed_file, +_build_delta_impact, +TaskOutput fields, build() delta branch
61
- src/sourcecode/cli.py delta content filter: project_summary=False, gaps=True, new fields serialized
62
- tests/test_signal_hierarchy.py test_delta_task_returns_valid_json: project_summary not in data, impact_summary in data
63
- ```
64
-
65
- ---
66
-
67
- ## Tests
68
-
69
- - **743 passed, 3 skipped** — sin regresiones nuevas
70
- - Fallos pre-existentes (no relacionados):
71
- - `test_block2_coverage.py::test_java_marked_unsupported`
72
- - `test_dependency_analyzer_node_python.py::test_python_requirements_without_lockfile`
73
- - `test_pipeline_integrity.py::TestBenchmarkContamination`
74
-
75
- ---
76
-
77
- ## Smoke tests pendientes (necesitan saint-server)
78
-
79
- ### Smoke delta (nuevo)
80
-
81
- ```bash
82
- # Test básico: relevant_files no vacío con cambios reales
83
- cd saint-server
84
- git diff --name-only main | head -5 # confirmar hay cambios
85
- sourcecode prepare-context delta . --since main --output /tmp/delta_test.json
86
- python3 -c "
87
- import json; d=json.load(open('/tmp/delta_test.json'))
88
- assert d['task'] == 'delta'
89
- assert len(d['relevant_files']) > 0, 'relevant_files is EMPTY — bug not fixed'
90
- assert 'impact_summary' in d, 'missing impact_summary'
91
- assert 'affected_modules' in d or 'risk_areas' in d, 'no impact fields'
92
- assert 'project_summary' not in d, 'project_summary should be suppressed'
93
- print('delta PASS:', d['impact_summary'])
94
- print('changed_files:', d.get('changed_files', [])[:3])
95
- print('affected_modules:', d.get('affected_modules', []))
96
- "
97
-
98
- # Test IDE noise: .idea change → baja prioridad
99
- python3 -c "
100
- from sourcecode.prepare_context import TaskContextBuilder
101
- from pathlib import Path
102
- b = TaskContextBuilder.__new__(TaskContextBuilder)
103
- b.root = Path('.')
104
- relevant, impact, modules, risks, why, gaps = b._build_delta_impact(
105
- changed_files=['.idea/vcs.xml'],
106
- all_paths=[],
107
- entry_points=[],
108
- since='main',
109
- )
110
- assert len(relevant) == 1
111
- assert relevant[0].role == 'noise'
112
- assert relevant[0].score == 0.1
113
- assert 'no semantic impact' in impact
114
- print('IDE noise PASS:', impact)
115
- "
116
-
117
- # Test seguridad: cambio en SecurityConfig → impacto critical
118
- python3 -c "
119
- from sourcecode.prepare_context import TaskContextBuilder
120
- b = TaskContextBuilder.__new__(TaskContextBuilder)
121
- cls = b._classify_changed_file('src/.../security/SecurityConfig.java')
122
- assert cls['artifact_type'] == 'security'
123
- assert cls['impact_level'] == 'critical'
124
- assert 'security' in cls['risk_areas']
125
- print('security PASS:', cls)
126
- "
127
- ```
128
-
129
- ### Smoke tests sesión 2 (pendientes desde antes)
130
-
131
- ```bash
132
- # FIX-1: síntoma inyecta ficheros en fix-bug
133
- sourcecode prepare-context fix-bug saint-server --symptom "ausencias contador" \
134
- --output /tmp/fix_symptom.json
135
-
136
- # FIX-2: resource_names resueltos en security_surface
137
- sourcecode saint-server --compact --output /tmp/sec_test.json
138
-
139
- # FIX-4: score presente en file_relevance
140
- sourcecode saint-server --agent --output /tmp/agent_test.json
141
-
142
- # (ver .continue-here.md sesión 2 para comandos completos de verificación)
143
- ```
144
-
145
- ---
146
-
147
- ## Mejoras opcionales para sesión siguiente
148
-
149
- 1. **`_classify_changed_file` con más patrones**: añadir `cli` (como `cli.py`) → `cli_entrypoint`, `interceptor` → `security`, `aspect` → `cross_cutting`
150
- 2. **`--since` sin argumento**: en vez de default `HEAD~1`, inferir mejor (e.g., base del branch actual vs main)
151
- 3. **Soporte para staged/untracked**: cuando `since` es None, incluir `git status --porcelain` para capturar staged + untracked (no solo `git diff --name-only --relative`)
152
- 4. **Test unitario dedicado** para `_build_delta_impact` y `_classify_changed_file` en `tests/test_task_differentiation.py`
153
-
154
- ---
155
-
156
- ## Para retomar
157
-
158
- ```bash
159
- cd /Users/user/Downloads/atlas-cli
160
- git log --oneline -3 # debe mostrar 8258c4c implementando delta
161
- python3 -m pytest tests/ \
162
- --ignore=tests/test_block2_coverage.py \
163
- --ignore=tests/test_dependency_analyzer_node_python.py \
164
- --ignore=tests/test_pipeline_integrity.py -q
165
- # Expected: 743 passed, 3 skipped
166
-
167
- # Smoke test rápido del delta
168
- python3 run_cli.py prepare-context delta . --since HEAD~3 | python3 -m json.tool | head -30
169
- ```
170
-
171
- ---
172
-
173
- *Pausado 2026-05-13 sesión 3 — gsd:pause-work*
@@ -1,62 +0,0 @@
1
- """Regression tests for C3 — UTF-8 double-encoding of accented characters.
2
-
3
- Fixture files:
4
- - tests/fixtures/latin1_sample_iso.java — Latin-1 encoded (bytes 0xe1, 0xf3, etc.)
5
- - tests/fixtures/latin1_sample.java — UTF-8 encoded (multibyte sequences)
6
-
7
- Both should decode cleanly to the correct Unicode characters.
8
- The old code read Latin-1 files with errors='replace', producing double-encoded garbage.
9
- """
10
- from __future__ import annotations
11
-
12
- from pathlib import Path
13
-
14
- import pytest
15
-
16
- from sourcecode.tree_utils import safe_read_text
17
-
18
- FIXTURES = Path(__file__).parent / "fixtures"
19
- LATIN1_FILE = FIXTURES / "latin1_sample_iso.java"
20
- UTF8_FILE = FIXTURES / "latin1_sample.java"
21
-
22
-
23
- class TestSafeReadText:
24
- """safe_read_text must decode both UTF-8 and Latin-1 files correctly."""
25
-
26
- def test_utf8_file_reads_correctly(self):
27
- content = safe_read_text(UTF8_FILE)
28
- # These characters must appear verbatim — not as double-encoded sequences
29
- assert "días" in content, f"Expected 'días', got: {content[:200]!r}"
30
- assert "ñ" in content or "función" in content or "ñoño" in content
31
- assert "Ã" not in content, "Double-encoded: U+00C3 found (Ã). Encoding was mangled."
32
-
33
- def test_latin1_file_reads_correctly(self):
34
- content = safe_read_text(LATIN1_FILE)
35
- # Latin-1 0xe1 = 'á' — must decode to the correct character
36
- assert "á" in content, f"Expected 'á', got: {content!r}"
37
- assert "ó" in content, f"Expected 'ó', got: {content!r}"
38
- # No replacement chars
39
- assert "�" not in content, "Replacement character found — file was not decoded correctly."
40
- # No double-encoding: 'á' in double-encoded UTF-8-as-Latin-1 would appear as 'á'
41
- assert "Ã" not in content, "Double-encoded: U+00C3 found (Ã). Latin-1 file was not decoded correctly."
42
-
43
- def test_nonexistent_file_raises_oserror(self):
44
- with pytest.raises(OSError):
45
- safe_read_text(FIXTURES / "does_not_exist.java")
46
-
47
-
48
- class TestCodeNotesEncoding:
49
- """CodeNotesAnalyzer must extract notes from Latin-1 files without encoding corruption."""
50
-
51
- def test_latin1_todo_extracted_cleanly(self):
52
- from sourcecode.code_notes_analyzer import CodeNotesAnalyzer
53
-
54
- # analyze() scans FIXTURES dir — Latin-1 file is there
55
- analyzer = CodeNotesAnalyzer()
56
- notes, _, _ = analyzer.analyze(FIXTURES)
57
- # Should have extracted TODO without replacement chars
58
- todo_texts = [n.text for n in notes if "latin1_sample_iso" in n.path]
59
- for text in todo_texts:
60
- assert "â" not in text, f"Double-encoded byte found in TODO text: {text!r}"
61
- assert "Ã" not in text, f"Double-encoded char in TODO text: {text!r}"
62
- assert "�" not in text, f"Replacement char in TODO text: {text!r}"
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes