sourcecode 1.31.25__tar.gz → 1.31.26__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 (230) hide show
  1. sourcecode-1.31.26/.continue-here.md +70 -0
  2. {sourcecode-1.31.25 → sourcecode-1.31.26}/PKG-INFO +3 -3
  3. {sourcecode-1.31.25 → sourcecode-1.31.26}/README.md +2 -2
  4. {sourcecode-1.31.25 → sourcecode-1.31.26}/pyproject.toml +1 -1
  5. {sourcecode-1.31.25 → sourcecode-1.31.26}/src/sourcecode/__init__.py +1 -1
  6. {sourcecode-1.31.25 → sourcecode-1.31.26}/src/sourcecode/cli.py +3 -1
  7. {sourcecode-1.31.25 → sourcecode-1.31.26}/src/sourcecode/mcp/server.py +219 -68
  8. {sourcecode-1.31.25 → sourcecode-1.31.26}/tests/test_enterprise_benchmarks.py +2 -2
  9. sourcecode-1.31.25/.continue-here.md +0 -99
  10. {sourcecode-1.31.25 → sourcecode-1.31.26}/.agents/skills/source-command-gsd-join-discord/SKILL.md +0 -0
  11. {sourcecode-1.31.25 → sourcecode-1.31.26}/.agents/skills/source-command-gsd-review-backlog/SKILL.md +0 -0
  12. {sourcecode-1.31.25 → sourcecode-1.31.26}/.agents/skills/source-command-gsd-workstreams/SKILL.md +0 -0
  13. {sourcecode-1.31.25 → sourcecode-1.31.26}/.github/workflows/build-windows.yml +0 -0
  14. {sourcecode-1.31.25 → sourcecode-1.31.26}/.gitignore +0 -0
  15. {sourcecode-1.31.25 → sourcecode-1.31.26}/.ruff.toml +0 -0
  16. {sourcecode-1.31.25 → sourcecode-1.31.26}/.sourcecode-cache/snapshot-3b5997a-fa5c742c.json +0 -0
  17. {sourcecode-1.31.25 → sourcecode-1.31.26}/AUDIT_REAL_REPOS.md +0 -0
  18. {sourcecode-1.31.25 → sourcecode-1.31.26}/AUDIT_v1.31.23.md +0 -0
  19. {sourcecode-1.31.25 → sourcecode-1.31.26}/CHANGELOG.md +0 -0
  20. {sourcecode-1.31.25 → sourcecode-1.31.26}/CONTRIBUTING.md +0 -0
  21. {sourcecode-1.31.25 → sourcecode-1.31.26}/LICENSE +0 -0
  22. {sourcecode-1.31.25 → sourcecode-1.31.26}/SECURITY.md +0 -0
  23. {sourcecode-1.31.25 → sourcecode-1.31.26}/docs/PRODUCT_TIERS.md +0 -0
  24. {sourcecode-1.31.25 → sourcecode-1.31.26}/docs/privacy.md +0 -0
  25. {sourcecode-1.31.25 → sourcecode-1.31.26}/docs/schema.md +0 -0
  26. {sourcecode-1.31.25 → sourcecode-1.31.26}/raw +0 -0
  27. {sourcecode-1.31.25 → sourcecode-1.31.26}/run_cli.py +0 -0
  28. {sourcecode-1.31.25 → sourcecode-1.31.26}/src/sourcecode/adaptive_scanner.py +0 -0
  29. {sourcecode-1.31.25 → sourcecode-1.31.26}/src/sourcecode/architecture_analyzer.py +0 -0
  30. {sourcecode-1.31.25 → sourcecode-1.31.26}/src/sourcecode/architecture_summary.py +0 -0
  31. {sourcecode-1.31.25 → sourcecode-1.31.26}/src/sourcecode/ast_extractor.py +0 -0
  32. {sourcecode-1.31.25 → sourcecode-1.31.26}/src/sourcecode/cache.py +0 -0
  33. {sourcecode-1.31.25 → sourcecode-1.31.26}/src/sourcecode/canonical_ir.py +0 -0
  34. {sourcecode-1.31.25 → sourcecode-1.31.26}/src/sourcecode/classifier.py +0 -0
  35. {sourcecode-1.31.25 → sourcecode-1.31.26}/src/sourcecode/code_notes_analyzer.py +0 -0
  36. {sourcecode-1.31.25 → sourcecode-1.31.26}/src/sourcecode/confidence_analyzer.py +0 -0
  37. {sourcecode-1.31.25 → sourcecode-1.31.26}/src/sourcecode/context_scorer.py +0 -0
  38. {sourcecode-1.31.25 → sourcecode-1.31.26}/src/sourcecode/context_summarizer.py +0 -0
  39. {sourcecode-1.31.25 → sourcecode-1.31.26}/src/sourcecode/contract_model.py +0 -0
  40. {sourcecode-1.31.25 → sourcecode-1.31.26}/src/sourcecode/contract_pipeline.py +0 -0
  41. {sourcecode-1.31.25 → sourcecode-1.31.26}/src/sourcecode/coverage_parser.py +0 -0
  42. {sourcecode-1.31.25 → sourcecode-1.31.26}/src/sourcecode/dependency_analyzer.py +0 -0
  43. {sourcecode-1.31.25 → sourcecode-1.31.26}/src/sourcecode/detectors/__init__.py +0 -0
  44. {sourcecode-1.31.25 → sourcecode-1.31.26}/src/sourcecode/detectors/base.py +0 -0
  45. {sourcecode-1.31.25 → sourcecode-1.31.26}/src/sourcecode/detectors/csproj_parser.py +0 -0
  46. {sourcecode-1.31.25 → sourcecode-1.31.26}/src/sourcecode/detectors/dart.py +0 -0
  47. {sourcecode-1.31.25 → sourcecode-1.31.26}/src/sourcecode/detectors/dotnet.py +0 -0
  48. {sourcecode-1.31.25 → sourcecode-1.31.26}/src/sourcecode/detectors/elixir.py +0 -0
  49. {sourcecode-1.31.25 → sourcecode-1.31.26}/src/sourcecode/detectors/go.py +0 -0
  50. {sourcecode-1.31.25 → sourcecode-1.31.26}/src/sourcecode/detectors/heuristic.py +0 -0
  51. {sourcecode-1.31.25 → sourcecode-1.31.26}/src/sourcecode/detectors/hybrid.py +0 -0
  52. {sourcecode-1.31.25 → sourcecode-1.31.26}/src/sourcecode/detectors/java.py +0 -0
  53. {sourcecode-1.31.25 → sourcecode-1.31.26}/src/sourcecode/detectors/jvm_ext.py +0 -0
  54. {sourcecode-1.31.25 → sourcecode-1.31.26}/src/sourcecode/detectors/nodejs.py +0 -0
  55. {sourcecode-1.31.25 → sourcecode-1.31.26}/src/sourcecode/detectors/parsers.py +0 -0
  56. {sourcecode-1.31.25 → sourcecode-1.31.26}/src/sourcecode/detectors/php.py +0 -0
  57. {sourcecode-1.31.25 → sourcecode-1.31.26}/src/sourcecode/detectors/project.py +0 -0
  58. {sourcecode-1.31.25 → sourcecode-1.31.26}/src/sourcecode/detectors/python.py +0 -0
  59. {sourcecode-1.31.25 → sourcecode-1.31.26}/src/sourcecode/detectors/ruby.py +0 -0
  60. {sourcecode-1.31.25 → sourcecode-1.31.26}/src/sourcecode/detectors/rust.py +0 -0
  61. {sourcecode-1.31.25 → sourcecode-1.31.26}/src/sourcecode/detectors/systems.py +0 -0
  62. {sourcecode-1.31.25 → sourcecode-1.31.26}/src/sourcecode/detectors/terraform.py +0 -0
  63. {sourcecode-1.31.25 → sourcecode-1.31.26}/src/sourcecode/detectors/tooling.py +0 -0
  64. {sourcecode-1.31.25 → sourcecode-1.31.26}/src/sourcecode/doc_analyzer.py +0 -0
  65. {sourcecode-1.31.25 → sourcecode-1.31.26}/src/sourcecode/entrypoint_classifier.py +0 -0
  66. {sourcecode-1.31.25 → sourcecode-1.31.26}/src/sourcecode/env_analyzer.py +0 -0
  67. {sourcecode-1.31.25 → sourcecode-1.31.26}/src/sourcecode/file_classifier.py +0 -0
  68. {sourcecode-1.31.25 → sourcecode-1.31.26}/src/sourcecode/flow_analyzer.py +0 -0
  69. {sourcecode-1.31.25 → sourcecode-1.31.26}/src/sourcecode/git_analyzer.py +0 -0
  70. {sourcecode-1.31.25 → sourcecode-1.31.26}/src/sourcecode/graph_analyzer.py +0 -0
  71. {sourcecode-1.31.25 → sourcecode-1.31.26}/src/sourcecode/mcp/__init__.py +0 -0
  72. {sourcecode-1.31.25 → sourcecode-1.31.26}/src/sourcecode/mcp/onboarding/__init__.py +0 -0
  73. {sourcecode-1.31.25 → sourcecode-1.31.26}/src/sourcecode/mcp/onboarding/applier.py +0 -0
  74. {sourcecode-1.31.25 → sourcecode-1.31.26}/src/sourcecode/mcp/onboarding/backup.py +0 -0
  75. {sourcecode-1.31.25 → sourcecode-1.31.26}/src/sourcecode/mcp/onboarding/detector.py +0 -0
  76. {sourcecode-1.31.25 → sourcecode-1.31.26}/src/sourcecode/mcp/onboarding/planner.py +0 -0
  77. {sourcecode-1.31.25 → sourcecode-1.31.26}/src/sourcecode/mcp/runner.py +0 -0
  78. {sourcecode-1.31.25 → sourcecode-1.31.26}/src/sourcecode/metrics_analyzer.py +0 -0
  79. {sourcecode-1.31.25 → sourcecode-1.31.26}/src/sourcecode/output_budget.py +0 -0
  80. {sourcecode-1.31.25 → sourcecode-1.31.26}/src/sourcecode/path_filters.py +0 -0
  81. {sourcecode-1.31.25 → sourcecode-1.31.26}/src/sourcecode/pr_comment_renderer.py +0 -0
  82. {sourcecode-1.31.25 → sourcecode-1.31.26}/src/sourcecode/prepare_context.py +0 -0
  83. {sourcecode-1.31.25 → sourcecode-1.31.26}/src/sourcecode/progress.py +0 -0
  84. {sourcecode-1.31.25 → sourcecode-1.31.26}/src/sourcecode/ranking_engine.py +0 -0
  85. {sourcecode-1.31.25 → sourcecode-1.31.26}/src/sourcecode/redactor.py +0 -0
  86. {sourcecode-1.31.25 → sourcecode-1.31.26}/src/sourcecode/relevance_scorer.py +0 -0
  87. {sourcecode-1.31.25 → sourcecode-1.31.26}/src/sourcecode/repo_classifier.py +0 -0
  88. {sourcecode-1.31.25 → sourcecode-1.31.26}/src/sourcecode/repository_ir.py +0 -0
  89. {sourcecode-1.31.25 → sourcecode-1.31.26}/src/sourcecode/runtime_classifier.py +0 -0
  90. {sourcecode-1.31.25 → sourcecode-1.31.26}/src/sourcecode/scanner.py +0 -0
  91. {sourcecode-1.31.25 → sourcecode-1.31.26}/src/sourcecode/schema.py +0 -0
  92. {sourcecode-1.31.25 → sourcecode-1.31.26}/src/sourcecode/semantic_analyzer.py +0 -0
  93. {sourcecode-1.31.25 → sourcecode-1.31.26}/src/sourcecode/serializer.py +0 -0
  94. {sourcecode-1.31.25 → sourcecode-1.31.26}/src/sourcecode/summarizer.py +0 -0
  95. {sourcecode-1.31.25 → sourcecode-1.31.26}/src/sourcecode/telemetry/__init__.py +0 -0
  96. {sourcecode-1.31.25 → sourcecode-1.31.26}/src/sourcecode/telemetry/config.py +0 -0
  97. {sourcecode-1.31.25 → sourcecode-1.31.26}/src/sourcecode/telemetry/consent.py +0 -0
  98. {sourcecode-1.31.25 → sourcecode-1.31.26}/src/sourcecode/telemetry/events.py +0 -0
  99. {sourcecode-1.31.25 → sourcecode-1.31.26}/src/sourcecode/telemetry/filters.py +0 -0
  100. {sourcecode-1.31.25 → sourcecode-1.31.26}/src/sourcecode/telemetry/transport.py +0 -0
  101. {sourcecode-1.31.25 → sourcecode-1.31.26}/src/sourcecode/tree_utils.py +0 -0
  102. {sourcecode-1.31.25 → sourcecode-1.31.26}/src/sourcecode/workspace.py +0 -0
  103. {sourcecode-1.31.25 → sourcecode-1.31.26}/tests/__init__.py +0 -0
  104. {sourcecode-1.31.25 → sourcecode-1.31.26}/tests/conftest.py +0 -0
  105. {sourcecode-1.31.25 → sourcecode-1.31.26}/tests/fixtures/coverage.xml +0 -0
  106. {sourcecode-1.31.25 → sourcecode-1.31.26}/tests/fixtures/fastapi_app/pyproject.toml +0 -0
  107. {sourcecode-1.31.25 → sourcecode-1.31.26}/tests/fixtures/fastapi_app/src/main.py +0 -0
  108. {sourcecode-1.31.25 → sourcecode-1.31.26}/tests/fixtures/go_service/cmd/api/main.go +0 -0
  109. {sourcecode-1.31.25 → sourcecode-1.31.26}/tests/fixtures/go_service/go.mod +0 -0
  110. {sourcecode-1.31.25 → sourcecode-1.31.26}/tests/fixtures/jacoco.xml +0 -0
  111. {sourcecode-1.31.25 → sourcecode-1.31.26}/tests/fixtures/latin1_sample.java +0 -0
  112. {sourcecode-1.31.25 → sourcecode-1.31.26}/tests/fixtures/latin1_sample_iso.java +0 -0
  113. {sourcecode-1.31.25 → sourcecode-1.31.26}/tests/fixtures/lcov.info +0 -0
  114. {sourcecode-1.31.25 → sourcecode-1.31.26}/tests/fixtures/nextjs_app/app/page.tsx +0 -0
  115. {sourcecode-1.31.25 → sourcecode-1.31.26}/tests/fixtures/nextjs_app/package.json +0 -0
  116. {sourcecode-1.31.25 → sourcecode-1.31.26}/tests/fixtures/nextjs_app/pnpm-lock.yaml +0 -0
  117. {sourcecode-1.31.25 → sourcecode-1.31.26}/tests/fixtures/pnpm_monorepo/apps/web/app/page.tsx +0 -0
  118. {sourcecode-1.31.25 → sourcecode-1.31.26}/tests/fixtures/pnpm_monorepo/apps/web/package.json +0 -0
  119. {sourcecode-1.31.25 → sourcecode-1.31.26}/tests/fixtures/pnpm_monorepo/packages/api/main.py +0 -0
  120. {sourcecode-1.31.25 → sourcecode-1.31.26}/tests/fixtures/pnpm_monorepo/packages/api/pyproject.toml +0 -0
  121. {sourcecode-1.31.25 → sourcecode-1.31.26}/tests/fixtures/pnpm_monorepo/pnpm-workspace.yaml +0 -0
  122. {sourcecode-1.31.25 → sourcecode-1.31.26}/tests/fixtures/spring_boot_minimal/pom.xml +0 -0
  123. {sourcecode-1.31.25 → sourcecode-1.31.26}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/ausente/application/service/FindAusenteService.java +0 -0
  124. {sourcecode-1.31.25 → sourcecode-1.31.26}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/ausente/domain/entities/Ausente.java +0 -0
  125. {sourcecode-1.31.25 → sourcecode-1.31.26}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/ausente/infrastructure/rest/AusenteRestController.java +0 -0
  126. {sourcecode-1.31.25 → sourcecode-1.31.26}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/autocoberturas/application/service/FindAutocoberturasService.java +0 -0
  127. {sourcecode-1.31.25 → sourcecode-1.31.26}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/autocoberturas/domain/entities/Autocoberturas.java +0 -0
  128. {sourcecode-1.31.25 → sourcecode-1.31.26}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/autocoberturas/infrastructure/rest/AutocoberturasRestController.java +0 -0
  129. {sourcecode-1.31.25 → sourcecode-1.31.26}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/calendarioTrabajador/application/service/FindCalendarioTrabajadorService.java +0 -0
  130. {sourcecode-1.31.25 → sourcecode-1.31.26}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/calendarioTrabajador/domain/entities/CalendarioTrabajador.java +0 -0
  131. {sourcecode-1.31.25 → sourcecode-1.31.26}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/calendarioTrabajador/infrastructure/rest/CalendarioTrabajadorRestController.java +0 -0
  132. {sourcecode-1.31.25 → sourcecode-1.31.26}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/departamento/application/service/FindDepartamentoService.java +0 -0
  133. {sourcecode-1.31.25 → sourcecode-1.31.26}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/departamento/domain/entities/Departamento.java +0 -0
  134. {sourcecode-1.31.25 → sourcecode-1.31.26}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/departamento/infrastructure/rest/DepartamentoRestController.java +0 -0
  135. {sourcecode-1.31.25 → sourcecode-1.31.26}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/empleado/application/service/FindEmpleadoService.java +0 -0
  136. {sourcecode-1.31.25 → sourcecode-1.31.26}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/empleado/domain/entities/Empleado.java +0 -0
  137. {sourcecode-1.31.25 → sourcecode-1.31.26}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/empleado/infrastructure/rest/EmpleadoRestController.java +0 -0
  138. {sourcecode-1.31.25 → sourcecode-1.31.26}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/demo/DemoApplication.java +0 -0
  139. {sourcecode-1.31.25 → sourcecode-1.31.26}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/demo/config/FilterConfig.java +0 -0
  140. {sourcecode-1.31.25 → sourcecode-1.31.26}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/demo/domain/Health.java +0 -0
  141. {sourcecode-1.31.25 → sourcecode-1.31.26}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/demo/mapper/HealthMapper.java +0 -0
  142. {sourcecode-1.31.25 → sourcecode-1.31.26}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/demo/repository/HealthRepository.java +0 -0
  143. {sourcecode-1.31.25 → sourcecode-1.31.26}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/demo/service/HealthService.java +0 -0
  144. {sourcecode-1.31.25 → sourcecode-1.31.26}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/demo/web/HealthRestController.java +0 -0
  145. {sourcecode-1.31.25 → sourcecode-1.31.26}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/demo/web/NominaRestController.java +0 -0
  146. {sourcecode-1.31.25 → sourcecode-1.31.26}/tests/fixtures/spring_boot_minimal/src/main/resources/application-dev.yml +0 -0
  147. {sourcecode-1.31.25 → sourcecode-1.31.26}/tests/fixtures/spring_boot_minimal/src/main/resources/application.yml +0 -0
  148. {sourcecode-1.31.25 → sourcecode-1.31.26}/tests/fixtures/spring_boot_minimal/src/main/resources/mapper/HealthMapper.xml +0 -0
  149. {sourcecode-1.31.25 → sourcecode-1.31.26}/tests/test_architecture_analyzer.py +0 -0
  150. {sourcecode-1.31.25 → sourcecode-1.31.26}/tests/test_architecture_summary.py +0 -0
  151. {sourcecode-1.31.25 → sourcecode-1.31.26}/tests/test_ast_extractor.py +0 -0
  152. {sourcecode-1.31.25 → sourcecode-1.31.26}/tests/test_audit_fixes.py +0 -0
  153. {sourcecode-1.31.25 → sourcecode-1.31.26}/tests/test_audit_sas_v2.py +0 -0
  154. {sourcecode-1.31.25 → sourcecode-1.31.26}/tests/test_block1_reliability.py +0 -0
  155. {sourcecode-1.31.25 → sourcecode-1.31.26}/tests/test_block2_coverage.py +0 -0
  156. {sourcecode-1.31.25 → sourcecode-1.31.26}/tests/test_block5_quality.py +0 -0
  157. {sourcecode-1.31.25 → sourcecode-1.31.26}/tests/test_broadleaf_fixes.py +0 -0
  158. {sourcecode-1.31.25 → sourcecode-1.31.26}/tests/test_bug_fixes_v1302.py +0 -0
  159. {sourcecode-1.31.25 → sourcecode-1.31.26}/tests/test_bug_fixes_v13115.py +0 -0
  160. {sourcecode-1.31.25 → sourcecode-1.31.26}/tests/test_bug_fixes_v1312.py +0 -0
  161. {sourcecode-1.31.25 → sourcecode-1.31.26}/tests/test_bug_fixes_v13122.py +0 -0
  162. {sourcecode-1.31.25 → sourcecode-1.31.26}/tests/test_bug_fixes_v1313.py +0 -0
  163. {sourcecode-1.31.25 → sourcecode-1.31.26}/tests/test_bug_fixes_v1321.py +0 -0
  164. {sourcecode-1.31.25 → sourcecode-1.31.26}/tests/test_bug_fixes_v16.py +0 -0
  165. {sourcecode-1.31.25 → sourcecode-1.31.26}/tests/test_bug_fixes_v2.py +0 -0
  166. {sourcecode-1.31.25 → sourcecode-1.31.26}/tests/test_cache.py +0 -0
  167. {sourcecode-1.31.25 → sourcecode-1.31.26}/tests/test_canonical_ir.py +0 -0
  168. {sourcecode-1.31.25 → sourcecode-1.31.26}/tests/test_classifier.py +0 -0
  169. {sourcecode-1.31.25 → sourcecode-1.31.26}/tests/test_cli.py +0 -0
  170. {sourcecode-1.31.25 → sourcecode-1.31.26}/tests/test_code_notes_analyzer.py +0 -0
  171. {sourcecode-1.31.25 → sourcecode-1.31.26}/tests/test_context_scorer.py +0 -0
  172. {sourcecode-1.31.25 → sourcecode-1.31.26}/tests/test_contract_pipeline.py +0 -0
  173. {sourcecode-1.31.25 → sourcecode-1.31.26}/tests/test_coverage_parser.py +0 -0
  174. {sourcecode-1.31.25 → sourcecode-1.31.26}/tests/test_cross_consistency.py +0 -0
  175. {sourcecode-1.31.25 → sourcecode-1.31.26}/tests/test_dependency_analyzer_node_python.py +0 -0
  176. {sourcecode-1.31.25 → sourcecode-1.31.26}/tests/test_dependency_analyzer_polyglot.py +0 -0
  177. {sourcecode-1.31.25 → sourcecode-1.31.26}/tests/test_dependency_schema.py +0 -0
  178. {sourcecode-1.31.25 → sourcecode-1.31.26}/tests/test_detector_dotnet.py +0 -0
  179. {sourcecode-1.31.25 → sourcecode-1.31.26}/tests/test_detector_go_rust_java.py +0 -0
  180. {sourcecode-1.31.25 → sourcecode-1.31.26}/tests/test_detector_nodejs.py +0 -0
  181. {sourcecode-1.31.25 → sourcecode-1.31.26}/tests/test_detector_php_ruby_dart.py +0 -0
  182. {sourcecode-1.31.25 → sourcecode-1.31.26}/tests/test_detector_python.py +0 -0
  183. {sourcecode-1.31.25 → sourcecode-1.31.26}/tests/test_detector_universal_managed.py +0 -0
  184. {sourcecode-1.31.25 → sourcecode-1.31.26}/tests/test_detector_universal_systems.py +0 -0
  185. {sourcecode-1.31.25 → sourcecode-1.31.26}/tests/test_detectors_base.py +0 -0
  186. {sourcecode-1.31.25 → sourcecode-1.31.26}/tests/test_doc_analyzer_jsdom.py +0 -0
  187. {sourcecode-1.31.25 → sourcecode-1.31.26}/tests/test_doc_analyzer_python.py +0 -0
  188. {sourcecode-1.31.25 → sourcecode-1.31.26}/tests/test_encoding_regression.py +0 -0
  189. {sourcecode-1.31.25 → sourcecode-1.31.26}/tests/test_graph_analyzer_polyglot.py +0 -0
  190. {sourcecode-1.31.25 → sourcecode-1.31.26}/tests/test_graph_analyzer_python_node.py +0 -0
  191. {sourcecode-1.31.25 → sourcecode-1.31.26}/tests/test_graph_schema.py +0 -0
  192. {sourcecode-1.31.25 → sourcecode-1.31.26}/tests/test_hybrid_inference.py +0 -0
  193. {sourcecode-1.31.25 → sourcecode-1.31.26}/tests/test_integration.py +0 -0
  194. {sourcecode-1.31.25 → sourcecode-1.31.26}/tests/test_integration_dependencies.py +0 -0
  195. {sourcecode-1.31.25 → sourcecode-1.31.26}/tests/test_integration_detection.py +0 -0
  196. {sourcecode-1.31.25 → sourcecode-1.31.26}/tests/test_integration_docs.py +0 -0
  197. {sourcecode-1.31.25 → sourcecode-1.31.26}/tests/test_integration_graph_modules.py +0 -0
  198. {sourcecode-1.31.25 → sourcecode-1.31.26}/tests/test_integration_lqn.py +0 -0
  199. {sourcecode-1.31.25 → sourcecode-1.31.26}/tests/test_integration_metrics.py +0 -0
  200. {sourcecode-1.31.25 → sourcecode-1.31.26}/tests/test_integration_multistack.py +0 -0
  201. {sourcecode-1.31.25 → sourcecode-1.31.26}/tests/test_integration_semantics.py +0 -0
  202. {sourcecode-1.31.25 → sourcecode-1.31.26}/tests/test_integration_universal.py +0 -0
  203. {sourcecode-1.31.25 → sourcecode-1.31.26}/tests/test_java_spring_integration.py +0 -0
  204. {sourcecode-1.31.25 → sourcecode-1.31.26}/tests/test_mcp_runner.py +0 -0
  205. {sourcecode-1.31.25 → sourcecode-1.31.26}/tests/test_mcp_serve.py +0 -0
  206. {sourcecode-1.31.25 → sourcecode-1.31.26}/tests/test_mcp_tools.py +0 -0
  207. {sourcecode-1.31.25 → sourcecode-1.31.26}/tests/test_metrics_analyzer.py +0 -0
  208. {sourcecode-1.31.25 → sourcecode-1.31.26}/tests/test_output_ux.py +0 -0
  209. {sourcecode-1.31.25 → sourcecode-1.31.26}/tests/test_packaging.py +0 -0
  210. {sourcecode-1.31.25 → sourcecode-1.31.26}/tests/test_phase1_improvements.py +0 -0
  211. {sourcecode-1.31.25 → sourcecode-1.31.26}/tests/test_pipeline_integrity.py +0 -0
  212. {sourcecode-1.31.25 → sourcecode-1.31.26}/tests/test_real_projects.py +0 -0
  213. {sourcecode-1.31.25 → sourcecode-1.31.26}/tests/test_redactor.py +0 -0
  214. {sourcecode-1.31.25 → sourcecode-1.31.26}/tests/test_repository_ir.py +0 -0
  215. {sourcecode-1.31.25 → sourcecode-1.31.26}/tests/test_scanner.py +0 -0
  216. {sourcecode-1.31.25 → sourcecode-1.31.26}/tests/test_schema.py +0 -0
  217. {sourcecode-1.31.25 → sourcecode-1.31.26}/tests/test_schema_normalization.py +0 -0
  218. {sourcecode-1.31.25 → sourcecode-1.31.26}/tests/test_scoring_calibration.py +0 -0
  219. {sourcecode-1.31.25 → sourcecode-1.31.26}/tests/test_semantic_analyzer_node.py +0 -0
  220. {sourcecode-1.31.25 → sourcecode-1.31.26}/tests/test_semantic_analyzer_python.py +0 -0
  221. {sourcecode-1.31.25 → sourcecode-1.31.26}/tests/test_semantic_import_resolution.py +0 -0
  222. {sourcecode-1.31.25 → sourcecode-1.31.26}/tests/test_semantic_schema.py +0 -0
  223. {sourcecode-1.31.25 → sourcecode-1.31.26}/tests/test_signal_hierarchy.py +0 -0
  224. {sourcecode-1.31.25 → sourcecode-1.31.26}/tests/test_summarizer.py +0 -0
  225. {sourcecode-1.31.25 → sourcecode-1.31.26}/tests/test_surface_honesty.py +0 -0
  226. {sourcecode-1.31.25 → sourcecode-1.31.26}/tests/test_task_differentiation.py +0 -0
  227. {sourcecode-1.31.25 → sourcecode-1.31.26}/tests/test_telemetry.py +0 -0
  228. {sourcecode-1.31.25 → sourcecode-1.31.26}/tests/test_v131_improvements.py +0 -0
  229. {sourcecode-1.31.25 → sourcecode-1.31.26}/tests/test_v1_10_regressions.py +0 -0
  230. {sourcecode-1.31.25 → sourcecode-1.31.26}/tests/test_workspace_analyzer.py +0 -0
