sourcecode 1.26.0__tar.gz → 1.27.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (189) hide show
  1. {sourcecode-1.26.0 → sourcecode-1.27.0}/PKG-INFO +3 -3
  2. {sourcecode-1.26.0 → sourcecode-1.27.0}/README.md +2 -2
  3. {sourcecode-1.26.0 → sourcecode-1.27.0}/pyproject.toml +1 -1
  4. {sourcecode-1.26.0 → sourcecode-1.27.0}/src/sourcecode/__init__.py +1 -1
  5. {sourcecode-1.26.0 → sourcecode-1.27.0}/src/sourcecode/cli.py +3 -0
  6. {sourcecode-1.26.0 → sourcecode-1.27.0}/src/sourcecode/prepare_context.py +130 -0
  7. {sourcecode-1.26.0 → sourcecode-1.27.0}/src/sourcecode/serializer.py +68 -77
  8. {sourcecode-1.26.0 → sourcecode-1.27.0}/tests/test_block5_quality.py +40 -42
  9. {sourcecode-1.26.0 → sourcecode-1.27.0}/tests/test_pipeline_integrity.py +10 -9
  10. {sourcecode-1.26.0 → sourcecode-1.27.0}/.agents/skills/source-command-gsd-join-discord/SKILL.md +0 -0
  11. {sourcecode-1.26.0 → sourcecode-1.27.0}/.agents/skills/source-command-gsd-review-backlog/SKILL.md +0 -0
  12. {sourcecode-1.26.0 → sourcecode-1.27.0}/.agents/skills/source-command-gsd-workstreams/SKILL.md +0 -0
  13. {sourcecode-1.26.0 → sourcecode-1.27.0}/.continue-here.md +0 -0
  14. {sourcecode-1.26.0 → sourcecode-1.27.0}/.github/workflows/build-windows.yml +0 -0
  15. {sourcecode-1.26.0 → sourcecode-1.27.0}/.gitignore +0 -0
  16. {sourcecode-1.26.0 → sourcecode-1.27.0}/.ruff.toml +0 -0
  17. {sourcecode-1.26.0 → sourcecode-1.27.0}/CONTRIBUTING.md +0 -0
  18. {sourcecode-1.26.0 → sourcecode-1.27.0}/LICENSE +0 -0
  19. {sourcecode-1.26.0 → sourcecode-1.27.0}/SECURITY.md +0 -0
  20. {sourcecode-1.26.0 → sourcecode-1.27.0}/docs/privacy.md +0 -0
  21. {sourcecode-1.26.0 → sourcecode-1.27.0}/docs/schema.md +0 -0
  22. {sourcecode-1.26.0 → sourcecode-1.27.0}/raw +0 -0
  23. {sourcecode-1.26.0 → sourcecode-1.27.0}/run_cli.py +0 -0
  24. {sourcecode-1.26.0 → sourcecode-1.27.0}/src/sourcecode/adaptive_scanner.py +0 -0
  25. {sourcecode-1.26.0 → sourcecode-1.27.0}/src/sourcecode/architecture_analyzer.py +0 -0
  26. {sourcecode-1.26.0 → sourcecode-1.27.0}/src/sourcecode/architecture_summary.py +0 -0
  27. {sourcecode-1.26.0 → sourcecode-1.27.0}/src/sourcecode/ast_extractor.py +0 -0
  28. {sourcecode-1.26.0 → sourcecode-1.27.0}/src/sourcecode/classifier.py +0 -0
  29. {sourcecode-1.26.0 → sourcecode-1.27.0}/src/sourcecode/code_notes_analyzer.py +0 -0
  30. {sourcecode-1.26.0 → sourcecode-1.27.0}/src/sourcecode/confidence_analyzer.py +0 -0
  31. {sourcecode-1.26.0 → sourcecode-1.27.0}/src/sourcecode/context_scorer.py +0 -0
  32. {sourcecode-1.26.0 → sourcecode-1.27.0}/src/sourcecode/context_summarizer.py +0 -0
  33. {sourcecode-1.26.0 → sourcecode-1.27.0}/src/sourcecode/contract_model.py +0 -0
  34. {sourcecode-1.26.0 → sourcecode-1.27.0}/src/sourcecode/contract_pipeline.py +0 -0
  35. {sourcecode-1.26.0 → sourcecode-1.27.0}/src/sourcecode/coverage_parser.py +0 -0
  36. {sourcecode-1.26.0 → sourcecode-1.27.0}/src/sourcecode/dependency_analyzer.py +0 -0
  37. {sourcecode-1.26.0 → sourcecode-1.27.0}/src/sourcecode/detectors/__init__.py +0 -0
  38. {sourcecode-1.26.0 → sourcecode-1.27.0}/src/sourcecode/detectors/base.py +0 -0
  39. {sourcecode-1.26.0 → sourcecode-1.27.0}/src/sourcecode/detectors/csproj_parser.py +0 -0
  40. {sourcecode-1.26.0 → sourcecode-1.27.0}/src/sourcecode/detectors/dart.py +0 -0
  41. {sourcecode-1.26.0 → sourcecode-1.27.0}/src/sourcecode/detectors/dotnet.py +0 -0
  42. {sourcecode-1.26.0 → sourcecode-1.27.0}/src/sourcecode/detectors/elixir.py +0 -0
  43. {sourcecode-1.26.0 → sourcecode-1.27.0}/src/sourcecode/detectors/go.py +0 -0
  44. {sourcecode-1.26.0 → sourcecode-1.27.0}/src/sourcecode/detectors/heuristic.py +0 -0
  45. {sourcecode-1.26.0 → sourcecode-1.27.0}/src/sourcecode/detectors/hybrid.py +0 -0
  46. {sourcecode-1.26.0 → sourcecode-1.27.0}/src/sourcecode/detectors/java.py +0 -0
  47. {sourcecode-1.26.0 → sourcecode-1.27.0}/src/sourcecode/detectors/jvm_ext.py +0 -0
  48. {sourcecode-1.26.0 → sourcecode-1.27.0}/src/sourcecode/detectors/nodejs.py +0 -0
  49. {sourcecode-1.26.0 → sourcecode-1.27.0}/src/sourcecode/detectors/parsers.py +0 -0
  50. {sourcecode-1.26.0 → sourcecode-1.27.0}/src/sourcecode/detectors/php.py +0 -0
  51. {sourcecode-1.26.0 → sourcecode-1.27.0}/src/sourcecode/detectors/project.py +0 -0
  52. {sourcecode-1.26.0 → sourcecode-1.27.0}/src/sourcecode/detectors/python.py +0 -0
  53. {sourcecode-1.26.0 → sourcecode-1.27.0}/src/sourcecode/detectors/ruby.py +0 -0
  54. {sourcecode-1.26.0 → sourcecode-1.27.0}/src/sourcecode/detectors/rust.py +0 -0
  55. {sourcecode-1.26.0 → sourcecode-1.27.0}/src/sourcecode/detectors/systems.py +0 -0
  56. {sourcecode-1.26.0 → sourcecode-1.27.0}/src/sourcecode/detectors/terraform.py +0 -0
  57. {sourcecode-1.26.0 → sourcecode-1.27.0}/src/sourcecode/detectors/tooling.py +0 -0
  58. {sourcecode-1.26.0 → sourcecode-1.27.0}/src/sourcecode/doc_analyzer.py +0 -0
  59. {sourcecode-1.26.0 → sourcecode-1.27.0}/src/sourcecode/entrypoint_classifier.py +0 -0
  60. {sourcecode-1.26.0 → sourcecode-1.27.0}/src/sourcecode/env_analyzer.py +0 -0
  61. {sourcecode-1.26.0 → sourcecode-1.27.0}/src/sourcecode/file_classifier.py +0 -0
  62. {sourcecode-1.26.0 → sourcecode-1.27.0}/src/sourcecode/git_analyzer.py +0 -0
  63. {sourcecode-1.26.0 → sourcecode-1.27.0}/src/sourcecode/graph_analyzer.py +0 -0
  64. {sourcecode-1.26.0 → sourcecode-1.27.0}/src/sourcecode/metrics_analyzer.py +0 -0
  65. {sourcecode-1.26.0 → sourcecode-1.27.0}/src/sourcecode/progress.py +0 -0
  66. {sourcecode-1.26.0 → sourcecode-1.27.0}/src/sourcecode/ranking_engine.py +0 -0
  67. {sourcecode-1.26.0 → sourcecode-1.27.0}/src/sourcecode/redactor.py +0 -0
  68. {sourcecode-1.26.0 → sourcecode-1.27.0}/src/sourcecode/relevance_scorer.py +0 -0
  69. {sourcecode-1.26.0 → sourcecode-1.27.0}/src/sourcecode/repo_classifier.py +0 -0
  70. {sourcecode-1.26.0 → sourcecode-1.27.0}/src/sourcecode/runtime_classifier.py +0 -0
  71. {sourcecode-1.26.0 → sourcecode-1.27.0}/src/sourcecode/scanner.py +0 -0
  72. {sourcecode-1.26.0 → sourcecode-1.27.0}/src/sourcecode/schema.py +0 -0
  73. {sourcecode-1.26.0 → sourcecode-1.27.0}/src/sourcecode/semantic_analyzer.py +0 -0
  74. {sourcecode-1.26.0 → sourcecode-1.27.0}/src/sourcecode/summarizer.py +0 -0
  75. {sourcecode-1.26.0 → sourcecode-1.27.0}/src/sourcecode/telemetry/__init__.py +0 -0
  76. {sourcecode-1.26.0 → sourcecode-1.27.0}/src/sourcecode/telemetry/config.py +0 -0
  77. {sourcecode-1.26.0 → sourcecode-1.27.0}/src/sourcecode/telemetry/consent.py +0 -0
  78. {sourcecode-1.26.0 → sourcecode-1.27.0}/src/sourcecode/telemetry/events.py +0 -0
  79. {sourcecode-1.26.0 → sourcecode-1.27.0}/src/sourcecode/telemetry/filters.py +0 -0
  80. {sourcecode-1.26.0 → sourcecode-1.27.0}/src/sourcecode/telemetry/transport.py +0 -0
  81. {sourcecode-1.26.0 → sourcecode-1.27.0}/src/sourcecode/tree_utils.py +0 -0
  82. {sourcecode-1.26.0 → sourcecode-1.27.0}/src/sourcecode/workspace.py +0 -0
  83. {sourcecode-1.26.0 → sourcecode-1.27.0}/tests/__init__.py +0 -0
  84. {sourcecode-1.26.0 → sourcecode-1.27.0}/tests/conftest.py +0 -0
  85. {sourcecode-1.26.0 → sourcecode-1.27.0}/tests/fixtures/coverage.xml +0 -0
  86. {sourcecode-1.26.0 → sourcecode-1.27.0}/tests/fixtures/fastapi_app/pyproject.toml +0 -0
  87. {sourcecode-1.26.0 → sourcecode-1.27.0}/tests/fixtures/fastapi_app/src/main.py +0 -0
  88. {sourcecode-1.26.0 → sourcecode-1.27.0}/tests/fixtures/go_service/cmd/api/main.go +0 -0
  89. {sourcecode-1.26.0 → sourcecode-1.27.0}/tests/fixtures/go_service/go.mod +0 -0
  90. {sourcecode-1.26.0 → sourcecode-1.27.0}/tests/fixtures/jacoco.xml +0 -0
  91. {sourcecode-1.26.0 → sourcecode-1.27.0}/tests/fixtures/latin1_sample.java +0 -0
  92. {sourcecode-1.26.0 → sourcecode-1.27.0}/tests/fixtures/latin1_sample_iso.java +0 -0
  93. {sourcecode-1.26.0 → sourcecode-1.27.0}/tests/fixtures/lcov.info +0 -0
  94. {sourcecode-1.26.0 → sourcecode-1.27.0}/tests/fixtures/nextjs_app/app/page.tsx +0 -0
  95. {sourcecode-1.26.0 → sourcecode-1.27.0}/tests/fixtures/nextjs_app/package.json +0 -0
  96. {sourcecode-1.26.0 → sourcecode-1.27.0}/tests/fixtures/nextjs_app/pnpm-lock.yaml +0 -0
  97. {sourcecode-1.26.0 → sourcecode-1.27.0}/tests/fixtures/pnpm_monorepo/apps/web/app/page.tsx +0 -0
  98. {sourcecode-1.26.0 → sourcecode-1.27.0}/tests/fixtures/pnpm_monorepo/apps/web/package.json +0 -0
  99. {sourcecode-1.26.0 → sourcecode-1.27.0}/tests/fixtures/pnpm_monorepo/packages/api/main.py +0 -0
  100. {sourcecode-1.26.0 → sourcecode-1.27.0}/tests/fixtures/pnpm_monorepo/packages/api/pyproject.toml +0 -0
  101. {sourcecode-1.26.0 → sourcecode-1.27.0}/tests/fixtures/pnpm_monorepo/pnpm-workspace.yaml +0 -0
  102. {sourcecode-1.26.0 → sourcecode-1.27.0}/tests/fixtures/spring_boot_minimal/pom.xml +0 -0
  103. {sourcecode-1.26.0 → sourcecode-1.27.0}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/ausente/application/service/FindAusenteService.java +0 -0
  104. {sourcecode-1.26.0 → sourcecode-1.27.0}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/ausente/domain/entities/Ausente.java +0 -0
  105. {sourcecode-1.26.0 → sourcecode-1.27.0}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/ausente/infrastructure/rest/AusenteRestController.java +0 -0
  106. {sourcecode-1.26.0 → sourcecode-1.27.0}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/autocoberturas/application/service/FindAutocoberturasService.java +0 -0
  107. {sourcecode-1.26.0 → sourcecode-1.27.0}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/autocoberturas/domain/entities/Autocoberturas.java +0 -0
  108. {sourcecode-1.26.0 → sourcecode-1.27.0}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/autocoberturas/infrastructure/rest/AutocoberturasRestController.java +0 -0
  109. {sourcecode-1.26.0 → sourcecode-1.27.0}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/calendarioTrabajador/application/service/FindCalendarioTrabajadorService.java +0 -0
  110. {sourcecode-1.26.0 → sourcecode-1.27.0}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/calendarioTrabajador/domain/entities/CalendarioTrabajador.java +0 -0
  111. {sourcecode-1.26.0 → sourcecode-1.27.0}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/calendarioTrabajador/infrastructure/rest/CalendarioTrabajadorRestController.java +0 -0
  112. {sourcecode-1.26.0 → sourcecode-1.27.0}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/departamento/application/service/FindDepartamentoService.java +0 -0
  113. {sourcecode-1.26.0 → sourcecode-1.27.0}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/departamento/domain/entities/Departamento.java +0 -0
  114. {sourcecode-1.26.0 → sourcecode-1.27.0}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/departamento/infrastructure/rest/DepartamentoRestController.java +0 -0
  115. {sourcecode-1.26.0 → sourcecode-1.27.0}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/empleado/application/service/FindEmpleadoService.java +0 -0
  116. {sourcecode-1.26.0 → sourcecode-1.27.0}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/empleado/domain/entities/Empleado.java +0 -0
  117. {sourcecode-1.26.0 → sourcecode-1.27.0}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/empleado/infrastructure/rest/EmpleadoRestController.java +0 -0
  118. {sourcecode-1.26.0 → sourcecode-1.27.0}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/demo/DemoApplication.java +0 -0
  119. {sourcecode-1.26.0 → sourcecode-1.27.0}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/demo/config/FilterConfig.java +0 -0
  120. {sourcecode-1.26.0 → sourcecode-1.27.0}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/demo/domain/Health.java +0 -0
  121. {sourcecode-1.26.0 → sourcecode-1.27.0}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/demo/mapper/HealthMapper.java +0 -0
  122. {sourcecode-1.26.0 → sourcecode-1.27.0}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/demo/repository/HealthRepository.java +0 -0
  123. {sourcecode-1.26.0 → sourcecode-1.27.0}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/demo/service/HealthService.java +0 -0
  124. {sourcecode-1.26.0 → sourcecode-1.27.0}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/demo/web/HealthRestController.java +0 -0
  125. {sourcecode-1.26.0 → sourcecode-1.27.0}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/demo/web/NominaRestController.java +0 -0
  126. {sourcecode-1.26.0 → sourcecode-1.27.0}/tests/fixtures/spring_boot_minimal/src/main/resources/application-dev.yml +0 -0
  127. {sourcecode-1.26.0 → sourcecode-1.27.0}/tests/fixtures/spring_boot_minimal/src/main/resources/application.yml +0 -0
  128. {sourcecode-1.26.0 → sourcecode-1.27.0}/tests/fixtures/spring_boot_minimal/src/main/resources/mapper/HealthMapper.xml +0 -0
  129. {sourcecode-1.26.0 → sourcecode-1.27.0}/tests/test_architecture_analyzer.py +0 -0
  130. {sourcecode-1.26.0 → sourcecode-1.27.0}/tests/test_architecture_summary.py +0 -0
  131. {sourcecode-1.26.0 → sourcecode-1.27.0}/tests/test_ast_extractor.py +0 -0
  132. {sourcecode-1.26.0 → sourcecode-1.27.0}/tests/test_block1_reliability.py +0 -0
  133. {sourcecode-1.26.0 → sourcecode-1.27.0}/tests/test_block2_coverage.py +0 -0
  134. {sourcecode-1.26.0 → sourcecode-1.27.0}/tests/test_bug_fixes_v16.py +0 -0
  135. {sourcecode-1.26.0 → sourcecode-1.27.0}/tests/test_classifier.py +0 -0
  136. {sourcecode-1.26.0 → sourcecode-1.27.0}/tests/test_cli.py +0 -0
  137. {sourcecode-1.26.0 → sourcecode-1.27.0}/tests/test_code_notes_analyzer.py +0 -0
  138. {sourcecode-1.26.0 → sourcecode-1.27.0}/tests/test_context_scorer.py +0 -0
  139. {sourcecode-1.26.0 → sourcecode-1.27.0}/tests/test_contract_pipeline.py +0 -0
  140. {sourcecode-1.26.0 → sourcecode-1.27.0}/tests/test_coverage_parser.py +0 -0
  141. {sourcecode-1.26.0 → sourcecode-1.27.0}/tests/test_cross_consistency.py +0 -0
  142. {sourcecode-1.26.0 → sourcecode-1.27.0}/tests/test_dependency_analyzer_node_python.py +0 -0
  143. {sourcecode-1.26.0 → sourcecode-1.27.0}/tests/test_dependency_analyzer_polyglot.py +0 -0
  144. {sourcecode-1.26.0 → sourcecode-1.27.0}/tests/test_dependency_schema.py +0 -0
  145. {sourcecode-1.26.0 → sourcecode-1.27.0}/tests/test_detector_dotnet.py +0 -0
  146. {sourcecode-1.26.0 → sourcecode-1.27.0}/tests/test_detector_go_rust_java.py +0 -0
  147. {sourcecode-1.26.0 → sourcecode-1.27.0}/tests/test_detector_nodejs.py +0 -0
  148. {sourcecode-1.26.0 → sourcecode-1.27.0}/tests/test_detector_php_ruby_dart.py +0 -0
  149. {sourcecode-1.26.0 → sourcecode-1.27.0}/tests/test_detector_python.py +0 -0
  150. {sourcecode-1.26.0 → sourcecode-1.27.0}/tests/test_detector_universal_managed.py +0 -0
  151. {sourcecode-1.26.0 → sourcecode-1.27.0}/tests/test_detector_universal_systems.py +0 -0
  152. {sourcecode-1.26.0 → sourcecode-1.27.0}/tests/test_detectors_base.py +0 -0
  153. {sourcecode-1.26.0 → sourcecode-1.27.0}/tests/test_doc_analyzer_jsdom.py +0 -0
  154. {sourcecode-1.26.0 → sourcecode-1.27.0}/tests/test_doc_analyzer_python.py +0 -0
  155. {sourcecode-1.26.0 → sourcecode-1.27.0}/tests/test_encoding_regression.py +0 -0
  156. {sourcecode-1.26.0 → sourcecode-1.27.0}/tests/test_graph_analyzer_polyglot.py +0 -0
  157. {sourcecode-1.26.0 → sourcecode-1.27.0}/tests/test_graph_analyzer_python_node.py +0 -0
  158. {sourcecode-1.26.0 → sourcecode-1.27.0}/tests/test_graph_schema.py +0 -0
  159. {sourcecode-1.26.0 → sourcecode-1.27.0}/tests/test_hybrid_inference.py +0 -0
  160. {sourcecode-1.26.0 → sourcecode-1.27.0}/tests/test_integration.py +0 -0
  161. {sourcecode-1.26.0 → sourcecode-1.27.0}/tests/test_integration_dependencies.py +0 -0
  162. {sourcecode-1.26.0 → sourcecode-1.27.0}/tests/test_integration_detection.py +0 -0
  163. {sourcecode-1.26.0 → sourcecode-1.27.0}/tests/test_integration_docs.py +0 -0
  164. {sourcecode-1.26.0 → sourcecode-1.27.0}/tests/test_integration_graph_modules.py +0 -0
  165. {sourcecode-1.26.0 → sourcecode-1.27.0}/tests/test_integration_lqn.py +0 -0
  166. {sourcecode-1.26.0 → sourcecode-1.27.0}/tests/test_integration_metrics.py +0 -0
  167. {sourcecode-1.26.0 → sourcecode-1.27.0}/tests/test_integration_multistack.py +0 -0
  168. {sourcecode-1.26.0 → sourcecode-1.27.0}/tests/test_integration_semantics.py +0 -0
  169. {sourcecode-1.26.0 → sourcecode-1.27.0}/tests/test_integration_universal.py +0 -0
  170. {sourcecode-1.26.0 → sourcecode-1.27.0}/tests/test_java_spring_integration.py +0 -0
  171. {sourcecode-1.26.0 → sourcecode-1.27.0}/tests/test_metrics_analyzer.py +0 -0
  172. {sourcecode-1.26.0 → sourcecode-1.27.0}/tests/test_packaging.py +0 -0
  173. {sourcecode-1.26.0 → sourcecode-1.27.0}/tests/test_phase1_improvements.py +0 -0
  174. {sourcecode-1.26.0 → sourcecode-1.27.0}/tests/test_real_projects.py +0 -0
  175. {sourcecode-1.26.0 → sourcecode-1.27.0}/tests/test_redactor.py +0 -0
  176. {sourcecode-1.26.0 → sourcecode-1.27.0}/tests/test_scanner.py +0 -0
  177. {sourcecode-1.26.0 → sourcecode-1.27.0}/tests/test_schema.py +0 -0
  178. {sourcecode-1.26.0 → sourcecode-1.27.0}/tests/test_schema_normalization.py +0 -0
  179. {sourcecode-1.26.0 → sourcecode-1.27.0}/tests/test_semantic_analyzer_node.py +0 -0
  180. {sourcecode-1.26.0 → sourcecode-1.27.0}/tests/test_semantic_analyzer_python.py +0 -0
  181. {sourcecode-1.26.0 → sourcecode-1.27.0}/tests/test_semantic_import_resolution.py +0 -0
  182. {sourcecode-1.26.0 → sourcecode-1.27.0}/tests/test_semantic_schema.py +0 -0
  183. {sourcecode-1.26.0 → sourcecode-1.27.0}/tests/test_signal_hierarchy.py +0 -0
  184. {sourcecode-1.26.0 → sourcecode-1.27.0}/tests/test_summarizer.py +0 -0
  185. {sourcecode-1.26.0 → sourcecode-1.27.0}/tests/test_surface_honesty.py +0 -0
  186. {sourcecode-1.26.0 → sourcecode-1.27.0}/tests/test_task_differentiation.py +0 -0
  187. {sourcecode-1.26.0 → sourcecode-1.27.0}/tests/test_telemetry.py +0 -0
  188. {sourcecode-1.26.0 → sourcecode-1.27.0}/tests/test_v1_10_regressions.py +0 -0
  189. {sourcecode-1.26.0 → sourcecode-1.27.0}/tests/test_workspace_analyzer.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: sourcecode
