sourcecode 4.10.5__tar.gz → 4.10.7__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 (224) hide show
  1. {sourcecode-4.10.5 → sourcecode-4.10.7}/CHANGELOG.md +245 -0
  2. {sourcecode-4.10.5 → sourcecode-4.10.7}/PKG-INFO +15 -6
  3. {sourcecode-4.10.5 → sourcecode-4.10.7}/README.md +14 -5
  4. {sourcecode-4.10.5 → sourcecode-4.10.7}/pyproject.toml +1 -1
  5. {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/__init__.py +1 -1
  6. {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/architectural_baseline.py +80 -1
  7. {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/cache.py +8 -3
  8. {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/cache_model.py +109 -45
  9. {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/canonical_ir.py +2 -1
  10. {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/change_plan.py +51 -11
  11. {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/cli.py +676 -106
  12. {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/compare.py +91 -11
  13. sourcecode-4.10.7/src/sourcecode/container_wiring.py +315 -0
  14. {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/context_cache.py +63 -0
  15. {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/data_exposure.py +27 -1
  16. sourcecode-4.10.7/src/sourcecode/detach.py +155 -0
  17. sourcecode-4.10.7/src/sourcecode/execution_plan.py +428 -0
  18. {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/non_coverage.py +54 -0
  19. {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/output_budget.py +26 -3
  20. sourcecode-4.10.7/src/sourcecode/output_encoding.py +51 -0
  21. sourcecode-4.10.7/src/sourcecode/phased_run.py +210 -0
  22. {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/posture.py +3 -3
  23. {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/pr_impact.py +69 -2
  24. {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/prepare_context.py +38 -4
  25. {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/progress.py +60 -6
  26. {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/remedies.py +37 -5
  27. {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/repository_ir.py +100 -3
  28. {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/runs.py +8 -0
  29. {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/security_posture.py +29 -1
  30. {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/serializer.py +19 -1
  31. {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/servlet_surface.py +17 -1
  32. {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/spring_impact.py +38 -0
  33. {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/spring_security_audit.py +21 -5
  34. {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/verify_repo.py +2 -2
  35. {sourcecode-4.10.5 → sourcecode-4.10.7}/.github/workflows/build-windows.yml +0 -0
  36. {sourcecode-4.10.5 → sourcecode-4.10.7}/.gitignore +0 -0
  37. {sourcecode-4.10.5 → sourcecode-4.10.7}/.ruff.toml +0 -0
  38. {sourcecode-4.10.5 → sourcecode-4.10.7}/CLAUDE.md +0 -0
  39. {sourcecode-4.10.5 → sourcecode-4.10.7}/CONTRIBUTING.md +0 -0
  40. {sourcecode-4.10.5 → sourcecode-4.10.7}/LICENSE +0 -0
  41. {sourcecode-4.10.5 → sourcecode-4.10.7}/SECURITY.md +0 -0
  42. {sourcecode-4.10.5 → sourcecode-4.10.7}/raw +0 -0
  43. {sourcecode-4.10.5 → sourcecode-4.10.7}/scripts/compare_integration_engines.py +0 -0
  44. {sourcecode-4.10.5 → sourcecode-4.10.7}/scripts/customer_smoke_test.sh +0 -0
  45. {sourcecode-4.10.5 → sourcecode-4.10.7}/scripts/generate_jdk_exports.py +0 -0
  46. {sourcecode-4.10.5 → sourcecode-4.10.7}/scripts/perf_harness.py +0 -0
  47. {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/adaptive_scanner.py +0 -0
  48. {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/archetype.py +0 -0
  49. {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/architectural_delta.py +0 -0
  50. {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/architecture_analyzer.py +0 -0
  51. {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/architecture_summary.py +0 -0
  52. {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/ast_extractor.py +0 -0
  53. {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/audit_report.py +0 -0
  54. {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/baseline_autocapture.py +0 -0
  55. {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/call_surface.py +0 -0
  56. {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/caller_metrics.py +0 -0
  57. {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/caller_reach.py +0 -0
  58. {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/chain_rules.py +0 -0
  59. {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/cir_graphs.py +0 -0
  60. {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/classifier.py +0 -0
  61. {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/client_calls.py +0 -0
  62. {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/code_notes_analyzer.py +0 -0
  63. {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/confidence_analyzer.py +0 -0
  64. {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/constraint_diff.py +0 -0
  65. {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/context_graph.py +0 -0
  66. {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/context_scorer.py +0 -0
  67. {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/context_summarizer.py +0 -0
  68. {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/contract_diff.py +0 -0
  69. {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/contract_init.py +0 -0
  70. {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/contract_model.py +0 -0
  71. {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/contract_pipeline.py +0 -0
  72. {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/coverage_parser.py +0 -0
  73. {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/data_labels.py +0 -0
  74. {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/defect_identity.py +0 -0
  75. {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/degradation.py +0 -0
  76. {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/dependency_analyzer.py +0 -0
  77. {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/deployment_prefix.py +0 -0
  78. {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/detectors/__init__.py +0 -0
  79. {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/detectors/base.py +0 -0
  80. {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/detectors/csproj_parser.py +0 -0
  81. {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/detectors/dart.py +0 -0
  82. {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/detectors/dotnet.py +0 -0
  83. {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/detectors/elixir.py +0 -0
  84. {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/detectors/go.py +0 -0
  85. {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/detectors/heuristic.py +0 -0
  86. {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/detectors/hybrid.py +0 -0
  87. {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/detectors/java.py +0 -0
  88. {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/detectors/jvm_ext.py +0 -0
  89. {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/detectors/nodejs.py +0 -0
  90. {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/detectors/parsers.py +0 -0
  91. {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/detectors/php.py +0 -0
  92. {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/detectors/project.py +0 -0
  93. {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/detectors/python.py +0 -0
  94. {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/detectors/ruby.py +0 -0
  95. {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/detectors/rust.py +0 -0
  96. {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/detectors/systems.py +0 -0
  97. {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/detectors/terraform.py +0 -0
  98. {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/detectors/tooling.py +0 -0
  99. {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/doc_analyzer.py +0 -0
  100. {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/dynamic_argument_surface.py +0 -0
  101. {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/endpoint_literals.py +0 -0
  102. {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/endpoint_metrics.py +0 -0
  103. {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/entrypoint_classifier.py +0 -0
  104. {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/env_analyzer.py +0 -0
  105. {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/envelope.py +0 -0
  106. {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/environment_resolution.py +0 -0
  107. {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/error_schema.py +0 -0
  108. {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/evidence_provider.py +0 -0
  109. {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/explain.py +0 -0
  110. {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/facts/__init__.py +0 -0
  111. {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/facts/registry.json +0 -0
  112. {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/file_chunker.py +0 -0
  113. {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/file_classifier.py +0 -0
  114. {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/filter_surface.py +0 -0
  115. {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/format_contract.py +0 -0
  116. {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/fqn_utils.py +0 -0
  117. {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/git_analyzer.py +0 -0
  118. {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/git_checkout.py +0 -0
  119. {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/graph_analyzer.py +0 -0
  120. {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/graph_evidence.py +0 -0
  121. {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/hibernate_strat.py +0 -0
  122. {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/identity_fallback.py +0 -0
  123. {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/integration_coordinates.py +0 -0
  124. {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/jdk_exports.py +0 -0
  125. {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/license.py +0 -0
  126. {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/mcp/__init__.py +0 -0
  127. {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/mcp/onboarding/__init__.py +0 -0
  128. {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/mcp/onboarding/applier.py +0 -0
  129. {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/mcp/onboarding/backup.py +0 -0
  130. {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/mcp/onboarding/detector.py +0 -0
  131. {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/mcp/onboarding/planner.py +0 -0
  132. {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/mcp/orchestrator.py +0 -0
  133. {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/mcp/registry.py +0 -0
  134. {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/mcp/runner.py +0 -0
  135. {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/mcp/server.py +0 -0
  136. {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/mcp_nudge.py +0 -0
  137. {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/metrics_analyzer.py +0 -0
  138. {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/migrate_check.py +0 -0
  139. {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/migration_blast.py +0 -0
  140. {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/openapi_surface.py +0 -0
  141. {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/openrewrite_recipe.py +0 -0
  142. {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/parse_cache.py +0 -0
  143. {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/path_admission.py +0 -0
  144. {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/path_filters.py +0 -0
  145. {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/perf.py +0 -0
  146. {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/pipe_contract.py +0 -0
  147. {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/pr_comment_renderer.py +0 -0
  148. {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/provenance.py +0 -0
  149. {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/ranking_engine.py +0 -0
  150. {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/readiness_timeline.py +0 -0
  151. {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/reconciliation.py +0 -0
  152. {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/redactor.py +0 -0
  153. {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/reference_facts.py +0 -0
  154. {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/release_info.py +0 -0
  155. {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/relevance_scorer.py +0 -0
  156. {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/rename_refactor.py +0 -0
  157. {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/repo_classifier.py +0 -0
  158. {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/retrieval/__init__.py +0 -0
  159. {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/retrieval/context.py +0 -0
  160. {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/retrieval/errors.py +0 -0
  161. {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/retrieval/executor.py +0 -0
  162. {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/retrieval/planner.py +0 -0
  163. {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/retrieval/query.py +0 -0
  164. {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/retrieval/request.py +0 -0
  165. {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/retrieval/resolution.py +0 -0
  166. {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/retrieval/result.py +0 -0
  167. {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/retrieval/retriever.py +0 -0
  168. {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/retrieval/runtime.py +0 -0
  169. {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/retrieval/steps.py +0 -0
  170. {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/retrieval/steps_endpoint.py +0 -0
  171. {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/retrieval/steps_graph.py +0 -0
  172. {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/retrieval/steps_impact.py +0 -0
  173. {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/retrieval/steps_intf.py +0 -0
  174. {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/retrieval/steps_struct.py +0 -0
  175. {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/retrieval/steps_txsec.py +0 -0
  176. {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/ris.py +0 -0
  177. {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/risk.py +0 -0
  178. {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/rule_catalog.py +0 -0
  179. {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/runtime_classifier.py +0 -0
  180. {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/sarif.py +0 -0
  181. {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/scanner.py +0 -0
  182. {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/schema.py +0 -0
  183. {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/schemas/envelope-v1.schema.json +0 -0
  184. {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/security_config.py +0 -0
  185. {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/security_config_scan.py +0 -0
  186. {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/semantic_analyzer.py +0 -0
  187. {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/semantic_impact_engine.py +0 -0
  188. {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/semantic_integration_engine.py +0 -0
  189. {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/semantic_services.py +0 -0
  190. {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/source_text.py +0 -0
  191. {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/spring_event_topology.py +0 -0
  192. {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/spring_findings.py +0 -0
  193. {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/spring_model.py +0 -0
  194. {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/spring_profiles.py +0 -0
  195. {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/spring_properties.py +0 -0
  196. {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/spring_semantic.py +0 -0
  197. {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/spring_tx_analyzer.py +0 -0
  198. {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/summarizer.py +0 -0
  199. {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/target_admission.py +0 -0
  200. {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/telemetry/__init__.py +0 -0
  201. {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/telemetry/config.py +0 -0
  202. {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/telemetry/consent.py +0 -0
  203. {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/telemetry/events.py +0 -0
  204. {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/telemetry/filters.py +0 -0
  205. {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/telemetry/transport.py +0 -0
  206. {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/test_gap_ranking.py +0 -0
  207. {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/test_sources.py +0 -0
  208. {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/text_input.py +0 -0
  209. {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/token_estimate.py +0 -0
  210. {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/tree_utils.py +0 -0
  211. {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/type_usage_surface.py +0 -0
  212. {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/validation_inference.py +0 -0
  213. {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/validation_surface.py +0 -0
  214. {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/verify_edit.py +0 -0
  215. {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/verify_rules.py +0 -0
  216. {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/version_check.py +0 -0
  217. {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/workspace.py +0 -0
  218. {sourcecode-4.10.5 → sourcecode-4.10.7}/supabase/functions/README.md +0 -0
  219. {sourcecode-4.10.5 → sourcecode-4.10.7}/supabase/functions/get-license/index.ts +0 -0
  220. {sourcecode-4.10.5 → sourcecode-4.10.7}/supabase/functions/lemonsqueezy-webhook/index.ts +0 -0
  221. {sourcecode-4.10.5 → sourcecode-4.10.7}/supabase/functions/telemetry/index.ts +0 -0
  222. {sourcecode-4.10.5 → sourcecode-4.10.7}/supabase/sql/license_event_ordering.sql +0 -0
  223. {sourcecode-4.10.5 → sourcecode-4.10.7}/supabase/sql/licensing_schema.sql +0 -0
  224. {sourcecode-4.10.5 → sourcecode-4.10.7}/supabase/sql/telemetry_events.sql +0 -0
@@ -2,6 +2,251 @@
2
2
 
3
3
  ## [Unreleased]
4
4
 
5
+ ## [4.10.7] — 2026-08-07
6
+
7
+ **Tier D, and with it the M13 bug queue.** Five ledger rows close (C4-17 · C4-18 ·
8
+ C4-19 · C4-20 · C4-21), one commit each, all of them discoverability: none was
9
+ publishing a false claim, and together they are the ergonomics score two field
10
+ evaluations put at 5/10. What remains of the queue is a *measurement*, not a fix —
11
+ the C3-53 re-run on Windows under an agent harness, which is written the same way
12
+ in the ledger and in the 4.10.6 entry below.
13
+
14
+ ⚠ **Three behaviour changes to read before upgrading a pipeline:**
15
+
16
+ - **`ask cache status --json` renames `cores` to `cached_cores`.** It always
17
+ counted cached core entries; `cores` is what a captured baseline calls the
18
+ machine's CPU count (C4-18).
19
+ - **`--output/-o` is now accepted after every command that publishes `--copy`**,
20
+ including eleven that refused it. On those the answer goes to the file and
21
+ stdout carries one `Written to <path>` line (C4-17).
22
+ - **`--detach` accepts every repository-wide and deep command**, not the six that
23
+ happened to be listed in a hand-kept table. `posture`, `modernize`, `repo-ir`
24
+ and `verify-edit` — four of the commands the field could not run in a session —
25
+ could not be detached before this release (C4-19).
26
+
27
+ ### Fixed
28
+
29
+ - **`ask --help` orders its front page by what will run on the repository being
30
+ read** (C4-19). *Start here* was, on the field repository, exactly the set of
31
+ commands that could not run there — four of five unrunnable in one evaluation,
32
+ three of five killing the session in the next. The help now measures the scope
33
+ (a capped tree walk plus two stat calls, paid only when help is what was asked
34
+ for) and groups the entries into **Runs now**, **Warm the cache first** and
35
+ **Too big for this session — `--output <file> --detach`**. What it deliberately
36
+ does not do is project a duration: `spring-audit` is 8.8 s on the 2 000-file
37
+ reference and was measured at 408 s on 3 342 files, so a scaled estimate would
38
+ be a confident falsehood; the class and the measured anchors are published
39
+ instead, and a command measured fast at field size (`endpoints`, 4.2 s) stays
40
+ on the fast list whatever its class. `--detach` accepts every repository-wide
41
+ and deep command now, not the six that happened to be in a hand-kept table:
42
+ `posture`, `modernize`, `repo-ir` and `verify-edit` were on the field's blocked
43
+ list and could not be detached.
44
+ - **A remedy is checked against the repository it is printed on** (C4-20).
45
+ `plan` pointed an unresolved symbol at `ask repo-ir`, and `onboard` named
46
+ `ask posture --profile <set>` as the authority — both correct, and neither
47
+ finished in an interactive session on the repository whose answer named them.
48
+ Every remedy block (`posture`, `data-exposure`, `verify`, the security-surface
49
+ limitation, the unresolved-target message) now carries `how_to_run_here` when
50
+ there is something to say: run it detached, or warm the cache first. Nothing is
51
+ added where the command runs in the foreground, and nothing is guessed where
52
+ the scope is unknown.
53
+ - **`--output/-o` works after every command that produces an answer** (C4-17).
54
+ It was a per-command decision, and the decisions disagreed: `endpoints`,
55
+ `validation` and `data-exposure` accepted it after the command, `baseline
56
+ capture` refused it — while its own siblings `baseline diff` and `baseline
57
+ trend` accepted it — and the refusal's hint blamed the placement rather than
58
+ the gap. The rule is now one line with its population taken from the CLI
59
+ registry: **a command that publishes `--copy` publishes `--output`**. Eleven
60
+ commands gained it (`version`, `baseline capture`, `cache status/warm/model/
61
+ freshness/context-stats`, `auth status`, `mcp status`, `mcp list-tools`,
62
+ `telemetry status`); on those the answer goes to the file and stdout carries
63
+ only `Written to <path>`. The hint for a genuinely global flag typed after a
64
+ subcommand was corrected with it: it said *"it goes before the command"*, which
65
+ is a placement that does nothing, since the root analysis is skipped as soon as
66
+ a subcommand is invoked.
67
+ - **`ask config` lists the repository's own declaration** (C4-21). `data-exposure`
68
+ answers `answered: false` until `sourcecode.config.json` declares which types
69
+ and fields are sensitive — the right refusal, since a label is a judgement
70
+ about a domain and is never inferred — but nothing afterwards said whether the
71
+ file had been picked up, so the last step of the cold start was a guess.
72
+ `ask config [path]` now resolves that file and reports its path, the labels
73
+ read from it, the custom security annotations, and any declaration that could
74
+ not be used; when it is absent, the path it looked at and the answer that
75
+ absence produces. The `data-exposure` refusal points at it (`declare.confirm`).
76
+ - **`cache status` no longer calls a cache count `Cores:`** (C4-18). The line
77
+ counted `core-*.json.gz` entries under the field name a captured baseline uses
78
+ for the machine's CPU count (`env: {cores: 20}` on the same machine, same
79
+ scope, minutes apart), and it sat beside `Views: 0 / CAS blobs: 0`, so
80
+ `Cores: 0` read as *the cache is empty* rather than *no core entries yet*. The
81
+ text line is `Cached cores: N entries` and the JSON key is `cached_cores`.
82
+ **Behaviour change for consumers of `ask cache status --json`: the `cores` key
83
+ is gone, replaced by `cached_cores`** — one fact, one name.
84
+
85
+ ## [4.10.6] — 2026-08-07
86
+
87
+ The M13 sanitation queue, tiers A through C plus the claims tier: **eighteen ledger
88
+ rows close** (C1-36 · C1-37 · C1-38 · C1-39 · C1-40 · C2-27 · C2-28 · C2-29 ·
89
+ C3-53 · C3-54 part 3 · C3-55 · C3-61 · C3-65 · C3-66 · C3-67 · C3-68 · C3-69 ·
90
+ CL-16), against the two independent field evaluations of 4.10.4 and 4.10.5 that
91
+ agreed on the diagnosis and disagreed on nothing material. No feature ships here:
92
+ the owner directive for this milestone is that every bug is sanitated before the
93
+ first feature starts.
94
+
95
+ ⚠ **Five behaviour changes to read before upgrading a pipeline.** All five are the
96
+ fix working, and three of them can move a gate:
97
+
98
+ - **`pr-impact`, `impact`, `impact-chain`, `plan` and `compare` now floor the
99
+ verdict at `HIGH` when the change touches a component the container invokes** —
100
+ a `@Configuration`, an `@Aspect`, a `Filter`, a `@ControllerAdvice`, a bean
101
+ resolved through an interface something injects, `web.xml`,
102
+ `application*.y*ml`. A gate that was passing green over a security-config diff
103
+ will start failing, with the verdict that diff always deserved (C1-36).
104
+ - **`ASK_MAX_ANALYSIS_SECONDS` is honoured instead of vetoed.** A value below the
105
+ class floor no longer refuses to run: it warns and runs, and a run that spends
106
+ its budget publishes what it measured with `partial: true`. `--ci` fails on a
107
+ partial answer (C3-55, C3-54 part 3).
108
+ - **`ask endpoints --servlets` answers with the servlet population only**, plus
109
+ the endpoint total as one number. A consumer that read `endpoints[]` out of that
110
+ document has to call `ask endpoints` for it (C3-65).
111
+ - **`ask plan` publishes `null`, not `0`, for anything it did not measure** — an
112
+ unresolved target, or `covering_tests` in a repository with no test source root.
113
+ A consumer coercing those to `int` needs to handle `null` (C1-39).
114
+ - **`baseline capture` no longer records the machine by default** (`cpu`, `cores`,
115
+ `hostname_hash`); `--record-env` restores it. A comparison keyed on those fields
116
+ needs the flag (C3-68).
117
+
118
+ `posture` moves from `experimental` to `supported` (CL-16).
119
+
120
+ ### Fixed
121
+
122
+ - **A component the container calls is not a component nothing calls** (C1-36).
123
+ *The one blind spot this product did not declare, reproduced on two builds by
124
+ two evaluations.* Blast radius is projected over the call graph, so a class the
125
+ framework invokes has fan-in ~0 and every figure derived from it reads as no
126
+ impact: a diff over the filter chain, the aspect gating 935 routes and the
127
+ production password encoder published `LOW / "No high-risk signals detected" /
128
+ affected_endpoints: []`, while a plain POJO in the same repository published
129
+ `CRITICAL` with 3 382 endpoints. The fan-in figure was never wrong; using it as
130
+ a risk proxy on that population was. `container_wiring.py` answers the one
131
+ question that separates them, from facts the CIR already carries — the role it
132
+ assigns, the interception annotations and supertypes fixed by published
133
+ specifications, and one route that consults no name at all: *the class
134
+ implements an interface something injects and has zero incoming call edges*,
135
+ which catches a password encoder without anyone naming one. Wired at the single
136
+ blast-radius authority so the four commands that disagreed now answer from one
137
+ place. The verdict is floored, never lowered; the population is published with
138
+ its evidence; and **NC-010** states the limit in the payload, the README and the
139
+ help.
140
+ - **A killed analysis keeps what it measured** (C3-54 part 3). `phased_run.py`
141
+ gives a long command a declared phase list and a durable checkpoint after each
142
+ phase, written through the same fsynced, atomic seam as the final answer and
143
+ removed only once the complete answer is on disk — so a teardown leaves the
144
+ better of the two files and never neither. A checkpoint can never pass for a
145
+ finished answer: `partial: true`, `phases_completed`, `phases_pending`,
146
+ `why_stopped`. The field lost 6,8 minutes of CPU and every recoverable byte
147
+ four times.
148
+ - **A budget that is set is honoured** (C3-55). Below the class floor was refused
149
+ and above it admitted a run that outlived the session, so no value was both
150
+ accepted and survivable on the variable the help presents as the CI control.
151
+ The floor is advice printed before the work; the budget stops the run between
152
+ phases; counts in a partial answer are a floor over the phases that completed
153
+ and say so.
154
+ - **A repository-wide run can outlive its shell** (C3-53, survivable half).
155
+ `--detach` (with `--output`) starts the analysis in a process that leads its own
156
+ session and, on Windows, carries `CREATE_BREAKAWAY_FROM_JOB` — the documented
157
+ way out of the parent shell's job object, which is what killed even
158
+ `Start-Process -NoNewWindow` and all six of its children at the same second the
159
+ session died. When a platform refuses the breakaway the envelope says so rather
160
+ than implying a guarantee it does not have. **Not closed:** the field case is
161
+ Windows under an agent harness, and only a Windows re-run proves the tree
162
+ survives there.
163
+ - **`--servlets` answers with the population it names** (C3-65). The flag read as
164
+ a filter and behaved as an aggregator: 1,8 MB to stdout, the useful signal at
165
+ 0,08 % of the bytes, at line 49 622 of 49 730 — and the agent session that asked
166
+ for it died. Every servlet row also carries `population: "servlet"`, so a
167
+ consumer iterating rows finally sees a servlet after passing the flag built to
168
+ show them.
169
+ - **`compare` no longer ranks the repository first** (C3-67). A candidate that
170
+ resolves to an existing directory is published as `resolved: false` /
171
+ `not_a_candidate` and ranks last. `ask compare A B .` used to rank the `.`
172
+ first, with 3 574 endpoints and 3 342 rollback files as its cost.
173
+ - **`secured_endpoints` published a display cap as a measurement** (C1-38). The
174
+ `15` that reconciled with nothing was `min(real, 15)`: the count was `len()` of
175
+ a truncated 15-row sample. The population is counted before the cut, the list is
176
+ still sampled, and the omission is published with its `cap_effect`. All four
177
+ figures that share the name now carry their unit and name the other three.
178
+ - **Four figures called "endpoints" each say what they counted** (C1-37), and the
179
+ baseline stopped disagreeing with itself: `totals.endpoints` counts handler
180
+ mappings, `totals.endpoint_contract_pairs` counts the distinct (METHOD, path)
181
+ pairs `endpoint_surface` lists, and the battery holds the invariant between the
182
+ second and the list — an invariant that is only checkable because the two
183
+ figures finally describe two things.
184
+ - **What was not measured is `null`, never `0`** (C1-39), in `plan` and in
185
+ `covering_tests` on a repository with no test source root. The shape
186
+ `data-exposure` already had, one level up.
187
+ - **`cache model` promised a hit the command does not store** (C1-40). Measured on
188
+ keycloak: **with** a warm, `onboard` costs 0,7 s; **without** one, a second
189
+ identical run costs 9,4 s against 10,2 s cold. `repeat` is now false for
190
+ `onboard`, with the figures published at two scales.
191
+ - **A local artefact is not committable by accident** (C3-68). `.ask/` gets its own
192
+ `.gitignore` the moment it is created — self-confined, never touching the user's
193
+ own, never overwriting one they edited — and `env` records only the two fields
194
+ that decide comparability.
195
+ - **A heartbeat does not make a successful run look failed** (C3-66).
196
+ `ASK_PROGRESS` takes `1`/`stderr`, `off` and `file:<path>`; the file form leaves
197
+ stderr empty, so a PowerShell job can watch a six-minute run and still trust
198
+ `$?`. No setting writes to stdout.
199
+ - **Fix the decoder, not the bytes** (C3-69). `SetConsoleOutputCP(65001)` at entry
200
+ tells the Windows console to read the UTF-8 we were always writing; only when
201
+ that fails does the emit seam escape the payload to ASCII. One decision, made
202
+ once, read by every emit seam.
203
+ - **A budget note that contradicts the summary beside it** (C2-27). The unit is
204
+ bytes, so `29KB → 29KB` beside `total_omitted_items: 10` cannot recur, and both
205
+ the note and `_truncation_summary.applies_to` state that trimming describes the
206
+ stdout rendering — `--output` writes the answer untrimmed.
207
+ - **Git churn is not evidence about semantics** (C2-29). When the symptom names
208
+ something this repository contains, activity signals contribute nothing to the
209
+ `fix-bug` rank and are reported as context; when nothing resolves they still
210
+ rank, published as correlational rather than as triage.
211
+ - **A limit is stated once and referenced** (C2-28). `NC-007` was emitted twice,
212
+ byte for byte, in the heaviest payload the tool produces.
213
+
214
+ ### Performance
215
+
216
+ - **The rule pass was never mostly rules** (C3-61, second measurement).
217
+ Re-profiled after the pre-filter shipped: `infer_security_posture` ran **twice**
218
+ per audit — once to learn the custom-gate tokens the rules match on, once to
219
+ publish the posture block — at ~2,1 s each, each rebuilding the filter surface
220
+ and re-walking the tree underneath it; and `_proxy_bypass` scanned every
221
+ admissible source for methods twice. Both are identities and both are fixed as
222
+ identities. **keycloak 6,17 s → 4,07 s, 90 findings before and after, payload
223
+ identical except `generated_at` and `analysis_time_ms`.** No threads and no
224
+ processes: parallelising would have bought ~15 % of a wall clock now dominated
225
+ by the CIR build (12,6 s warm against 4,1 s for the whole rule pass), which is
226
+ F-AA's problem and not this row's.
227
+ - **Deciding whether a cached context is still valid no longer deserialises it**
228
+ (C1-40, second half). The validity keys live in an uncompressed sidecar beside
229
+ the blob; the field measured 1 029 ms average / 1 955 ms p95 to read three short
230
+ strings out of a 10 MB envelope, and an entry invalidated by a changed signature
231
+ paid all of it before discarding the result.
232
+
233
+ ### Changed
234
+
235
+ - `posture` is `supported`, not `experimental` (CL-16). It is the one command
236
+ neither field evaluation found a competitor for, and it produced 2 of
237
+ evaluation #15's 3 CRITICAL findings.
238
+ - `pr-impact` keeps its `core` tier because C1-36's silent half is closed: it can
239
+ now keep the promise that tier makes.
240
+
241
+ ### Still open from this queue
242
+
243
+ `C4-17` (`--output` accepted postfix on some subcommands, absent on others),
244
+ `C4-19` (a scope-aware `--help` ordered by what can actually run), `C4-20`
245
+ (suggested next commands checked against the cost model before printing), `C4-21`
246
+ (`ask config` listing the label source it resolved) and `C4-18` (`cache status`
247
+ printing `Cores:` for a cache count). All five are discoverability; none of them
248
+ publishes a false claim.
249
+
5
250
  ## [4.10.5] — 2026-08-07
6
251
 
7
252
  Second release of the field-evaluation #13 queue. Three rows close and one closes
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: sourcecode
3
- Version: 4.10.5
3
+ Version: 4.10.7
4
4
  Summary: Persistent structural context and ultra-fast repeated analysis for AI coding agents
5
5
  License-File: LICENSE
6
6
  Keywords: agents,ai,codebase,context,developer-tools,llm
@@ -42,7 +42,7 @@ Description-Content-Type: text/markdown
42
42
 
43
43
  **Context · Impact · Migration · Architecture · Review — everything from one structural model.**
44
44
 
45
- ![Version](https://img.shields.io/badge/version-4.10.5-blue)
45
+ ![Version](https://img.shields.io/badge/version-4.10.7-blue)
46
46
  ![Python](https://img.shields.io/badge/python-3.9%2B-green)
47
47
 
48
48
  > **ASK Engine** is the product. The CLI command is **`ask`**. The legacy **`sourcecode`**
@@ -106,7 +106,7 @@ brew tap haroundominique/sourcecode && brew install sourcecode
106
106
  # pip / pipx
107
107
  pipx install sourcecode # or: pip install sourcecode
108
108
 
109
- ask version # ask 4.10.5 — and, on a build that has aged,
109
+ ask version # ask 4.10.7 — and, on a build that has aged,
110
110
  # how many releases have probably shipped since
111
111
  ```
112
112
 
@@ -299,7 +299,7 @@ experimental: both are true, and they are two different facts.
299
299
  |---|---|---|
300
300
  | **core** | contract stable within a major — safe to gate CI on | `endpoints` · `spring-audit` · `migrate-check` · `impact` · `impact-chain` · `pr-impact` · `verify` |
301
301
  | **supported** | maintained; fields are added, never removed without a major | every command not named in another row |
302
- | **experimental** | shape may change in a minor — do not gate CI on it | `risk` · `enrich` · `audit-report` · `data-exposure` · `migrate-recipe` · `posture` · `archetype` |
302
+ | **experimental** | shape may change in a minor — do not gate CI on it | `risk` · `enrich` · `audit-report` · `data-exposure` · `migrate-recipe` · `archetype` |
303
303
  | **parked** | kept working, no longer developed | `retrieve` |
304
304
 
305
305
  The same table is printed by `ask --help`, and both are generated from one authority
@@ -315,7 +315,7 @@ from it.
315
315
 
316
316
  | Command | Tier | Answers | Note |
317
317
  |---|---|---|---|
318
- | `posture` | experimental | which beans a profile set wires, and how effective endpoint access differs between two sets | the most differentiated capability here |
318
+ | `posture` | supported | which beans a profile set wires, and how effective endpoint access differs between two sets | the most differentiated capability here |
319
319
  | `risk` | experimental | what each defect actually costs, once reach, access, write effect and the shape of the input path are in it | `defect_severity × reachability × auth_verdict × write_effect × query_construction × input_constraints`; every factor names its authority; `--table --rule SEC-008 --band high --top-n 20` gives audit triage without `jq` |
320
320
  | `enrich` | experimental | another scanner's SARIF findings, ranked by what this repository does with them | `--sarif <log>`; same composition as `risk`, with `--table --rule <id> --band high --top-n 20` for triage |
321
321
  | `audit-report` | experimental | human audit bundle over existing `risk` + `posture` evidence, optionally signed | includes `evidence_manifest` claim provenance; `--format markdown`; `--sign-key <file>` signs canonical JSON with HMAC-SHA256 |
@@ -398,6 +398,12 @@ And one about who calls a route:
398
398
  |---|---|---|
399
399
  | **Whether a route is called from outside this repository — another service, a mobile app, a partner, a cron job, or a client whose URL is assembled at run time.** | The join reads the TypeScript/JavaScript checked in beside the server and only the call shapes whose verb and path are written at the call site. That is a floor on who calls a route and can never be a ceiling: the repository cannot observe consumers it does not contain. So a route with no call site here is published as a candidate for deletion, never as dead API. | Access logs or an API gateway answer who really calls a route. The opposite direction is decisive without them: a client call matching no route is a request this repository's own front end makes and its server does not serve. |
400
400
 
401
+ And one about blast radius:
402
+
403
+ | Not covered | Why | What answers it |
404
+ |---|---|---|
405
+ | **The reach of a component the container invokes rather than the code — a security filter chain, an around-advice aspect, a `@ControllerAdvice`, a bean resolved through the interface it implements.** | Blast radius here is projected over the call graph: who calls the changed symbol, and which routes reach those callers. Nothing in the repository calls a container-wired component, so its measured call-graph fan-in is ~0 and every figure derived from it — affected endpoints, direct callers, rollback surface — reads as no impact. The fan-in figure is correct; using it as a risk proxy on this population is not. Publishing that as a low verdict would be a confident zero, which is the one thing this product does not do. | Such a change is flagged in `analysis_warnings` and its verdict is floored, never rated on fan-in. The reach itself is measured elsewhere and was there all along: `ask endpoints` resolves a gate annotation to the routes carrying it, `ask explain <class>` prints the request chain a configuration declares with its source line, and `ask posture --profile <set>` states what each profile leaves open. Projecting those into the blast radius (pointcut → routes, matcher → routes) is a measurement this command does not yet make. |
406
+
401
407
  The one row above with a remedy in this build: `ask endpoints /path/to/repo --servlets`
402
408
  lists the servlet-mounted HTTP surface as a population of its own — `web.xml` mappings and
403
409
  `ServletRegistrationBean` registrations, with the file that declares each — and never merges
@@ -461,6 +467,9 @@ Full breakdown: [docs/PRODUCT_TIERS.md](docs/PRODUCT_TIERS.md).
461
467
 
462
468
  ```bash
463
469
  ask config # version, config file path, telemetry status
470
+ ask config /repo # + the repository's own sourcecode.config.json:
471
+ # data labels, custom security annotations,
472
+ # and any declaration that could not be used
464
473
  ask telemetry enable # anonymous telemetry is OFF by default (opt-in)
465
474
  ```
466
475
 
@@ -497,7 +506,7 @@ Matching endpoints report `policy: "custom"` and drop out of the `no_security_si
497
506
  | [USER_GUIDE.md](docs/USER_GUIDE.md) | Full command reference, flags, output schema, workflows |
498
507
  | [contracts.md](docs/contracts.md) | Declare invariants in `.ask/contracts.yml` (or derive them with `ask verify --init`), enforce them in the edit loop and in CI |
499
508
  | [baseline-ci.yml](docs/baseline-ci.yml) | Capture an architectural baseline per release, so the series exists when you want to read it |
500
- | [posture.md](docs/posture.md) | What a profile set actually wires — down to which endpoints its filter chain permits — and what could not be decided (experimental) |
509
+ | [posture.md](docs/posture.md) | What a profile set actually wires — down to which endpoints its filter chain permits — and what could not be decided |
501
510
  | [migrate-check.md](docs/migrate-check.md) | Migration rule catalogue (MIG-001..043) + Hibernate stratification |
502
511
  | [MODERNIZATION.md](docs/MODERNIZATION.md) | The modernization product: assess → understand → plan → execute |
503
512
  | [PRODUCT_TIERS.md](docs/PRODUCT_TIERS.md) | Free vs Pro, pricing model |
@@ -4,7 +4,7 @@
4
4
 
5
5
  **Context · Impact · Migration · Architecture · Review — everything from one structural model.**
6
6
 
7
- ![Version](https://img.shields.io/badge/version-4.10.5-blue)
7
+ ![Version](https://img.shields.io/badge/version-4.10.7-blue)
8
8
  ![Python](https://img.shields.io/badge/python-3.9%2B-green)
9
9
 
10
10
  > **ASK Engine** is the product. The CLI command is **`ask`**. The legacy **`sourcecode`**
@@ -68,7 +68,7 @@ brew tap haroundominique/sourcecode && brew install sourcecode
68
68
  # pip / pipx
69
69
  pipx install sourcecode # or: pip install sourcecode
70
70
 
71
- ask version # ask 4.10.5 — and, on a build that has aged,
71
+ ask version # ask 4.10.7 — and, on a build that has aged,
72
72
  # how many releases have probably shipped since
73
73
  ```
74
74
 
@@ -261,7 +261,7 @@ experimental: both are true, and they are two different facts.
261
261
  |---|---|---|
262
262
  | **core** | contract stable within a major — safe to gate CI on | `endpoints` · `spring-audit` · `migrate-check` · `impact` · `impact-chain` · `pr-impact` · `verify` |
263
263
  | **supported** | maintained; fields are added, never removed without a major | every command not named in another row |
264
- | **experimental** | shape may change in a minor — do not gate CI on it | `risk` · `enrich` · `audit-report` · `data-exposure` · `migrate-recipe` · `posture` · `archetype` |
264
+ | **experimental** | shape may change in a minor — do not gate CI on it | `risk` · `enrich` · `audit-report` · `data-exposure` · `migrate-recipe` · `archetype` |
265
265
  | **parked** | kept working, no longer developed | `retrieve` |
266
266
 
267
267
  The same table is printed by `ask --help`, and both are generated from one authority
@@ -277,7 +277,7 @@ from it.
277
277
 
278
278
  | Command | Tier | Answers | Note |
279
279
  |---|---|---|---|
280
- | `posture` | experimental | which beans a profile set wires, and how effective endpoint access differs between two sets | the most differentiated capability here |
280
+ | `posture` | supported | which beans a profile set wires, and how effective endpoint access differs between two sets | the most differentiated capability here |
281
281
  | `risk` | experimental | what each defect actually costs, once reach, access, write effect and the shape of the input path are in it | `defect_severity × reachability × auth_verdict × write_effect × query_construction × input_constraints`; every factor names its authority; `--table --rule SEC-008 --band high --top-n 20` gives audit triage without `jq` |
282
282
  | `enrich` | experimental | another scanner's SARIF findings, ranked by what this repository does with them | `--sarif <log>`; same composition as `risk`, with `--table --rule <id> --band high --top-n 20` for triage |
283
283
  | `audit-report` | experimental | human audit bundle over existing `risk` + `posture` evidence, optionally signed | includes `evidence_manifest` claim provenance; `--format markdown`; `--sign-key <file>` signs canonical JSON with HMAC-SHA256 |
@@ -360,6 +360,12 @@ And one about who calls a route:
360
360
  |---|---|---|
361
361
  | **Whether a route is called from outside this repository — another service, a mobile app, a partner, a cron job, or a client whose URL is assembled at run time.** | The join reads the TypeScript/JavaScript checked in beside the server and only the call shapes whose verb and path are written at the call site. That is a floor on who calls a route and can never be a ceiling: the repository cannot observe consumers it does not contain. So a route with no call site here is published as a candidate for deletion, never as dead API. | Access logs or an API gateway answer who really calls a route. The opposite direction is decisive without them: a client call matching no route is a request this repository's own front end makes and its server does not serve. |
362
362
 
363
+ And one about blast radius:
364
+
365
+ | Not covered | Why | What answers it |
366
+ |---|---|---|
367
+ | **The reach of a component the container invokes rather than the code — a security filter chain, an around-advice aspect, a `@ControllerAdvice`, a bean resolved through the interface it implements.** | Blast radius here is projected over the call graph: who calls the changed symbol, and which routes reach those callers. Nothing in the repository calls a container-wired component, so its measured call-graph fan-in is ~0 and every figure derived from it — affected endpoints, direct callers, rollback surface — reads as no impact. The fan-in figure is correct; using it as a risk proxy on this population is not. Publishing that as a low verdict would be a confident zero, which is the one thing this product does not do. | Such a change is flagged in `analysis_warnings` and its verdict is floored, never rated on fan-in. The reach itself is measured elsewhere and was there all along: `ask endpoints` resolves a gate annotation to the routes carrying it, `ask explain <class>` prints the request chain a configuration declares with its source line, and `ask posture --profile <set>` states what each profile leaves open. Projecting those into the blast radius (pointcut → routes, matcher → routes) is a measurement this command does not yet make. |
368
+
363
369
  The one row above with a remedy in this build: `ask endpoints /path/to/repo --servlets`
364
370
  lists the servlet-mounted HTTP surface as a population of its own — `web.xml` mappings and
365
371
  `ServletRegistrationBean` registrations, with the file that declares each — and never merges
@@ -423,6 +429,9 @@ Full breakdown: [docs/PRODUCT_TIERS.md](docs/PRODUCT_TIERS.md).
423
429
 
424
430
  ```bash
425
431
  ask config # version, config file path, telemetry status
432
+ ask config /repo # + the repository's own sourcecode.config.json:
433
+ # data labels, custom security annotations,
434
+ # and any declaration that could not be used
426
435
  ask telemetry enable # anonymous telemetry is OFF by default (opt-in)
427
436
  ```
428
437
 
@@ -459,7 +468,7 @@ Matching endpoints report `policy: "custom"` and drop out of the `no_security_si
459
468
  | [USER_GUIDE.md](docs/USER_GUIDE.md) | Full command reference, flags, output schema, workflows |
460
469
  | [contracts.md](docs/contracts.md) | Declare invariants in `.ask/contracts.yml` (or derive them with `ask verify --init`), enforce them in the edit loop and in CI |
461
470
  | [baseline-ci.yml](docs/baseline-ci.yml) | Capture an architectural baseline per release, so the series exists when you want to read it |
462
- | [posture.md](docs/posture.md) | What a profile set actually wires — down to which endpoints its filter chain permits — and what could not be decided (experimental) |
471
+ | [posture.md](docs/posture.md) | What a profile set actually wires — down to which endpoints its filter chain permits — and what could not be decided |
463
472
  | [migrate-check.md](docs/migrate-check.md) | Migration rule catalogue (MIG-001..043) + Hibernate stratification |
464
473
  | [MODERNIZATION.md](docs/MODERNIZATION.md) | The modernization product: assess → understand → plan → execute |
465
474
  | [PRODUCT_TIERS.md](docs/PRODUCT_TIERS.md) | Free vs Pro, pricing model |
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "sourcecode"
7
- version = "4.10.5"
7
+ version = "4.10.7"
8
8
  description = "Persistent structural context and ultra-fast repeated analysis for AI coding agents"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.9"
@@ -4,4 +4,4 @@ ASK Engine is the product. ``ask`` is the canonical CLI command; ``sourcecode``
4
4
  the legacy compatibility alias and the Python/PyPI package name. See
5
5
  docs/PRODUCT_IDENTITY.md (normative)."""
6
6
 
7
- __version__ = "4.10.5"
7
+ __version__ = "4.10.7"
@@ -136,6 +136,19 @@ def _fan_in_from_stored(value: Any) -> dict[str, int]:
136
136
  return {}
137
137
 
138
138
 
139
+ def _comparability_env() -> dict:
140
+ """The environment fields a delta actually depends on (C3-68).
141
+
142
+ A baseline is comparable to another when the platform and the tool agree;
143
+ the CPU model, the core count and a hash of the hostname change none of
144
+ that. `--record-env` restores the full set for someone benchmarking runs
145
+ against each other on one machine.
146
+ """
147
+ import sys as _sys
148
+
149
+ return {"os": _sys.platform, "tool_version": TOOL_VERSION, "recorded": "comparability_only"}
150
+
151
+
139
152
  def build_baseline(
140
153
  cir: "CanonicalRepositoryIR",
141
154
  *,
@@ -145,6 +158,7 @@ def build_baseline(
145
158
  captured_at: str | None = None,
146
159
  env: dict | None = None,
147
160
  tool_version: str | None = None,
161
+ record_env: bool = False,
148
162
  ) -> dict:
149
163
  """Freeze a CIR's measured architectural metrics into a baseline artifact.
150
164
 
@@ -168,6 +182,21 @@ def build_baseline(
168
182
  "files": m.file_count,
169
183
  "symbols": m.symbol_count,
170
184
  "endpoints": m.endpoint_count,
185
+ # C1-37: this artefact's declared purpose is to be a replayable
186
+ # fingerprint, and it disagreed with itself — `totals.endpoints`
187
+ # 3 574 against `len(endpoint_surface)` 3 538 on the field
188
+ # repository. Neither figure was wrong: `endpoints` counts handler
189
+ # mappings and `endpoint_surface` is the set of distinct
190
+ # (METHOD, path) contract pairs, so 36 routes are declared by more
191
+ # than one handler. Two facts, two names, and the invariant the
192
+ # battery can actually hold.
193
+ "endpoint_contract_pairs": len(m.endpoints),
194
+ "endpoints_unit": (
195
+ "handler mappings declared in the repository; "
196
+ "`endpoint_contract_pairs` counts the distinct (METHOD, path) "
197
+ "pairs those mappings expose, which is what `endpoint_surface` "
198
+ "lists and what a diff compares"
199
+ ),
171
200
  "dependency_edges": m.dependency_edge_count,
172
201
  "import_cycles": len(m.cycles),
173
202
  },
@@ -175,7 +204,16 @@ def build_baseline(
175
204
  "endpoint_surface": endpoints,
176
205
  "fan_in": _fan_in_to_list(m.fan_in),
177
206
  "import_cycles": cycles,
178
- "env": env if env is not None else collect_env(),
207
+ # C3-68: this artefact is written inside the work tree, so what it
208
+ # records is what a `git add -A` publishes. `hostname_hash`, `cpu` and
209
+ # `cores` describe the developer's machine and affect nothing a delta
210
+ # compares — from a tool whose own `ask config` says telemetry is off.
211
+ # The default is now the two fields that DO decide comparability; the
212
+ # rest is opt-in per capture.
213
+ "env": (
214
+ env if env is not None
215
+ else (collect_env() if record_env else _comparability_env())
216
+ ),
179
217
  "provenance": (
180
218
  "architectural_baseline (D5): a measured structural fingerprint of one "
181
219
  "CIR, persisted per ref. Metric content is a pure function of the repo "
@@ -319,9 +357,50 @@ def _baseline_filename(baseline: dict) -> str:
319
357
  return f"{safe}.json"
320
358
 
321
359
 
360
+ #: What `.ask/` gets the moment it is created, and why.
361
+ #:
362
+ #: C3-68: `baseline capture` writes into the work tree and nothing protected it.
363
+ #: The field verified `grep -nE "^\.ask|sourcecode" .gitignore` → no matches, so
364
+ #: a `git add -A` commits the artefact — which carries a machine fingerprint and
365
+ #: a 14 587-entry structural inventory of the code. A self-confined
366
+ #: `.ask/.gitignore` is the honest form: it never touches the user's own
367
+ #: `.gitignore`, and it stops applying the moment they delete the directory.
368
+ _ASK_DIR_GITIGNORE = (
369
+ "# Written by `ask` the first time it created this directory.\n"
370
+ "# These are local analysis artefacts: a structural inventory of your code\n"
371
+ "# and, if you asked for it, the machine that measured it. Nothing here\n"
372
+ "# belongs in a commit. Delete this file to version them deliberately.\n"
373
+ "*\n"
374
+ )
375
+
376
+
377
+ def protect_ask_dir(out_dir: Path) -> None:
378
+ """Give a freshly created `.ask/` its own `.gitignore` (C3-68).
379
+
380
+ Best-effort and never overwriting: a user who edited it decided something,
381
+ and a tool that re-imposes its default on every run is worse than one that
382
+ never wrote it.
383
+ """
384
+ try:
385
+ ask_dir = Path(out_dir)
386
+ while ask_dir.name and ask_dir.name != ".ask":
387
+ if ask_dir.parent == ask_dir:
388
+ return
389
+ ask_dir = ask_dir.parent
390
+ if ask_dir.name != ".ask":
391
+ return
392
+ marker = ask_dir / ".gitignore"
393
+ if not marker.exists():
394
+ ask_dir.mkdir(parents=True, exist_ok=True)
395
+ marker.write_text(_ASK_DIR_GITIGNORE, encoding="utf-8")
396
+ except OSError:
397
+ return
398
+
399
+
322
400
  def write_baseline(baseline: dict, out_dir: Path) -> Path:
323
401
  """Write `baseline` as deterministic JSON under `out_dir`; return the file path."""
324
402
  out_dir.mkdir(parents=True, exist_ok=True)
403
+ protect_ask_dir(out_dir)
325
404
  path = out_dir / _baseline_filename(baseline)
326
405
  path.write_text(
327
406
  json.dumps(baseline, sort_keys=True, indent=2) + "\n", encoding="utf-8"
@@ -336,10 +336,15 @@ def cache_dir(repo_root: Path) -> Path:
336
336
  def status(repo_root: Path) -> dict[str, Any]:
337
337
  """Return a stats dict describing the current cache state for *repo_root*.
338
338
 
339
- Keys: ``cache_dir``, ``cores``, ``views``, ``cas_blobs``,
339
+ Keys: ``cache_dir``, ``cached_cores``, ``views``, ``cas_blobs``,
340
340
  ``total_size_bytes``, ``total_size_mb``, ``ris_exists``, ``ris_git_head``,
341
341
  ``ris_last_updated_at``, ``ris_is_stale``, ``current_git_head``.
342
342
 
343
+ ``cached_cores`` counts ``core-*.json.gz`` entries in this cache. It was
344
+ named ``cores`` until 4.10.7, which is the field name a captured baseline
345
+ uses for the machine's CPU count (``env.cores``) — two different facts under
346
+ one name, on the same machine, minutes apart (C4-18).
347
+
343
348
  Note: ``snapshots`` is a legacy v1 field — always 0 in v2 (kept for
344
349
  backward compatibility; v2 writes ``core-*`` and ``view-*`` files only).
345
350
  """
@@ -377,7 +382,7 @@ def status(repo_root: Path) -> dict[str, Any]:
377
382
  if not cache_d.exists():
378
383
  return {
379
384
  "cache_dir": str(cache_d),
380
- "cores": 0, "snapshots": 0, "views": 0, "cas_blobs": 0,
385
+ "cached_cores": 0, "snapshots": 0, "views": 0, "cas_blobs": 0,
381
386
  "total_size_bytes": 0, "total_size_mb": 0.0,
382
387
  "current_git_head": current_head,
383
388
  "stores": _store_breakdown(repo_root, 0),
@@ -391,7 +396,7 @@ def status(repo_root: Path) -> dict[str, Any]:
391
396
  total_bytes = sum(f.stat().st_size for f in all_files if f.exists())
392
397
  return {
393
398
  "cache_dir": str(cache_d),
394
- "cores": len(cores),
399
+ "cached_cores": len(cores),
395
400
  "snapshots": len(snapshots),
396
401
  "views": len(views),
397
402
  "cas_blobs": len(cas_blobs),