@@ -0,0 +1,70 @@
1
+ # Handoff — Sesión 30 (2026-05-26)
2
+
3
+ ## Position
4
+
5
+ **Project:** sourcecode (atlas-cli)
6
+ **Activity:** Post-audit bug fixing — AUDIT_v1.31.23.md
7
+ **Branch:** master
8
+ **Last commit:** f225ab2 — (fix) updating flags in order to copy the output in the clipboard
9
+ **Tests:** 1590 passed, 3 skipped ✅
10
+
11
+ ---
12
+
13
+ ## Work Done This Session
14
+
15
+ ### Session 30 (this session)
16
+ **`--copy/-c` flag parity across all output commands** (`cli.py`):
17
+ - `impact_cmd`: added `--copy/-c` option + copy logic (fires only when no `--output`)
18
+ - `repo_ir_cmd`: added `--copy/-c` option + copy logic (after stdout write, before UnicodeEncodeError path)
19
+ - `endpoints_cmd`: added `--copy/-c` option + copy logic
20
+
21
+ All three now consistent with existing commands (`main`, `prepare-context`, `onboard`, `review-pr`, `fix-bug`, `modernize`).
22
+
23
+ Pattern: `if copy: if _copy_to_clipboard(output): typer.echo("✓ copied to clipboard", err=True)`
24
+
25
+ ---
26
+
27
+ ## Remaining from AUDIT_v1.31.23.md
28
+
29
+ ### P2 unfixed (section 13, items 6–18)
30
+ | # | Issue | File | Effort |
31
+ |---|---|---|---|
32
+ | P2-06 | `subsystem_summary.member_count` always 0 | cli.py modernize_cmd | Medium |
33
+ | P2-07 | `no_security_signal` → detect filter-based security → `security_model: "filter_based"` | repository_ir.py | Medium |
34
+ | P2-10 | `architecture.confidence` inconsistent between `--compact` and `--agent` | serializer.py | Low |
35
+ | P2-13 | `--no-cache` flag inconsistent across subcommands (`--copy` now fixed) | cli.py | Medium |
36
+ | P2-14 | URLs in code_notes truncated (missing `https://bugs.` prefix) | code_notes_analyzer.py | Low (needs repro) |
37
+ | P2-16 | `entry_points.controllers.methods` mismatches `endpoints` count | cli.py | Medium |
38
+ | P2-17 | `--compact --help` token claim outdated | cli.py | Trivial |
39
+ | P2-18 | `impact` via file path: resolve to FQN before IR lookup | repository_ir.py | Low |
40
+
41
+ ### Score from Session 29
42
+ | Dimension | v1.31.23 | After S29 | Fix applied |
43
+ |---|---|---|---|
44
+ | Correctness impl classes | 8/10 | 8.5/10 | BFS sampling |
45
+ | Onboarding context quality | 7/10 | 8/10 | project_summary quantitative + bounded_contexts |
46
+ | Modernize/dead code | 3/10 | 5.5/10 | hotspots with churn, roles classified |
47
+ | Java/Spring depth | 8/10 | 8.5/10 | bounded_contexts Maven modules |
48
+ | **TOTAL** | **6.5/10** | **~7.2/10** | |
49
+
50
+ ---
51
+
52
+ ## Key Files Modified (this session)
53
+
54
+ ```
55
+ src/sourcecode/cli.py — --copy/-c added to impact_cmd, repo_ir_cmd, endpoints_cmd
56
+ ```
57
+
58
+ ---
59
+
60
+ ## Next Session
61
+
62
+ **Recommended start:** Fix `subsystem_summary.member_count` (P2-06).
63
+
64
+ Root cause: `_detect_subsystems()` in `repository_ir.py` builds subsystems but doesn't populate the `members` list that `modernize_cmd` reads via `len(s.get("members") or [])`. Fix: ensure each subsystem dict includes the list of FQNs.
65
+
66
+ Then: `--no-cache` flag consistency audit (P2-13 remainder).
67
+
68
+ **Resume command:** `/gsd:resume-work`
69
+
70
+ **Test baseline:** `python3 -m pytest tests/ → 1590 passed, 3 skipped`
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: sourcecode
3
- Version: 1.31.25
3
+ Version: 1.31.26
4
4
  Summary: Deterministic codebase context for AI coding agents