3
- Version: 1.26.0
3
+ Version: 1.27.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.26.0-blue)
224
+ ![Version](https://img.shields.io/badge/version-1.27.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.26.0
258
+ # sourcecode 1.27.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.26.0-blue)
5
+ ![Version](https://img.shields.io/badge/version-1.27.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.26.0
39
+ # sourcecode 1.27.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.26.0"
7
+ version = "1.27.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.26.0"
3
+ __version__ = "1.27.0"
@@ -1777,6 +1777,7 @@ def prepare_context_cmd(
1777
1777
  # Hard error — emit structured error JSON and exit, skip normal delta fields
1778
1778
  _err_out: dict[str, Any] = {
1779
1779
  "task": output.task,
1780
+ "ci_decision": output.ci_decision or "git_ref_error",
1780
1781
  "error": output.error_code,
1781
1782
  "since": output.since,
1782
1783
  "message": output.error_message,
@@ -1792,6 +1793,8 @@ def prepare_context_cmd(
1792
1793
  _sys.stdout.buffer.write(b"\n")
1793
1794
  _sys.stdout.buffer.flush()
1794
1795
  raise typer.Exit(code=1)
1796
+ if output.ci_decision:
1797
+ out["ci_decision"] = output.ci_decision
1795
1798
  if output.since:
1796
1799
  out["since"] = output.since
1797
1800
  if output.impact_summary:
@@ -337,6 +337,12 @@ class TaskOutput:
337
337
  error_code: Optional[str] = None
338
338
  error_message: Optional[str] = None
339
339
  error_hints: list[str] = field(default_factory=list)
340
+ # CI decision state machine — machine-decidable signal
341
+ ci_decision: Optional[str] = None # "no_changes" | "analysis_success" | "git_ref_error"
342
+ # git baseline resolution metadata
343
+ resolved_since_ref: Optional[str] = None # actual ref/hash used for the diff
344
+ resolution_path: Optional[str] = None # "exact_local_ref"|"remote_tracking_ref"|"symbolic_ref"|"head_minus_1_fallback"|"uncommitted_changes"|"unresolvable"
345
+ diff_validation_status: Optional[str] = None # "valid_non_empty"|"valid_empty"|"invalid_ref"
340
346
 
341
347
 
342
348
  # ─────────────────────────────────────────────────────────────────────────────
@@ -648,6 +654,7 @@ class TaskContextBuilder:
648
654
  error_message=f"Git reference '{since}' does not exist in this repository.",
649
655
  error_hints=_hints,
650
656
  gaps=[f"Cannot compute delta: git ref '{since}' not found."] + _hints,
657
+ ci_decision="git_ref_error",
651
658
  )
652
659
  elif _delta_raw:
653
660
  _delta_files = set(_delta_raw)
@@ -937,6 +944,11 @@ class TaskContextBuilder:
937
944
  change_type=_delta_change_type,
938
945
  dependency_graph_summary=_delta_dep_graph_summary,
939
946
  impact_score_per_file=_delta_impact_score_per_file,
947
+ ci_decision=(
948
+ "no_changes" if task_name == "delta" and not changed_files
949
+ else "analysis_success" if task_name == "delta"
950
+ else None
951
+ ),
940
952
  )
941
953
 
942
954
  def render_prompt(self, output: TaskOutput) -> str:
@@ -2118,6 +2130,124 @@ class TaskContextBuilder:
2118
2130
  impact_score_per_file,
2119
2131
  )
2120
2132
 
2133
+ def _resolve_git_baseline(self, since: Optional[str]) -> dict[str, Any]:
2134
+ """Resolve git baseline for delta diff using a 4-stage fallback chain.
2135
+
2136
+ Resolution order when `since` is provided:
2137
+ 1. exact local ref (git rev-parse --verify <since>)
2138
+ 2. remote-tracking ref (origin/<since>)
2139
+ 3. symbolic ref (git symbolic-ref refs/remotes/origin/HEAD)
2140
+ 4. HEAD~1 fallback
2141
+
2142
+ When `since` is None:
2143
+ 1. uncommitted changes (git diff --name-only --relative)
2144
+ 2. HEAD~1 fallback
2145
+
2146
+ Returns dict with keys:
2147
+ files: list[str] — changed paths (empty = confirmed no changes)
2148
+ resolved_ref: str — ref actually used for the diff
2149
+ resolution_path: str — which strategy resolved it
2150
+ diff_validation_status: str — "valid_non_empty"|"valid_empty"|"invalid_ref"
2151
+ error: bool — True only when ALL strategies failed
2152
+ """
2153
+ import subprocess
2154
+
2155
+ def _run(*args: str, timeout: int = 5) -> tuple[bool, str]:
2156
+ try:
2157
+ r = subprocess.run(
2158
+ ["git", *args], cwd=str(self.root),
2159
+ capture_output=True, text=True,
2160
+ encoding="utf-8", errors="replace", timeout=timeout,
2161
+ )
2162
+ return r.returncode == 0, (r.stdout or "").strip()
2163
+ except (subprocess.TimeoutExpired, FileNotFoundError):
2164
+ return False, ""
2165
+
2166
+ def _verify(ref: str) -> bool:
2167
+ ok, _ = _run("rev-parse", "--verify", ref)
2168
+ return ok
2169
+
2170
+ def _diff(ref: str) -> Optional[list[str]]:
2171
+ ok, out = _run("diff", "--name-only", "--relative", ref, "HEAD", timeout=10)
2172
+ if not ok:
2173
+ return None
2174
+ return [line.strip() for line in out.splitlines() if line.strip()]
2175
+
2176
+ def _make(files: list[str], ref: str, path: str) -> dict[str, Any]:
2177
+ return {
2178
+ "files": files,
2179
+ "resolved_ref": ref,
2180
+ "resolution_path": path,
2181
+ "diff_validation_status": "valid_non_empty" if files else "valid_empty",
2182
+ "error": False,
2183
+ }
2184
+
2185
+ if since:
2186
+ # Stage 1: exact local ref
2187
+ if _verify(since):
2188
+ files = _diff(since)
2189
+ if files is not None:
2190
+ return _make(files, since, "exact_local_ref")
2191
+
2192
+ # Stage 2: remote-tracking ref (origin/<since>)
2193
+ remote_ref = f"origin/{since}"
2194
+ if _verify(remote_ref):
2195
+ files = _diff(remote_ref)
2196
+ if files is not None:
2197
+ return _make(files, remote_ref, "remote_tracking_ref")
2198
+
2199
+ # Stage 3: symbolic ref (origin/HEAD → e.g. origin/main)
2200
+ ok, symref = _run("symbolic-ref", "refs/remotes/origin/HEAD")
2201
+ if ok and symref:
2202
+ short = symref.removeprefix("refs/remotes/")
2203
+ if _verify(short):
2204
+ files = _diff(short)
2205
+ if files is not None:
2206
+ return _make(files, short, "symbolic_ref")
2207
+
2208
+ # Stage 4: HEAD~1 fallback — original ref was invalid
2209
+ if _verify("HEAD~1"):
2210
+ files = _diff("HEAD~1")
2211
+ if files is not None:
2212
+ return {
2213
+ "files": files,
2214
+ "resolved_ref": "HEAD~1",
2215
+ "resolution_path": "head_minus_1_fallback",
2216
+ "diff_validation_status": "invalid_ref", # original ref unresolved
2217
+ "error": False,
2218
+ }
2219
+
2220
+ # All stages failed
2221
+ return {
2222
+ "files": [],
2223
+ "resolved_ref": since,
2224
+ "resolution_path": "unresolvable",
2225
+ "diff_validation_status": "invalid_ref",
2226
+ "error": True,
2227
+ }
2228
+
2229
+ else:
2230
+ # No since: uncommitted changes first
2231
+ ok, out = _run("diff", "--name-only", "--relative", timeout=10)
2232
+ if ok:
2233
+ files = [line.strip() for line in out.splitlines() if line.strip()]
2234
+ if files:
2235
+ return _make(files, "HEAD", "uncommitted_changes")
2236
+
2237
+ # HEAD~1 fallback
2238
+ if _verify("HEAD~1"):
2239
+ files = _diff("HEAD~1")
2240
+ if files is not None:
2241
+ return _make(files or [], "HEAD~1", "head_minus_1_fallback")
2242
+
2243
+ return {
2244
+ "files": [],
2245
+ "resolved_ref": "HEAD",
2246
+ "resolution_path": "unresolvable",
2247
+ "diff_validation_status": "invalid_ref",
2248
+ "error": True,
2249
+ }
2250
+
2121
2251
  def _get_git_changed_files(self, since: Optional[str] = None) -> Optional[list[str]]:
2122
2252
  """Get files changed since a git ref (default: HEAD~1) relative to self.root.
2123
2253
 
@@ -1450,17 +1450,26 @@ def agent_view(sm: SourceMap, *, full: bool = False) -> dict[str, Any]:
1450
1450
  """Opinionated output for AI agents — structured, noise-free, gap-aware.
1451
1451
 
1452
1452
  Output order:
1453
- 1. project → identity: type, summary, primary stack, frameworks
1454
- 2. entry_points → where execution starts (with reason/evidence)
1455
- 3. architecture how it's structured (flow description)
1456
- 4. key_dependencies runtime dependencies that matter (when analyzed)
1457
- 5. signals compact operational context (env, notes, tests)
1458
- 6. confidence_summary detection quality and hard/soft signals
1459
- 7. analysis_gaps what's uncertain or missing
1460
-
1461
- Never includes: file_tree, file_paths, schema internals, empty sections,
1462
- null fields, raw dependency lists, metrics, docs, or low-signal metadata.
1453
+ 1. project → identity: type, summary, primary stack, frameworks
1454
+ 2. entry_points → where execution starts (path+kind+confidence)
1455
+ 3. architecture pattern, layers (capped at 5)
1456
+ 4. file_relevance top-20 scored files primary agent value-add
1457
+ 5. runtime_packages monorepo package roles (when available)
1458
+ 6. key_dependencies production deps: name+version+role+risk_flags (cap 20)
1459
+ 7. suspicious_dependencies declared but never imported (cap 5)
1460
+ 8. signals → env summary, top-5 code notes, tests, Spring/JVM context
1461
+ 9. git_context → top-5 hotspots, branch, uncommitted count
1462
+ 10. confidence_summary overall quality + anomalies (no internal signals)
1463
+ 11. confidence_reasons → actionable reasons for low-confidence sections
1464
+ 12. analysis_gaps → what's uncertain or missing
1465
+
1466
+ Never includes: file_tree, file_paths, raw dep lists, dep_groups detail,
1467
+ hard/soft/ignored signals, env var key list, metrics, docs, agent_mode meta.
1463
1468
  """
1469
+ _AGENT_KEY_DEPS_CAP = 20
1470
+ _AGENT_LAYERS_CAP = 5
1471
+ _AGENT_CODE_NOTES_CAP = 5
1472
+
1464
1473
  # ── 1. Identity ──────────────────────────────────────────────────────────
1465
1474
  primary = next((s for s in sm.stacks if s.primary), sm.stacks[0] if sm.stacks else None)
1466
1475
 
@@ -1509,14 +1518,23 @@ def agent_view(sm: SourceMap, *, full: bool = False) -> dict[str, Any]:
1509
1518
  result["entry_points"] = _bs
1510
1519
  else:
1511
1520
  ep_groups = _entry_point_groups(sm.entry_points)
1512
- result["entry_points"] = ep_groups["production"][:_EP_PRODUCTION_CAP]
1513
- if ep_groups["development"]:
1514
- result["development_entry_points"] = ep_groups["development"][:_EP_DEV_CAP]
1521
+ result["entry_points"] = [
1522
+ {
1523
+ "path": ep["path"],
1524
+ **({"kind": ep["kind"]} if ep.get("kind") else {}),
1525
+ **({"confidence": ep["confidence"]} if ep.get("confidence") else {}),
1526
+ }
1527
+ for ep in ep_groups["production"][:_EP_PRODUCTION_CAP]
1528
+ ]
1515
1529
 
1516
- # ── 3. Architecture ───────────────────────────────────────────────────────
1517
- result["architecture"] = _architecture_context(sm)
1530
+ # ── 3. Architecture — pattern + layers (capped) ───────────────────────────
1531
+ _arch_ctx = _architecture_context(sm)
1532
+ if "layers" in _arch_ctx and len(_arch_ctx["layers"]) > _AGENT_LAYERS_CAP:
1533
+ _arch_ctx = dict(_arch_ctx)
1534
+ _arch_ctx["layers"] = _arch_ctx["layers"][:_AGENT_LAYERS_CAP]
1535
+ result["architecture"] = _arch_ctx
1518
1536
 
1519
- # ── 3a. File relevance: evidence-backed, high-signal only ────────────────
1537
+ # ── 4. File relevance: top-scored files — primary agent value-add ────────
1520
1538
  _FR_AGENT_CAP = 20
1521
1539
  _total_paths = len(sm.file_paths)
1522
1540
  relevant_files = _file_relevance(sm, limit=_FR_AGENT_CAP if not full else _total_paths)
@@ -1528,7 +1546,7 @@ def agent_view(sm: SourceMap, *, full: bool = False) -> dict[str, Any]:
1528
1546
  "Use --full to see all."
1529
1547
  )
1530
1548
 
1531
- # ── 3b. Monorepo package roles (when available), capped ──────────────────
1549
+ # ── 5. Monorepo package roles (when available), capped ───────────────────
1532
1550
  if sm.monorepo_packages:
1533
1551
  _noise_roles = {"benchmark_layer", "tooling_layer", "docs_layer", "test_layer"}
1534
1552
  operational_pkgs = [
@@ -1539,32 +1557,36 @@ def agent_view(sm: SourceMap, *, full: bool = False) -> dict[str, Any]:
1539
1557
  if operational_pkgs:
1540
1558
  result["runtime_packages"] = operational_pkgs[:_MONOREPO_PKGS_CAP]
1541
1559
 
1542
- # ── 4. Dependencies: separated by operational role, capped ───────────────
1543
- # noise_dependencies intentionally excluded not actionable.
1544
- dep_groups = _dependency_groups(sm)
1545
- if dep_groups["production_dependencies"]:
1546
- result["production_dependencies"] = dep_groups["production_dependencies"][:_PROD_DEPS_CAP]
1547
- for dep_key in ("dev_tools", "test_utilities", "build_tooling", "suspicious_dependencies"):
1548
- if dep_groups[dep_key]:
1549
- result[dep_key] = dep_groups[dep_key][:_SECONDARY_DEPS_CAP]
1550
-
1551
- # Backward-compatible compact list, now production-only, with risk_flags.
1560
+ # ── 6. Key dependencies: name+version+role+risk_flags only, cap 20 ───────
1561
+ # dep_groups verbose detail (production_dependencies, dev_tools, etc.) excluded —
1562
+ # fully overlaps key_dependencies with added noise from full asdict fields.
1552
1563
  production_key_deps = [
1553
1564
  d for d in sm.key_dependencies
1554
1565
  if (d.role or "unknown") in _PRODUCTION_DEP_ROLES and d.scope not in {"dev"}
1555
1566
  ]
1556
1567
  if sm.dependency_summary and sm.dependency_summary.requested and production_key_deps:
1557
- _dep_skip = {"parent", "manifest_path", "workspace", "source", "ecosystem"}
1558
1568
  _kd_list = []
1559
- for d in production_key_deps[:_KEY_DEPS_CAP]:
1560
- item = {k: v for k, v in asdict(d).items() if v is not None and k not in _dep_skip}
1569
+ for d in production_key_deps[:_AGENT_KEY_DEPS_CAP]:
1570
+ entry: dict[str, Any] = {"name": d.name}
1571
+ if d.declared_version:
1572
+ entry["version"] = d.declared_version
1573
+ if d.role and d.role != "runtime":
1574
+ entry["role"] = d.role
1561
1575
  flags = _dep_risk_flags(d.name, d.declared_version)
1562
1576
  if flags:
1563
- item["risk_flags"] = flags
1564
- _kd_list.append(item)
1577
+ entry["risk_flags"] = flags
1578
+ _kd_list.append(entry)
1565
1579
  result["key_dependencies"] = _kd_list
1566
1580
 
1567
- # ── 5. Signals compact operational context ─────────────────────────────
1581
+ # ── 7. Suspicious dependencies: declared but no static import observed ────
1582
+ dep_groups = _dependency_groups(sm)
1583
+ if dep_groups["suspicious_dependencies"]:
1584
+ result["suspicious_dependencies"] = [
1585
+ {"name": d.get("name", ""), "reason": d.get("reason", "")}
1586
+ for d in dep_groups["suspicious_dependencies"][:_SECONDARY_DEPS_CAP]
1587
+ ]
1588
+
1589
+ # ── 8. Signals — compact operational context ─────────────────────────────
1568
1590
  signals: dict[str, Any] = {}
1569
1591
 
1570
1592
  if sm.env_summary and sm.env_summary.requested and sm.env_summary.total > 0:
@@ -1580,15 +1602,6 @@ def agent_view(sm: SourceMap, *, full: bool = False) -> dict[str, Any]:
1580
1602
  elif (sm.env_summary.spring_profiles or sm.env_summary.profiles_scanned):
1581
1603
  _raw_profiles = sm.env_summary.spring_profiles or sm.env_summary.profiles_scanned
1582
1604
  signals["env_vars"]["spring_profiles"] = sorted(set(_raw_profiles))
1583
- if sm.env_map:
1584
- _sorted_env = sorted(
1585
- sm.env_map,
1586
- key=lambda e: (not getattr(e, "required", False), getattr(e, "key", "")),
1587
- )
1588
- signals["env_vars"]["keys"] = [
1589
- {k: v for k, v in asdict(e).items() if v is not None and v != "" and v != []}
1590
- for e in _sorted_env[:10]
1591
- ]
1592
1605
 
1593
1606
  if sm.code_notes_summary and sm.code_notes_summary.requested and sm.code_notes_summary.total > 0:
1594
1607
  by_kind = {k: v for k, v in sm.code_notes_summary.by_kind.items() if v > 0}
@@ -1602,8 +1615,14 @@ def agent_view(sm: SourceMap, *, full: bool = False) -> dict[str, Any]:
1602
1615
  key=lambda n: (_SEVERITY_ORDER.get(getattr(n, "kind", "").upper(), 9), getattr(n, "path", "")),
1603
1616
  )
1604
1617
  _code_notes_signal["top"] = [
1605
- {k: v for k, v in asdict(n).items() if v is not None}
1606
- for n in _sorted_notes[:10]
1618
+ {
1619
+ "kind": getattr(n, "kind", ""),
1620
+ "path": getattr(n, "path", ""),
1621
+ "line": getattr(n, "line", None),
1622
+ **({"text": _truncate_note(getattr(n, "text", ""), 120)} if getattr(n, "text", "") else {}),
1623
+ }
1624
+ for n in _sorted_notes[:_AGENT_CODE_NOTES_CAP]
1625
+ if getattr(n, "kind", "").upper() in _SEVERITY_ORDER
1607
1626
  ]
1608
1627
  if _code_notes_signal:
1609
1628
  signals["code_notes"] = _code_notes_signal
@@ -1651,12 +1670,13 @@ def agent_view(sm: SourceMap, *, full: bool = False) -> dict[str, Any]:
1651
1670
  if signals:
1652
1671
  result["signals"] = signals
1653
1672
 
1654
- # Git context — lightweight (top-5 hotspots, branch, uncommitted count)
1673
+ # ── 9. Git context — lightweight (top-5 hotspots, branch, uncommitted count)
1655
1674
  _gc = _compact_git_context(sm)
1656
1675
  if _gc:
1657
1676
  result["git_context"] = _gc
1658
1677
 
1659
- # ── 6. Confidence summary ─────────────────────────────────────────────────
1678
+ # ── 10. Confidence summary — overall quality + anomalies only ─────────────
1679
+ # hard_signals/soft_signals/ignored_signals are detection internals — excluded.
1660
1680
  if sm.confidence_summary is not None:
1661
1681
  cs = sm.confidence_summary
1662
1682
  conf: dict[str, Any] = {
@@ -1665,23 +1685,11 @@ def agent_view(sm: SourceMap, *, full: bool = False) -> dict[str, Any]:
1665
1685
  "entry_points": cs.entry_point_confidence,
1666
1686
  "sections": _section_confidence(sm),
1667
1687
  }
1668
- if cs.hard_signals:
1669
- _MAX_HARD_SIGNALS = 20
1670
- _hs = cs.hard_signals
1671
- _hs_total = len(_hs)
1672
- conf["hard_signals"] = _hs[:_MAX_HARD_SIGNALS]
1673
- if _hs_total > _MAX_HARD_SIGNALS:
1674
- conf["hard_signals_truncated"] = True
1675
- conf["hard_signals_total"] = _hs_total
1676
- if cs.soft_signals:
1677
- conf["soft_signals"] = cs.soft_signals
1678
- if cs.ignored_signals:
1679
- conf["ignored_signals"] = cs.ignored_signals
1680
1688
  if cs.anomalies:
1681
1689
  conf["anomalies"] = cs.anomalies
1682
1690
  result["confidence_summary"] = conf
1683
1691
 
1684
- # ── 6a. Confidence reasons: explain any low-confidence section ────────────
1692
+ # ── 11. Confidence reasons: actionable explanation of low-confidence sections
1685
1693
  _conf_reasons = _confidence_reasons(sm)
1686
1694
  if _conf_reasons:
1687
1695
  result["confidence_reasons"] = _conf_reasons
@@ -1691,7 +1699,7 @@ def agent_view(sm: SourceMap, *, full: bool = False) -> dict[str, Any]:
1691
1699
  # No reasons found → low was overly conservative; upgrade to high
1692
1700
  result["confidence_summary"].setdefault("sections", {})["architecture"] = "high"
1693
1701
 
1694
- # ── 7. Analysis gaps ──────────────────────────────────────────────────────
1702
+ # ── 12. Analysis gaps ─────────────────────────────────────────────────────
1695
1703
  analysis_gaps: list[dict[str, Any]] = []
1696
1704
 
1697
1705
  if sm.analysis_gaps:
@@ -1727,23 +1735,6 @@ def agent_view(sm: SourceMap, *, full: bool = False) -> dict[str, Any]:
1727
1735
  if analysis_gaps:
1728
1736
  result["analysis_gaps"] = analysis_gaps
1729
1737
 
1730
- # ── 8. Agent mode metadata — explicit transparency about auto-enabled/suppressed flags ──
1731
- _auto_enabled: list[str] = ["--dependencies", "--env-map", "--code-notes"]
1732
- _suppressed: list[str] = []
1733
- if sm.metrics_summary is not None and sm.metrics_summary.requested:
1734
- _suppressed.append("--full-metrics")
1735
- if sm.module_graph is not None and sm.module_graph.summary.requested:
1736
- _suppressed.append("--graph-modules")
1737
- if sm.doc_summary is not None and sm.doc_summary.requested:
1738
- _suppressed.append("--docs")
1739
- agent_mode_meta: dict[str, Any] = {
1740
- "auto_enabled": _auto_enabled,
1741
- }
1742
- if _suppressed:
1743
- agent_mode_meta["suppressed_flags"] = _suppressed
1744
- agent_mode_meta["suppressed_note"] = "computed but excluded from agent_view"
1745
- result["agent_mode"] = agent_mode_meta
1746
-
1747
1738
  return result
1748
1739
 
1749
1740
 
@@ -117,59 +117,57 @@ def test_symbol_definers_not_truncated() -> None:
117
117
 
118
118
 
119
119
  # ---------------------------------------------------------------------------
120
- # 4. agent_view suppressed flags metadata
120
+ # 4. agent_view noise exclusions
121
121
  # ---------------------------------------------------------------------------
122
122
 
123
- def test_agent_view_suppressed_flags_detected() -> None:
124
- """When metrics_summary.requested=True, agent_view includes it in suppressed_flags."""
125
- sm = _make_sm(
126
- metrics_summary=MetricsSummary(requested=True, file_count=5),
127
- )
128
- result = agent_view(sm)
129
-
130
- assert "agent_mode" in result
131
- am = result["agent_mode"]
132
- assert "--full-metrics" in am.get("suppressed_flags", [])
133
- assert am.get("suppressed_note") == "computed but excluded from agent_view"
134
-
135
-
136
- def test_agent_view_suppressed_graph_modules() -> None:
137
- """When module_graph.summary.requested=True, --graph-modules appears in suppressed_flags."""
138
- mg = ModuleGraph(summary=ModuleGraphSummary(requested=True))
139
- sm = _make_sm(module_graph=mg)
123
+ def test_agent_view_no_agent_mode_block() -> None:
124
+ """agent_mode metadata block removed static content with no signal value."""
125
+ sm = _make_sm(metrics_summary=MetricsSummary(requested=True, file_count=5))
140
126
  result = agent_view(sm)
141
-
142
- am = result["agent_mode"]
143
- assert "--graph-modules" in am.get("suppressed_flags", [])
144
-
145
-
146
- def test_agent_view_suppressed_docs() -> None:
147
- """When doc_summary.requested=True, --docs appears in suppressed_flags."""
148
- sm = _make_sm(doc_summary=DocSummary(requested=True))
127
+ assert "agent_mode" not in result
128
+
129
+
130
+ def test_agent_view_no_hard_signals() -> None:
131
+ """confidence_summary excludes hard/soft/ignored signals — detection internals."""
132
+ from sourcecode.schema import ConfidenceSummary
133
+ cs = ConfidenceSummary(
134
+ overall="high",
135
+ stack_confidence="high",
136
+ entry_point_confidence="high",
137
+ hard_signals=["pom.xml found", "spring-boot-starter-web in deps"],
138
+ soft_signals=["src/main/java present"],
139
+ ignored_signals=["README.md"],
140
+ )
141
+ sm = _make_sm(confidence_summary=cs)
149
142
  result = agent_view(sm)
150
143
 
151
- am = result["agent_mode"]
152
- assert "--docs" in am.get("suppressed_flags", [])
144
+ conf = result.get("confidence_summary", {})
145
+ assert "hard_signals" not in conf
146
+ assert "soft_signals" not in conf
147
+ assert "ignored_signals" not in conf
153
148
 
154
149
 
155
- def test_agent_view_no_suppressed_flags() -> None:
156
- """agent_view with no suppressed flags doesn't include suppressed_flags key."""
157
- sm = _make_sm()
150
+ def test_agent_view_no_env_keys_list() -> None:
151
+ """signals.env_vars excludes the keys[] list already present in compact env_map."""
152
+ from sourcecode.schema import EnvSummary, EnvVarRecord
153
+ env_map = [EnvVarRecord(key="DB_URL", required=True, category="database")]
154
+ env_summary = EnvSummary(requested=True, total=1, required_count=1)
155
+ sm = _make_sm(env_summary=env_summary, env_map=env_map)
158
156
  result = agent_view(sm)
159
157
 
160
- assert "agent_mode" in result
161
- am = result["agent_mode"]
162
- assert "suppressed_flags" not in am
163
- assert "--dependencies" in am.get("auto_enabled", [])
158
+ env_vars = result.get("signals", {}).get("env_vars", {})
159
+ assert "keys" not in env_vars
164
160
 
165
161
 
166
- def test_agent_view_auto_enabled_always_present() -> None:
167
- """auto_enabled list always contains the three flags agent mode enables."""
162
+ def test_agent_view_no_dep_groups() -> None:
163
+ """Verbose dep group fields excluded overlaps key_dependencies with noise."""
168
164
  sm = _make_sm()
169
165
  result = agent_view(sm)
170
166
 
171
- am = result["agent_mode"]
172
- assert set(am["auto_enabled"]) == {"--dependencies", "--env-map", "--code-notes"}
167
+ assert "production_dependencies" not in result
168
+ assert "dev_tools" not in result
169
+ assert "test_utilities" not in result
170
+ assert "build_tooling" not in result
173
171
 
174
172
 
175
173
  # ---------------------------------------------------------------------------
@@ -187,8 +185,8 @@ def test_agent_view_empty_ep_lists_omitted() -> None:
187
185
  assert "entry_points" in result
188
186
 
189
187
 
190
- def test_agent_view_dev_ep_present_when_nonempty() -> None:
191
- """When a dev entry point exists, development_entry_points appears in agent_view."""
188
+ def test_agent_view_dev_ep_excluded() -> None:
189
+ """development_entry_points excluded from agent_view noise for production-focused agents."""
192
190
  dev_ep = EntryPoint(
193
191
  path="webpack.config.js",
194
192
  stack="nodejs",
@@ -199,7 +197,7 @@ def test_agent_view_dev_ep_present_when_nonempty() -> None:
199
197
  sm = _make_sm(entry_points=[dev_ep])
200
198
  result = agent_view(sm)
201
199
 
202
- assert "development_entry_points" in result
200
+ assert "development_entry_points" not in result
203
201
 
204
202
 
205
203
  def test_standard_view_empty_ep_lists_omitted() -> None:
@@ -141,20 +141,21 @@ class TestBenchmarkContamination:
141
141
  data = _parse_agent(result.output)
142
142
  assert data.get("entry_points") == []
143
143
 
144
- def test_agent_splits_development_and_auxiliary_eps(self, nocobase_like: Path) -> None:
144
+ def test_agent_excludes_development_and_auxiliary_eps(self, nocobase_like: Path) -> None:
145
+ """agent_view only surfaces production EPs — dev/aux excluded as noise."""
145
146
  result = runner.invoke(app, ["--agent", str(nocobase_like)])
146
147
  assert result.exit_code == 0, result.output
147
148
  data = _parse_agent(result.output)
148
149
 
149
- dev_eps = data.get("development_entry_points", [])
150
- aux_eps = data.get("auxiliary_entry_points", [])
150
+ assert "development_entry_points" not in data
151
+ assert "auxiliary_entry_points" not in data
151
152
 
152
- assert any(ep.get("path") == "docs/rspress.mjs" for ep in dev_eps), dev_eps
153
- assert all(ep.get("classification") == "development" for ep in dev_eps), dev_eps
154
- assert all(ep.get("runtime_relevance") == "low" for ep in dev_eps), dev_eps
155
- assert any(ep.get("path") == "benchmarks/run.js" for ep in aux_eps), aux_eps
156
- assert any(ep.get("path") == "examples/demo.js" for ep in aux_eps), aux_eps
157
- assert all(ep.get("classification") == "auxiliary" for ep in aux_eps), aux_eps
153
+ entry_points = data.get("entry_points", [])
154
+ dev_paths = {"docs/rspress.mjs"}
155
+ aux_paths = {"benchmarks/run.js", "examples/demo.js"}
156
+ ep_paths = {ep.get("path", "") for ep in entry_points} if isinstance(entry_points, list) else set()
157
+ assert not (ep_paths & dev_paths), f"Dev EP leaked into entry_points: {ep_paths & dev_paths}"
158
+ assert not (ep_paths & aux_paths), f"Aux EP leaked into entry_points: {ep_paths & aux_paths}"
158
159
 
159
160
  def test_production_server_survives_benchmark_coexistence(
160
161
  self, production_nodejs: Path
File without changes
File without changes
File without changes
File without changes
File without changes