5
5
  License: Apache License
6
6
  Version 2.0, January 2004
@@ -225,7 +225,7 @@ Description-Content-Type: text/markdown
225
225
 
226
226
  **AI-ready change intelligence for Java/Spring enterprise monoliths.**
227
227
 
228
- ![Version](https://img.shields.io/badge/version-1.31.25-blue)
228
+ ![Version](https://img.shields.io/badge/version-1.31.26-blue)
229
229
  ![Python](https://img.shields.io/badge/python-3.10%2B-green)
230
230
 
231
231
  ---
@@ -263,7 +263,7 @@ pipx install sourcecode
263
263
 
264
264
  ```bash
265
265
  sourcecode version
266
- # sourcecode 1.31.25
266
+ # sourcecode 1.31.26
267
267
  ```
268
268
 
269
269
  ---
@@ -2,7 +2,7 @@
2
2
 
3
3
  **AI-ready change intelligence for Java/Spring enterprise monoliths.**
4
4
 
5
- ![Version](https://img.shields.io/badge/version-1.31.25-blue)
5
+ ![Version](https://img.shields.io/badge/version-1.31.26-blue)
6
6
  ![Python](https://img.shields.io/badge/python-3.10%2B-green)
7
7
 
8
8
  ---
@@ -40,7 +40,7 @@ pipx install sourcecode
40
40
 
41
41
  ```bash
42
42
  sourcecode version
43
- # sourcecode 1.31.25
43
+ # sourcecode 1.31.26
44
44
  ```
45
45
 
46
46
  ---
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "sourcecode"
7
- version = "1.31.25"
7
+ version = "1.31.26"
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.31.25"
3
+ __version__ = "1.31.26"
@@ -745,7 +745,7 @@ def main(
745
745
  "is meant for --agent mode. Use --agent --full for expanded output.",
746
746
  err=True,
747
747
  )
748
- raise typer.Exit(code=2)
748
+ raise typer.Exit(code=1)
749
749
 
750
750
  # P0-2 FIX: --full without --compact or --agent has no effect in contract/raw mode.
751
751
  # Warn so the user knows the flag is not doing anything.
@@ -3549,6 +3549,7 @@ def mcp_init(
3549
3549
  raise typer.Exit(code=1)
3550
3550
 
3551
3551
  typer.echo("MCP integration active.")
3552
+ typer.echo(" Note: repo_path debe usar forward slashes: C:/Users/... o /ruta/unix")
3552
3553
  typer.echo("")
3553
3554
 
3554
3555
  # Post-write: validate config and warn if client not running
@@ -3696,6 +3697,7 @@ def mcp_status() -> None:
3696
3697
  typer.echo(sep)
3697
3698
  typer.echo(" Note: 'configured' and 'running' are checked independently.")
3698
3699
  typer.echo(" A running app still needs restart after first-time config.")
3700
+ typer.echo(" Path: repo_path debe usar forward slashes: C:/Users/... o /ruta/unix")
3699
3701
  typer.echo(" Setup: sourcecode mcp init")
3700
3702
  typer.echo(" Remove: sourcecode mcp remove")
3701
3703
 
@@ -10,8 +10,10 @@ data is the parsed JSON object from the CLI output, not a shell string.
10
10
  """
11
11
  from __future__ import annotations
12
12
 
13
+ import concurrent.futures
13
14
  import json
14
15
  import os
16
+ import re
15
17
  from typing import Any
16
18
 
17
19
  from mcp.server.fastmcp import FastMCP
@@ -63,6 +65,29 @@ def _execute(args: list[str]) -> dict | CallToolResult:
63
65
  return _ok(result)
64
66
 
65
67
 
68
+ _DEFAULT_TESTS_TIMEOUT_MS = 15_000
69
+
70
+ # Regex for MINGW paths: /c/some/path → C:/some/path
71
+ _MINGW_PATH_RE = re.compile(r"^/([a-zA-Z])(/.*)?$")
72
+
73
+
74
+ def _normalize_repo_path(path: str) -> str:
75
+ """Normalize repo_path for cross-platform compatibility (P0-2).
76
+
77
+ Handles two Windows-specific formats:
78
+ - MINGW/Git-Bash: /c/Users/... → C:/Users/...
79
+ - Backslash: C:\\Users\\... → C:/Users/...
80
+ Forward-slash paths (C:/Users/... or /unix/path) pass through unchanged.
81
+ """
82
+ m = _MINGW_PATH_RE.match(path)
83
+ if m:
84
+ drive = m.group(1).upper()
85
+ rest = m.group(2) or "/"
86
+ path = f"{drive}:{rest}"
87
+ path = path.replace("\\", "/")
88
+ return path
89
+
90
+
66
91
  @mcp.tool()
67
92
  def get_compact_context(repo_path: str = ".", git_context: bool = False) -> dict:
68
93
  """Compact human/LLM summary of a repository (~1000-3000 tokens). USE THIS FIRST.
@@ -76,14 +101,22 @@ def get_compact_context(repo_path: str = ".", git_context: bool = False) -> dict
76
101
  repo_path: absolute path to the repository (default: current working directory).
77
102
  git_context: include git log and branch context in the analysis.
78
103
  """
79
- if not isinstance(repo_path, str):
80
- return _err("repo_path must be a string", "INVALID_ARGUMENT")
81
- if not isinstance(git_context, bool):
82
- return _err("git_context must be boolean", "INVALID_ARGUMENT")
83
- args = [repo_path, "--compact"]
84
- if git_context:
85
- args.append("--git-context")
86
- return _execute(args)
104
+ _raw = repo_path
105
+ try:
106
+ if not isinstance(repo_path, str):
107
+ return _err("repo_path must be a string", "INVALID_ARGUMENT")
108
+ if not isinstance(git_context, bool):
109
+ return _err("git_context must be boolean", "INVALID_ARGUMENT")
110
+ repo_path = _normalize_repo_path(repo_path)
111
+ args = [repo_path, "--compact"]
112
+ if git_context:
113
+ args.append("--git-context")
114
+ return _execute(args)
115
+ except Exception as exc:
116
+ return _err(
117
+ f"Internal error: {type(exc).__name__}: {exc} — repo_path recibido: {_raw}",
118
+ "INTERNAL_ERROR",
119
+ )
87
120
 
88
121
 
89
122
  @mcp.tool()
@@ -99,14 +132,22 @@ def get_agent_context(repo_path: str = ".", git_context: bool = False) -> dict:
99
132
  repo_path: absolute path to the repository (default: current working directory).
100
133
  git_context: include git log and branch context in the analysis.
101
134
  """
102
- if not isinstance(repo_path, str):
103
- return _err("repo_path must be a string", "INVALID_ARGUMENT")
104
- if not isinstance(git_context, bool):
105
- return _err("git_context must be boolean", "INVALID_ARGUMENT")
106
- args = [repo_path, "--agent"]
107
- if git_context:
108
- args.append("--git-context")
109
- return _execute(args)
135
+ _raw = repo_path
136
+ try:
137
+ if not isinstance(repo_path, str):
138
+ return _err("repo_path must be a string", "INVALID_ARGUMENT")
139
+ if not isinstance(git_context, bool):
140
+ return _err("git_context must be boolean", "INVALID_ARGUMENT")
141
+ repo_path = _normalize_repo_path(repo_path)
142
+ args = [repo_path, "--agent"]
143
+ if git_context:
144
+ args.append("--git-context")
145
+ return _execute(args)
146
+ except Exception as exc:
147
+ return _err(
148
+ f"Internal error: {type(exc).__name__}: {exc} — repo_path recibido: {_raw}",
149
+ "INTERNAL_ERROR",
150
+ )
110
151
 
111
152
 
112
153
  @mcp.tool()
@@ -125,9 +166,17 @@ def get_endpoints(repo_path: str = ".") -> dict:
125
166
  @Authenticated, @PreAuthorize, @Secured, @SecurityRequirement, @M3FiltroSeguridad.
126
167
  repo_path: absolute path to the repository (default: current working directory).
127
168
  """
128
- if not isinstance(repo_path, str):
129
- return _err("repo_path must be a string", "INVALID_ARGUMENT")
130
- return _execute(["endpoints", repo_path])
169
+ _raw = repo_path
170
+ try:
171
+ if not isinstance(repo_path, str):
172
+ return _err("repo_path must be a string", "INVALID_ARGUMENT")
173
+ repo_path = _normalize_repo_path(repo_path)
174
+ return _execute(["endpoints", repo_path])
175
+ except Exception as exc:
176
+ return _err(
177
+ f"Internal error: {type(exc).__name__}: {exc} — repo_path recibido: {_raw}",
178
+ "INTERNAL_ERROR",
179
+ )
131
180
 
132
181
 
133
182
  @mcp.tool()
@@ -138,12 +187,20 @@ def get_module_context(repo_path: str = ".", module: str = "") -> dict:
138
187
  repo_path: absolute path to the repository root.
139
188
  module: subdirectory name relative to repo_path (e.g. 'src/auth', 'api', 'core').
140
189
  """
141
- if not isinstance(repo_path, str):
142
- return _err("repo_path must be a string", "INVALID_ARGUMENT")
143
- if not isinstance(module, str) or not module.strip():
144
- return _err("module must be a non-empty string", "INVALID_ARGUMENT")
145
- module_path = os.path.join(repo_path, module)
146
- return _execute([module_path, "--compact"])
190
+ _raw = repo_path
191
+ try:
192
+ if not isinstance(repo_path, str):
193
+ return _err("repo_path must be a string", "INVALID_ARGUMENT")
194
+ if not isinstance(module, str) or not module.strip():
195
+ return _err("module must be a non-empty string", "INVALID_ARGUMENT")
196
+ repo_path = _normalize_repo_path(repo_path)
197
+ module_path = repo_path.rstrip("/") + "/" + module.strip("/")
198
+ return _execute([module_path, "--compact"])
199
+ except Exception as exc:
200
+ return _err(
201
+ f"Internal error: {type(exc).__name__}: {exc} — repo_path recibido: {_raw}",
202
+ "INTERNAL_ERROR",
203
+ )
147
204
 
148
205
 
149
206
  @mcp.tool()
@@ -154,11 +211,19 @@ def get_delta(repo_path: str = ".", since: str = "HEAD~1") -> dict:
154
211
  repo_path: absolute path to the repository (default: current working directory).
155
212
  since: git ref to diff against (e.g. HEAD~3, main, origin/main).
156
213
  """
157
- if not isinstance(repo_path, str):
158
- return _err("repo_path must be a string", "INVALID_ARGUMENT")
159
- if not isinstance(since, str) or not since.strip():
160
- return _err("since must be a non-empty git ref", "INVALID_ARGUMENT")
161
- return _execute(["prepare-context", "delta", repo_path, "--since", since])
214
+ _raw = repo_path
215
+ try:
216
+ if not isinstance(repo_path, str):
217
+ return _err("repo_path must be a string", "INVALID_ARGUMENT")
218
+ if not isinstance(since, str) or not since.strip():
219
+ return _err("since must be a non-empty git ref", "INVALID_ARGUMENT")
220
+ repo_path = _normalize_repo_path(repo_path)
221
+ return _execute(["prepare-context", "delta", repo_path, "--since", since])
222
+ except Exception as exc:
223
+ return _err(
224
+ f"Internal error: {type(exc).__name__}: {exc} — repo_path recibido: {_raw}",
225
+ "INTERNAL_ERROR",
226
+ )
162
227
 
163
228
 
164
229
  @mcp.tool()
@@ -175,9 +240,17 @@ def get_ir_summary(repo_path: str = ".") -> dict:
175
240
 
176
241
  repo_path: absolute path to the Java repository (default: current working directory).
177
242
  """
178
- if not isinstance(repo_path, str):
179
- return _err("repo_path must be a string", "INVALID_ARGUMENT")
180
- return _execute(["repo-ir", repo_path, "--summary-only"])
243
+ _raw = repo_path
244
+ try:
245
+ if not isinstance(repo_path, str):
246
+ return _err("repo_path must be a string", "INVALID_ARGUMENT")
247
+ repo_path = _normalize_repo_path(repo_path)
248
+ return _execute(["repo-ir", repo_path, "--summary-only"])
249
+ except Exception as exc:
250
+ return _err(
251
+ f"Internal error: {type(exc).__name__}: {exc} — repo_path recibido: {_raw}",
252
+ "INTERNAL_ERROR",
253
+ )
181
254
 
182
255
 
183
256
  @mcp.tool()
@@ -190,12 +263,20 @@ def fix_bug_context(repo_path: str = ".", symptom: str = "") -> dict:
190
263
  symptom: optional error message or class name to focus the file ranking
191
264
  (e.g. "NullPointerException in EstructuraRrHhRestController").
192
265
  """
193
- if not isinstance(repo_path, str):
194
- return _err("repo_path must be a string", "INVALID_ARGUMENT")
195
- args = ["prepare-context", "fix-bug", repo_path]
196
- if symptom and isinstance(symptom, str) and symptom.strip():
197
- args.extend(["--symptom", symptom.strip()])
198
- return _execute(args)
266
+ _raw = repo_path
267
+ try:
268
+ if not isinstance(repo_path, str):
269
+ return _err("repo_path must be a string", "INVALID_ARGUMENT")
270
+ repo_path = _normalize_repo_path(repo_path)
271
+ args = ["prepare-context", "fix-bug", repo_path]
272
+ if symptom and isinstance(symptom, str) and symptom.strip():
273
+ args.extend(["--symptom", symptom.strip()])
274
+ return _execute(args)
275
+ except Exception as exc:
276
+ return _err(
277
+ f"Internal error: {type(exc).__name__}: {exc} — repo_path recibido: {_raw}",
278
+ "INTERNAL_ERROR",
279
+ )
199
280
 
200
281
 
201
282
  @mcp.tool()
@@ -208,12 +289,20 @@ def review_pr_context(repo_path: str = ".", since: str = "") -> dict:
208
289
  since: git ref to diff against (e.g. HEAD~3, main, origin/main).
209
290
  If omitted, diffs against uncommitted changes or HEAD~1 fallback.
210
291
  """
211
- if not isinstance(repo_path, str):
212
- return _err("repo_path must be a string", "INVALID_ARGUMENT")
213
- args = ["prepare-context", "review-pr", repo_path]
214
- if since and isinstance(since, str) and since.strip():
215
- args.extend(["--since", since.strip()])
216
- return _execute(args)
292
+ _raw = repo_path
293
+ try:
294
+ if not isinstance(repo_path, str):
295
+ return _err("repo_path must be a string", "INVALID_ARGUMENT")
296
+ repo_path = _normalize_repo_path(repo_path)
297
+ args = ["prepare-context", "review-pr", repo_path]
298
+ if since and isinstance(since, str) and since.strip():
299
+ args.extend(["--since", since.strip()])
300
+ return _execute(args)
301
+ except Exception as exc:
302
+ return _err(
303
+ f"Internal error: {type(exc).__name__}: {exc} — repo_path recibido: {_raw}",
304
+ "INTERNAL_ERROR",
305
+ )
217
306
 
218
307
 
219
308
  @mcp.tool()
@@ -223,9 +312,17 @@ def onboard_context(repo_path: str = ".") -> dict:
223
312
  Maps to: sourcecode prepare-context onboard <repo_path>
224
313
  repo_path: absolute path to the repository (default: current working directory).
225
314
  """
226
- if not isinstance(repo_path, str):
227
- return _err("repo_path must be a string", "INVALID_ARGUMENT")
228
- return _execute(["prepare-context", "onboard", repo_path])
315
+ _raw = repo_path
316
+ try:
317
+ if not isinstance(repo_path, str):
318
+ return _err("repo_path must be a string", "INVALID_ARGUMENT")
319
+ repo_path = _normalize_repo_path(repo_path)
320
+ return _execute(["prepare-context", "onboard", repo_path])
321
+ except Exception as exc:
322
+ return _err(
323
+ f"Internal error: {type(exc).__name__}: {exc} — repo_path recibido: {_raw}",
324
+ "INTERNAL_ERROR",
325
+ )
229
326
 
230
327
 
231
328
  @mcp.tool()
@@ -236,9 +333,17 @@ def explain_context(repo_path: str = ".") -> dict:
236
333
  Returns: project summary, architecture, entry points, key dependencies.
237
334
  repo_path: absolute path to the repository (default: current working directory).
238
335
  """
239
- if not isinstance(repo_path, str):
240
- return _err("repo_path must be a string", "INVALID_ARGUMENT")
241
- return _execute(["prepare-context", "explain", repo_path])
336
+ _raw = repo_path
337
+ try:
338
+ if not isinstance(repo_path, str):
339
+ return _err("repo_path must be a string", "INVALID_ARGUMENT")
340
+ repo_path = _normalize_repo_path(repo_path)
341
+ return _execute(["prepare-context", "explain", repo_path])
342
+ except Exception as exc:
343
+ return _err(
344
+ f"Internal error: {type(exc).__name__}: {exc} — repo_path recibido: {_raw}",
345
+ "INTERNAL_ERROR",
346
+ )
242
347
 
243
348
 
244
349
  @mcp.tool()
@@ -249,9 +354,17 @@ def refactor_context(repo_path: str = ".") -> dict:
249
354
  Returns: structural issues, coupling hotspots, improvement opportunities.
250
355
  repo_path: absolute path to the repository (default: current working directory).
251
356
  """
252
- if not isinstance(repo_path, str):
253
- return _err("repo_path must be a string", "INVALID_ARGUMENT")
254
- return _execute(["prepare-context", "refactor", repo_path])
357
+ _raw = repo_path
358
+ try:
359
+ if not isinstance(repo_path, str):
360
+ return _err("repo_path must be a string", "INVALID_ARGUMENT")
361
+ repo_path = _normalize_repo_path(repo_path)
362
+ return _execute(["prepare-context", "refactor", repo_path])
363
+ except Exception as exc:
364
+ return _err(
365
+ f"Internal error: {type(exc).__name__}: {exc} — repo_path recibido: {_raw}",
366
+ "INTERNAL_ERROR",
367
+ )
255
368
 
256
369
 
257
370
  @mcp.tool()
@@ -260,15 +373,45 @@ def generate_tests_context(repo_path: str = ".", include_all: bool = False) -> d
260
373
 
261
374
  Maps to: sourcecode prepare-context generate-tests <repo_path> [--all]
262
375
  Returns: test_gaps list of untested files ranked by risk.
376
+ On large repos (>2000 classes) analysis is bounded by SOURCECODE_TESTS_TIMEOUT_MS
377
+ (default: 15000 ms). If timeout elapses, returns truncated=true with partial results.
263
378
  repo_path: absolute path to the repository (default: current working directory).
264
379
  include_all: return full test_gaps list without truncating to top 20.
265
380
  """
266
- if not isinstance(repo_path, str):
267
- return _err("repo_path must be a string", "INVALID_ARGUMENT")
268
- args = ["prepare-context", "generate-tests", repo_path]
269
- if include_all:
270
- args.append("--all")
271
- return _execute(args)
381
+ _raw = repo_path
382
+ try:
383
+ if not isinstance(repo_path, str):
384
+ return _err("repo_path must be a string", "INVALID_ARGUMENT")
385
+ if not isinstance(include_all, bool):
386
+ return _err("include_all must be boolean", "INVALID_ARGUMENT")
387
+ repo_path = _normalize_repo_path(repo_path)
388
+ args = ["prepare-context", "generate-tests", repo_path]
389
+ if include_all:
390
+ args.append("--all")
391
+
392
+ # P0-3: timeout guard — large repos can stall the stdio transport indefinitely.
393
+ timeout_ms = int(os.environ.get("SOURCECODE_TESTS_TIMEOUT_MS", str(_DEFAULT_TESTS_TIMEOUT_MS)))
394
+ timeout_s = timeout_ms / 1000.0
395
+
396
+ executor = concurrent.futures.ThreadPoolExecutor(max_workers=1)
397
+ future = executor.submit(_execute, args)
398
+ done, _not_done = concurrent.futures.wait([future], timeout=timeout_s)
399
+ if _not_done:
400
+ executor.shutdown(wait=False)
401
+ return _ok({
402
+ "truncated": True,
403
+ "truncated_reason": f"timeout_{timeout_ms // 1000}s" if timeout_ms >= 1000 else f"timeout_{timeout_ms}ms",
404
+ "files_analyzed": 0,
405
+ "results": [],
406
+ })
407
+ executor.shutdown(wait=False)
408
+ return future.result()
409
+
410
+ except Exception as exc:
411
+ return _err(
412
+ f"Internal error: {type(exc).__name__}: {exc} — repo_path recibido: {_raw}",
413
+ "INTERNAL_ERROR",
414
+ )
272
415
 
273
416
 
274
417
  @mcp.tool()
@@ -289,14 +432,22 @@ def get_impact_context(repo_path: str = ".", target: str = "", depth: int = 4) -
289
432
  repo_path: absolute path to the Java repository (default: current working directory).
290
433
  depth: BFS depth for indirect caller traversal (1–8, default: 4).
291
434
  """
292
- if not isinstance(repo_path, str):
293
- return _err("repo_path must be a string", "INVALID_ARGUMENT")
294
- if not isinstance(target, str) or not target.strip():
295
- return _err("target must be a non-empty class name or FQN", "INVALID_ARGUMENT")
296
- if not isinstance(depth, int) or depth < 1 or depth > 8:
297
- return _err("depth must be an integer between 1 and 8", "INVALID_ARGUMENT")
298
- args = ["impact", target.strip(), repo_path, "--depth", str(depth)]
299
- return _execute(args)
435
+ _raw = repo_path
436
+ try:
437
+ if not isinstance(repo_path, str):
438
+ return _err("repo_path must be a string", "INVALID_ARGUMENT")
439
+ if not isinstance(target, str) or not target.strip():
440
+ return _err("target must be a non-empty class name or FQN", "INVALID_ARGUMENT")
441
+ if not isinstance(depth, int) or depth < 1 or depth > 8:
442
+ return _err("depth must be an integer between 1 and 8", "INVALID_ARGUMENT")
443
+ repo_path = _normalize_repo_path(repo_path)
444
+ args = ["impact", target.strip(), repo_path, "--depth", str(depth)]
445
+ return _execute(args)
446
+ except Exception as exc:
447
+ return _err(
448
+ f"Internal error: {type(exc).__name__}: {exc} — repo_path recibido: {_raw}",
449
+ "INTERNAL_ERROR",
450
+ )
300
451
 
301
452
 
302
453
  _TELEMETRY_ACTIONS = frozenset({"status", "enable", "disable"})
@@ -556,11 +556,11 @@ class TestFlagSemantics:
556
556
  """Flag interactions are honest, deterministic, and clearly documented."""
557
557
 
558
558
  def test_compact_full_conflict_is_error(self, keycloak_like_repo: Path) -> None:
559
- """--compact --full must exit 2 with a clear error message."""
559
+ """--compact --full must exit 1 with a clear error message (P0-1 fix: all errors → 1)."""
560
560
  result = runner.invoke(
561
561
  app, [str(keycloak_like_repo), "--compact", "--full"]
562
562
  )
563
- assert result.exit_code == 2
563
+ assert result.exit_code == 1
564
564
  assert "mutually exclusive" in result.output.lower() or \
565
565
  "mutually exclusive" in (result.stderr or "").lower()
566
566