sourcecode 4.1.0__tar.gz → 4.3.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 (213) hide show
  1. {sourcecode-4.1.0 → sourcecode-4.3.0}/CHANGELOG.md +335 -0
  2. {sourcecode-4.1.0 → sourcecode-4.3.0}/PKG-INFO +41 -8
  3. {sourcecode-4.1.0 → sourcecode-4.3.0}/README.md +40 -7
  4. {sourcecode-4.1.0 → sourcecode-4.3.0}/pyproject.toml +1 -1
  5. {sourcecode-4.1.0 → sourcecode-4.3.0}/src/sourcecode/__init__.py +1 -1
  6. {sourcecode-4.1.0 → sourcecode-4.3.0}/src/sourcecode/architectural_baseline.py +19 -0
  7. sourcecode-4.3.0/src/sourcecode/baseline_autocapture.py +375 -0
  8. {sourcecode-4.1.0 → sourcecode-4.3.0}/src/sourcecode/cache_model.py +19 -0
  9. {sourcecode-4.1.0 → sourcecode-4.3.0}/src/sourcecode/caller_reach.py +16 -7
  10. {sourcecode-4.1.0 → sourcecode-4.3.0}/src/sourcecode/canonical_ir.py +29 -0
  11. {sourcecode-4.1.0 → sourcecode-4.3.0}/src/sourcecode/cli.py +787 -26
  12. sourcecode-4.3.0/src/sourcecode/client_calls.py +305 -0
  13. {sourcecode-4.1.0 → sourcecode-4.3.0}/src/sourcecode/context_graph.py +11 -0
  14. {sourcecode-4.1.0 → sourcecode-4.3.0}/src/sourcecode/contract_diff.py +5 -4
  15. sourcecode-4.3.0/src/sourcecode/data_exposure.py +353 -0
  16. sourcecode-4.3.0/src/sourcecode/data_labels.py +200 -0
  17. {sourcecode-4.1.0 → sourcecode-4.3.0}/src/sourcecode/dynamic_argument_surface.py +12 -5
  18. {sourcecode-4.1.0 → sourcecode-4.3.0}/src/sourcecode/environment_resolution.py +100 -6
  19. {sourcecode-4.1.0 → sourcecode-4.3.0}/src/sourcecode/facts/registry.json +15 -0
  20. {sourcecode-4.1.0 → sourcecode-4.3.0}/src/sourcecode/format_contract.py +1 -0
  21. {sourcecode-4.1.0 → sourcecode-4.3.0}/src/sourcecode/git_checkout.py +5 -2
  22. {sourcecode-4.1.0 → sourcecode-4.3.0}/src/sourcecode/non_coverage.py +70 -0
  23. sourcecode-4.3.0/src/sourcecode/openrewrite_recipe.py +278 -0
  24. {sourcecode-4.1.0 → sourcecode-4.3.0}/src/sourcecode/posture.py +425 -7
  25. {sourcecode-4.1.0 → sourcecode-4.3.0}/src/sourcecode/remedies.py +18 -1
  26. {sourcecode-4.1.0 → sourcecode-4.3.0}/src/sourcecode/repository_ir.py +24 -3
  27. sourcecode-4.3.0/src/sourcecode/risk.py +764 -0
  28. sourcecode-4.3.0/src/sourcecode/sarif.py +618 -0
  29. {sourcecode-4.1.0 → sourcecode-4.3.0}/src/sourcecode/spring_impact.py +14 -3
  30. {sourcecode-4.1.0 → sourcecode-4.3.0}/src/sourcecode/validation_inference.py +33 -4
  31. {sourcecode-4.1.0 → sourcecode-4.3.0}/src/sourcecode/verify_repo.py +22 -2
  32. sourcecode-4.1.0/src/sourcecode/risk.py +0 -345
  33. {sourcecode-4.1.0 → sourcecode-4.3.0}/.github/workflows/build-windows.yml +0 -0
  34. {sourcecode-4.1.0 → sourcecode-4.3.0}/.gitignore +0 -0
  35. {sourcecode-4.1.0 → sourcecode-4.3.0}/.ruff.toml +0 -0
  36. {sourcecode-4.1.0 → sourcecode-4.3.0}/CONTRIBUTING.md +0 -0
  37. {sourcecode-4.1.0 → sourcecode-4.3.0}/LICENSE +0 -0
  38. {sourcecode-4.1.0 → sourcecode-4.3.0}/SECURITY.md +0 -0
  39. {sourcecode-4.1.0 → sourcecode-4.3.0}/raw +0 -0
  40. {sourcecode-4.1.0 → sourcecode-4.3.0}/scripts/compare_integration_engines.py +0 -0
  41. {sourcecode-4.1.0 → sourcecode-4.3.0}/scripts/customer_smoke_test.sh +0 -0
  42. {sourcecode-4.1.0 → sourcecode-4.3.0}/scripts/generate_jdk_exports.py +0 -0
  43. {sourcecode-4.1.0 → sourcecode-4.3.0}/scripts/perf_harness.py +0 -0
  44. {sourcecode-4.1.0 → sourcecode-4.3.0}/src/sourcecode/adaptive_scanner.py +0 -0
  45. {sourcecode-4.1.0 → sourcecode-4.3.0}/src/sourcecode/archetype.py +0 -0
  46. {sourcecode-4.1.0 → sourcecode-4.3.0}/src/sourcecode/architectural_delta.py +0 -0
  47. {sourcecode-4.1.0 → sourcecode-4.3.0}/src/sourcecode/architecture_analyzer.py +0 -0
  48. {sourcecode-4.1.0 → sourcecode-4.3.0}/src/sourcecode/architecture_summary.py +0 -0
  49. {sourcecode-4.1.0 → sourcecode-4.3.0}/src/sourcecode/ast_extractor.py +0 -0
  50. {sourcecode-4.1.0 → sourcecode-4.3.0}/src/sourcecode/cache.py +0 -0
  51. {sourcecode-4.1.0 → sourcecode-4.3.0}/src/sourcecode/call_surface.py +0 -0
  52. {sourcecode-4.1.0 → sourcecode-4.3.0}/src/sourcecode/caller_metrics.py +0 -0
  53. {sourcecode-4.1.0 → sourcecode-4.3.0}/src/sourcecode/chain_rules.py +0 -0
  54. {sourcecode-4.1.0 → sourcecode-4.3.0}/src/sourcecode/change_plan.py +0 -0
  55. {sourcecode-4.1.0 → sourcecode-4.3.0}/src/sourcecode/cir_graphs.py +0 -0
  56. {sourcecode-4.1.0 → sourcecode-4.3.0}/src/sourcecode/classifier.py +0 -0
  57. {sourcecode-4.1.0 → sourcecode-4.3.0}/src/sourcecode/code_notes_analyzer.py +0 -0
  58. {sourcecode-4.1.0 → sourcecode-4.3.0}/src/sourcecode/compare.py +0 -0
  59. {sourcecode-4.1.0 → sourcecode-4.3.0}/src/sourcecode/confidence_analyzer.py +0 -0
  60. {sourcecode-4.1.0 → sourcecode-4.3.0}/src/sourcecode/constraint_diff.py +0 -0
  61. {sourcecode-4.1.0 → sourcecode-4.3.0}/src/sourcecode/context_cache.py +0 -0
  62. {sourcecode-4.1.0 → sourcecode-4.3.0}/src/sourcecode/context_scorer.py +0 -0
  63. {sourcecode-4.1.0 → sourcecode-4.3.0}/src/sourcecode/context_summarizer.py +0 -0
  64. {sourcecode-4.1.0 → sourcecode-4.3.0}/src/sourcecode/contract_init.py +0 -0
  65. {sourcecode-4.1.0 → sourcecode-4.3.0}/src/sourcecode/contract_model.py +0 -0
  66. {sourcecode-4.1.0 → sourcecode-4.3.0}/src/sourcecode/contract_pipeline.py +0 -0
  67. {sourcecode-4.1.0 → sourcecode-4.3.0}/src/sourcecode/coverage_parser.py +0 -0
  68. {sourcecode-4.1.0 → sourcecode-4.3.0}/src/sourcecode/defect_identity.py +0 -0
  69. {sourcecode-4.1.0 → sourcecode-4.3.0}/src/sourcecode/degradation.py +0 -0
  70. {sourcecode-4.1.0 → sourcecode-4.3.0}/src/sourcecode/dependency_analyzer.py +0 -0
  71. {sourcecode-4.1.0 → sourcecode-4.3.0}/src/sourcecode/deployment_prefix.py +0 -0
  72. {sourcecode-4.1.0 → sourcecode-4.3.0}/src/sourcecode/detectors/__init__.py +0 -0
  73. {sourcecode-4.1.0 → sourcecode-4.3.0}/src/sourcecode/detectors/base.py +0 -0
  74. {sourcecode-4.1.0 → sourcecode-4.3.0}/src/sourcecode/detectors/csproj_parser.py +0 -0
  75. {sourcecode-4.1.0 → sourcecode-4.3.0}/src/sourcecode/detectors/dart.py +0 -0
  76. {sourcecode-4.1.0 → sourcecode-4.3.0}/src/sourcecode/detectors/dotnet.py +0 -0
  77. {sourcecode-4.1.0 → sourcecode-4.3.0}/src/sourcecode/detectors/elixir.py +0 -0
  78. {sourcecode-4.1.0 → sourcecode-4.3.0}/src/sourcecode/detectors/go.py +0 -0
  79. {sourcecode-4.1.0 → sourcecode-4.3.0}/src/sourcecode/detectors/heuristic.py +0 -0
  80. {sourcecode-4.1.0 → sourcecode-4.3.0}/src/sourcecode/detectors/hybrid.py +0 -0
  81. {sourcecode-4.1.0 → sourcecode-4.3.0}/src/sourcecode/detectors/java.py +0 -0
  82. {sourcecode-4.1.0 → sourcecode-4.3.0}/src/sourcecode/detectors/jvm_ext.py +0 -0
  83. {sourcecode-4.1.0 → sourcecode-4.3.0}/src/sourcecode/detectors/nodejs.py +0 -0
  84. {sourcecode-4.1.0 → sourcecode-4.3.0}/src/sourcecode/detectors/parsers.py +0 -0
  85. {sourcecode-4.1.0 → sourcecode-4.3.0}/src/sourcecode/detectors/php.py +0 -0
  86. {sourcecode-4.1.0 → sourcecode-4.3.0}/src/sourcecode/detectors/project.py +0 -0
  87. {sourcecode-4.1.0 → sourcecode-4.3.0}/src/sourcecode/detectors/python.py +0 -0
  88. {sourcecode-4.1.0 → sourcecode-4.3.0}/src/sourcecode/detectors/ruby.py +0 -0
  89. {sourcecode-4.1.0 → sourcecode-4.3.0}/src/sourcecode/detectors/rust.py +0 -0
  90. {sourcecode-4.1.0 → sourcecode-4.3.0}/src/sourcecode/detectors/systems.py +0 -0
  91. {sourcecode-4.1.0 → sourcecode-4.3.0}/src/sourcecode/detectors/terraform.py +0 -0
  92. {sourcecode-4.1.0 → sourcecode-4.3.0}/src/sourcecode/detectors/tooling.py +0 -0
  93. {sourcecode-4.1.0 → sourcecode-4.3.0}/src/sourcecode/doc_analyzer.py +0 -0
  94. {sourcecode-4.1.0 → sourcecode-4.3.0}/src/sourcecode/endpoint_literals.py +0 -0
  95. {sourcecode-4.1.0 → sourcecode-4.3.0}/src/sourcecode/endpoint_metrics.py +0 -0
  96. {sourcecode-4.1.0 → sourcecode-4.3.0}/src/sourcecode/entrypoint_classifier.py +0 -0
  97. {sourcecode-4.1.0 → sourcecode-4.3.0}/src/sourcecode/env_analyzer.py +0 -0
  98. {sourcecode-4.1.0 → sourcecode-4.3.0}/src/sourcecode/envelope.py +0 -0
  99. {sourcecode-4.1.0 → sourcecode-4.3.0}/src/sourcecode/error_schema.py +0 -0
  100. {sourcecode-4.1.0 → sourcecode-4.3.0}/src/sourcecode/evidence_provider.py +0 -0
  101. {sourcecode-4.1.0 → sourcecode-4.3.0}/src/sourcecode/explain.py +0 -0
  102. {sourcecode-4.1.0 → sourcecode-4.3.0}/src/sourcecode/facts/__init__.py +0 -0
  103. {sourcecode-4.1.0 → sourcecode-4.3.0}/src/sourcecode/file_chunker.py +0 -0
  104. {sourcecode-4.1.0 → sourcecode-4.3.0}/src/sourcecode/file_classifier.py +0 -0
  105. {sourcecode-4.1.0 → sourcecode-4.3.0}/src/sourcecode/filter_surface.py +0 -0
  106. {sourcecode-4.1.0 → sourcecode-4.3.0}/src/sourcecode/fqn_utils.py +0 -0
  107. {sourcecode-4.1.0 → sourcecode-4.3.0}/src/sourcecode/git_analyzer.py +0 -0
  108. {sourcecode-4.1.0 → sourcecode-4.3.0}/src/sourcecode/graph_analyzer.py +0 -0
  109. {sourcecode-4.1.0 → sourcecode-4.3.0}/src/sourcecode/graph_evidence.py +0 -0
  110. {sourcecode-4.1.0 → sourcecode-4.3.0}/src/sourcecode/hibernate_strat.py +0 -0
  111. {sourcecode-4.1.0 → sourcecode-4.3.0}/src/sourcecode/identity_fallback.py +0 -0
  112. {sourcecode-4.1.0 → sourcecode-4.3.0}/src/sourcecode/integration_coordinates.py +0 -0
  113. {sourcecode-4.1.0 → sourcecode-4.3.0}/src/sourcecode/jdk_exports.py +0 -0
  114. {sourcecode-4.1.0 → sourcecode-4.3.0}/src/sourcecode/license.py +0 -0
  115. {sourcecode-4.1.0 → sourcecode-4.3.0}/src/sourcecode/mcp/__init__.py +0 -0
  116. {sourcecode-4.1.0 → sourcecode-4.3.0}/src/sourcecode/mcp/onboarding/__init__.py +0 -0
  117. {sourcecode-4.1.0 → sourcecode-4.3.0}/src/sourcecode/mcp/onboarding/applier.py +0 -0
  118. {sourcecode-4.1.0 → sourcecode-4.3.0}/src/sourcecode/mcp/onboarding/backup.py +0 -0
  119. {sourcecode-4.1.0 → sourcecode-4.3.0}/src/sourcecode/mcp/onboarding/detector.py +0 -0
  120. {sourcecode-4.1.0 → sourcecode-4.3.0}/src/sourcecode/mcp/onboarding/planner.py +0 -0
  121. {sourcecode-4.1.0 → sourcecode-4.3.0}/src/sourcecode/mcp/orchestrator.py +0 -0
  122. {sourcecode-4.1.0 → sourcecode-4.3.0}/src/sourcecode/mcp/registry.py +0 -0
  123. {sourcecode-4.1.0 → sourcecode-4.3.0}/src/sourcecode/mcp/runner.py +0 -0
  124. {sourcecode-4.1.0 → sourcecode-4.3.0}/src/sourcecode/mcp/server.py +0 -0
  125. {sourcecode-4.1.0 → sourcecode-4.3.0}/src/sourcecode/mcp_nudge.py +0 -0
  126. {sourcecode-4.1.0 → sourcecode-4.3.0}/src/sourcecode/metrics_analyzer.py +0 -0
  127. {sourcecode-4.1.0 → sourcecode-4.3.0}/src/sourcecode/migrate_check.py +0 -0
  128. {sourcecode-4.1.0 → sourcecode-4.3.0}/src/sourcecode/migration_blast.py +0 -0
  129. {sourcecode-4.1.0 → sourcecode-4.3.0}/src/sourcecode/openapi_surface.py +0 -0
  130. {sourcecode-4.1.0 → sourcecode-4.3.0}/src/sourcecode/output_budget.py +0 -0
  131. {sourcecode-4.1.0 → sourcecode-4.3.0}/src/sourcecode/parse_cache.py +0 -0
  132. {sourcecode-4.1.0 → sourcecode-4.3.0}/src/sourcecode/path_admission.py +0 -0
  133. {sourcecode-4.1.0 → sourcecode-4.3.0}/src/sourcecode/path_filters.py +0 -0
  134. {sourcecode-4.1.0 → sourcecode-4.3.0}/src/sourcecode/perf.py +0 -0
  135. {sourcecode-4.1.0 → sourcecode-4.3.0}/src/sourcecode/pipe_contract.py +0 -0
  136. {sourcecode-4.1.0 → sourcecode-4.3.0}/src/sourcecode/pr_comment_renderer.py +0 -0
  137. {sourcecode-4.1.0 → sourcecode-4.3.0}/src/sourcecode/pr_impact.py +0 -0
  138. {sourcecode-4.1.0 → sourcecode-4.3.0}/src/sourcecode/prepare_context.py +0 -0
  139. {sourcecode-4.1.0 → sourcecode-4.3.0}/src/sourcecode/progress.py +0 -0
  140. {sourcecode-4.1.0 → sourcecode-4.3.0}/src/sourcecode/ranking_engine.py +0 -0
  141. {sourcecode-4.1.0 → sourcecode-4.3.0}/src/sourcecode/readiness_timeline.py +0 -0
  142. {sourcecode-4.1.0 → sourcecode-4.3.0}/src/sourcecode/reconciliation.py +0 -0
  143. {sourcecode-4.1.0 → sourcecode-4.3.0}/src/sourcecode/redactor.py +0 -0
  144. {sourcecode-4.1.0 → sourcecode-4.3.0}/src/sourcecode/reference_facts.py +0 -0
  145. {sourcecode-4.1.0 → sourcecode-4.3.0}/src/sourcecode/release_info.py +0 -0
  146. {sourcecode-4.1.0 → sourcecode-4.3.0}/src/sourcecode/relevance_scorer.py +0 -0
  147. {sourcecode-4.1.0 → sourcecode-4.3.0}/src/sourcecode/rename_refactor.py +0 -0
  148. {sourcecode-4.1.0 → sourcecode-4.3.0}/src/sourcecode/repo_classifier.py +0 -0
  149. {sourcecode-4.1.0 → sourcecode-4.3.0}/src/sourcecode/retrieval/__init__.py +0 -0
  150. {sourcecode-4.1.0 → sourcecode-4.3.0}/src/sourcecode/retrieval/context.py +0 -0
  151. {sourcecode-4.1.0 → sourcecode-4.3.0}/src/sourcecode/retrieval/errors.py +0 -0
  152. {sourcecode-4.1.0 → sourcecode-4.3.0}/src/sourcecode/retrieval/executor.py +0 -0
  153. {sourcecode-4.1.0 → sourcecode-4.3.0}/src/sourcecode/retrieval/planner.py +0 -0
  154. {sourcecode-4.1.0 → sourcecode-4.3.0}/src/sourcecode/retrieval/query.py +0 -0
  155. {sourcecode-4.1.0 → sourcecode-4.3.0}/src/sourcecode/retrieval/request.py +0 -0
  156. {sourcecode-4.1.0 → sourcecode-4.3.0}/src/sourcecode/retrieval/resolution.py +0 -0
  157. {sourcecode-4.1.0 → sourcecode-4.3.0}/src/sourcecode/retrieval/result.py +0 -0
  158. {sourcecode-4.1.0 → sourcecode-4.3.0}/src/sourcecode/retrieval/retriever.py +0 -0
  159. {sourcecode-4.1.0 → sourcecode-4.3.0}/src/sourcecode/retrieval/runtime.py +0 -0
  160. {sourcecode-4.1.0 → sourcecode-4.3.0}/src/sourcecode/retrieval/steps.py +0 -0
  161. {sourcecode-4.1.0 → sourcecode-4.3.0}/src/sourcecode/retrieval/steps_endpoint.py +0 -0
  162. {sourcecode-4.1.0 → sourcecode-4.3.0}/src/sourcecode/retrieval/steps_graph.py +0 -0
  163. {sourcecode-4.1.0 → sourcecode-4.3.0}/src/sourcecode/retrieval/steps_impact.py +0 -0
  164. {sourcecode-4.1.0 → sourcecode-4.3.0}/src/sourcecode/retrieval/steps_intf.py +0 -0
  165. {sourcecode-4.1.0 → sourcecode-4.3.0}/src/sourcecode/retrieval/steps_struct.py +0 -0
  166. {sourcecode-4.1.0 → sourcecode-4.3.0}/src/sourcecode/retrieval/steps_txsec.py +0 -0
  167. {sourcecode-4.1.0 → sourcecode-4.3.0}/src/sourcecode/ris.py +0 -0
  168. {sourcecode-4.1.0 → sourcecode-4.3.0}/src/sourcecode/rule_catalog.py +0 -0
  169. {sourcecode-4.1.0 → sourcecode-4.3.0}/src/sourcecode/runtime_classifier.py +0 -0
  170. {sourcecode-4.1.0 → sourcecode-4.3.0}/src/sourcecode/scanner.py +0 -0
  171. {sourcecode-4.1.0 → sourcecode-4.3.0}/src/sourcecode/schema.py +0 -0
  172. {sourcecode-4.1.0 → sourcecode-4.3.0}/src/sourcecode/schemas/envelope-v1.schema.json +0 -0
  173. {sourcecode-4.1.0 → sourcecode-4.3.0}/src/sourcecode/security_config.py +0 -0
  174. {sourcecode-4.1.0 → sourcecode-4.3.0}/src/sourcecode/security_config_scan.py +0 -0
  175. {sourcecode-4.1.0 → sourcecode-4.3.0}/src/sourcecode/security_posture.py +0 -0
  176. {sourcecode-4.1.0 → sourcecode-4.3.0}/src/sourcecode/semantic_analyzer.py +0 -0
  177. {sourcecode-4.1.0 → sourcecode-4.3.0}/src/sourcecode/semantic_impact_engine.py +0 -0
  178. {sourcecode-4.1.0 → sourcecode-4.3.0}/src/sourcecode/semantic_integration_engine.py +0 -0
  179. {sourcecode-4.1.0 → sourcecode-4.3.0}/src/sourcecode/semantic_services.py +0 -0
  180. {sourcecode-4.1.0 → sourcecode-4.3.0}/src/sourcecode/serializer.py +0 -0
  181. {sourcecode-4.1.0 → sourcecode-4.3.0}/src/sourcecode/spring_event_topology.py +0 -0
  182. {sourcecode-4.1.0 → sourcecode-4.3.0}/src/sourcecode/spring_findings.py +0 -0
  183. {sourcecode-4.1.0 → sourcecode-4.3.0}/src/sourcecode/spring_model.py +0 -0
  184. {sourcecode-4.1.0 → sourcecode-4.3.0}/src/sourcecode/spring_profiles.py +0 -0
  185. {sourcecode-4.1.0 → sourcecode-4.3.0}/src/sourcecode/spring_properties.py +0 -0
  186. {sourcecode-4.1.0 → sourcecode-4.3.0}/src/sourcecode/spring_security_audit.py +0 -0
  187. {sourcecode-4.1.0 → sourcecode-4.3.0}/src/sourcecode/spring_semantic.py +0 -0
  188. {sourcecode-4.1.0 → sourcecode-4.3.0}/src/sourcecode/spring_tx_analyzer.py +0 -0
  189. {sourcecode-4.1.0 → sourcecode-4.3.0}/src/sourcecode/summarizer.py +0 -0
  190. {sourcecode-4.1.0 → sourcecode-4.3.0}/src/sourcecode/target_admission.py +0 -0
  191. {sourcecode-4.1.0 → sourcecode-4.3.0}/src/sourcecode/telemetry/__init__.py +0 -0
  192. {sourcecode-4.1.0 → sourcecode-4.3.0}/src/sourcecode/telemetry/config.py +0 -0
  193. {sourcecode-4.1.0 → sourcecode-4.3.0}/src/sourcecode/telemetry/consent.py +0 -0
  194. {sourcecode-4.1.0 → sourcecode-4.3.0}/src/sourcecode/telemetry/events.py +0 -0
  195. {sourcecode-4.1.0 → sourcecode-4.3.0}/src/sourcecode/telemetry/filters.py +0 -0
  196. {sourcecode-4.1.0 → sourcecode-4.3.0}/src/sourcecode/telemetry/transport.py +0 -0
  197. {sourcecode-4.1.0 → sourcecode-4.3.0}/src/sourcecode/test_gap_ranking.py +0 -0
  198. {sourcecode-4.1.0 → sourcecode-4.3.0}/src/sourcecode/test_sources.py +0 -0
  199. {sourcecode-4.1.0 → sourcecode-4.3.0}/src/sourcecode/token_estimate.py +0 -0
  200. {sourcecode-4.1.0 → sourcecode-4.3.0}/src/sourcecode/tree_utils.py +0 -0
  201. {sourcecode-4.1.0 → sourcecode-4.3.0}/src/sourcecode/type_usage_surface.py +0 -0
  202. {sourcecode-4.1.0 → sourcecode-4.3.0}/src/sourcecode/validation_surface.py +0 -0
  203. {sourcecode-4.1.0 → sourcecode-4.3.0}/src/sourcecode/verify_edit.py +0 -0
  204. {sourcecode-4.1.0 → sourcecode-4.3.0}/src/sourcecode/verify_rules.py +0 -0
  205. {sourcecode-4.1.0 → sourcecode-4.3.0}/src/sourcecode/version_check.py +0 -0
  206. {sourcecode-4.1.0 → sourcecode-4.3.0}/src/sourcecode/workspace.py +0 -0
  207. {sourcecode-4.1.0 → sourcecode-4.3.0}/supabase/functions/README.md +0 -0
  208. {sourcecode-4.1.0 → sourcecode-4.3.0}/supabase/functions/get-license/index.ts +0 -0
  209. {sourcecode-4.1.0 → sourcecode-4.3.0}/supabase/functions/lemonsqueezy-webhook/index.ts +0 -0
  210. {sourcecode-4.1.0 → sourcecode-4.3.0}/supabase/functions/telemetry/index.ts +0 -0
  211. {sourcecode-4.1.0 → sourcecode-4.3.0}/supabase/sql/license_event_ordering.sql +0 -0
  212. {sourcecode-4.1.0 → sourcecode-4.3.0}/supabase/sql/licensing_schema.sql +0 -0
  213. {sourcecode-4.1.0 → sourcecode-4.3.0}/supabase/sql/telemetry_events.sql +0 -0
@@ -2,6 +2,341 @@
2
2
 
3
3
  ## [Unreleased]
4
4
 
5
+ ### Added
6
+
7
+ - **`ask migrate-recipe` — the migration report in the form the executor takes**
8
+ (roadmap M10.5 item 5 / M8.5, experimental). `migrate-check` already names the
9
+ OpenRewrite recipe each finding carries (296 of 309 on openmrs-core) and a reader
10
+ still had to copy them out of a JSON payload by hand — field evaluation #4's verdict
11
+ on that gap was *"el informe muere en un cajón; el codemod se convierte en PRs"*. The
12
+ command emits the declarative composite recipe naming exactly those recipes, the
13
+ artifact coordinates derived from their packages, and the invocation for the build the
14
+ repository declares (Maven or Gradle). It writes nothing without `--write`, so an audit
15
+ of somebody else's repository can run it; `--write` refuses to replace an existing
16
+ `rewrite.yml` without `--force`. **Nothing here edits source** — that is NC-005's
17
+ position, not a gap: OpenRewrite is the executor and this is its input.
18
+ - The recipe list comes from the findings, never from a catalogue of what OpenRewrite
19
+ can do: a recipe nobody's finding asked for would rewrite code nobody measured.
20
+ - Every finding with no recipe is published under `manual_remainder`. Measured on
21
+ BroadleafCommerce: **25 blocking findings in product code and not one automatable**,
22
+ which is an answer, not an empty result — and the reason an empty recipe list prints
23
+ *no* runnable command, because `mvn … rewrite:run` over nothing is a green executor
24
+ run that reads as "the migration is automated".
25
+ - Advisory hygiene is excluded by default (`--include-hygiene` opts in): on openmrs-core
26
+ it takes the population from 125 findings to 309 and adds `JavaTimeAPIs`, and a
27
+ migration diff that also modernises date handling cannot be reviewed as one change.
28
+ - The coverage block names **both** populations — its own and `migrate-check`'s narrower
29
+ `blocking_count` (125 against 114 on openmrs-core) — because two populations under one
30
+ name is the defect this project keeps finding in its own output.
31
+
32
+ ## [4.3.0] — 2026-08-03
33
+
34
+ Minor, not a patch: two commands are new (`ask enrich`, `ask data-exposure`), the
35
+ composed risk model gains two factors, and `ask verify` writes a file where it
36
+ wrote none — every one of them additive, none of them removing a published field
37
+ or moving an exit code. A pipeline that reads this release the way it read 4.2.0
38
+ gets the same answers, plus blocks it can ignore.
39
+
40
+ ### Added
41
+
42
+ - **`ask baseline capture --auto` — an architectural history that does not depend on
43
+ somebody remembering** (roadmap M10.5, head of the milestone). The snapshot has
44
+ shipped since D5; the *series* is the asset a competitor cannot backfill, and in
45
+ every repository measured so far its length is zero, because capture is a command a
46
+ human has to type. `--auto` is the form a pipeline can keep: it captures one baseline
47
+ per commit, keeps an already-captured commit instead of relabelling it, refuses to
48
+ file a tree with uncommitted changes under the commit it would be stored as, and
49
+ **exits 0 whatever happens** — a build never goes red because a snapshot could not be
50
+ taken. Every outcome names itself (`captured` / `skipped` with the reason and a
51
+ sentence of effect), so a pipeline log says which happened rather than going quiet.
52
+ A skip costs no analysis: the decision is taken before the IR is built, so the common
53
+ case in a per-push job is ~0.2 s against 1.8 s for a capture. New authority
54
+ `sourcecode/baseline_autocapture.py`; `docs/baseline-ci.yml` now captures per merge
55
+ as well as per tag.
56
+ - **`ask data-exposure` — which routes can carry the data you labelled, and who
57
+ reaches them** (roadmap M10.5 item 3, experimental). Nothing here detects sensitive
58
+ data: a label is a judgement about a domain, a field named `dni` is a national
59
+ identifier in one repository and a column name in another, and the engine never
60
+ branches on a name (VAI). It is declared once under `dataLabels` in
61
+ `sourcecode.config.json`; everything after that is measured over authorities that
62
+ already exist — the call reach `impact-chain` walks, the endpoint security surface
63
+ `risk` weighs, the profile resolution `posture` publishes (`--profile`). Two evidence
64
+ classes, published apart and never added together: `signature` (the handler names the
65
+ labelled type in its own signature) and `call_reach` (the chain reaches it — a
66
+ supremum, not a proof, because the mapping in between is not modelled: NC-008).
67
+ Measured: petclinic labelling `Owner#telephone` → **7 routes by signature**;
68
+ BroadleafCommerce labelling `Customer` → **6 by call reach and none by signature**,
69
+ because those controllers return view names. A repository that declared nothing is
70
+ `answered: false`, never zero exposed routes, and a declared type the graph never
71
+ resolved is named with the note that this is not evidence it is unexposed.
72
+ - **A request handler declares types too.** `_extract_class_type_refs` enumerated
73
+ `symbol_kind == "method"`, and a handler is classified `endpoint` at emission (a
74
+ factory method `bean`), so the class-scope type surface contained **no controller
75
+ signature anywhere in a repository**: `structural_references_to_type("Owner")` on
76
+ petclinic returned 3 atoms, none of them a route that takes an `Owner` as its request
77
+ body, and "which routes accept or return this type" answered nothing while looking
78
+ like an answer. Now 10 atoms, 7 of them handler signatures. Same shape as the F.4-1
79
+ body-surface seam, one scope up; `member_kind` still publishes the kind the symbol was
80
+ classified with.
81
+ - **The history answers from the repository path.** `ask trend .` and
82
+ `ask baseline trend .` now take either a repository or a directory of baselines, and
83
+ `ask baseline diff .` defaults to the newest point in that repository's own history
84
+ instead of requiring `--baseline <file>`. Capture writes to `<repo>/.ask/baselines`,
85
+ so making the reader name the storage directory was the same friction that kept the
86
+ series empty. An explicit directory (the `--dir` case) is unchanged, and a repository
87
+ with no history gets an error that names how to start one. New
88
+ `architectural_baseline.latest_baseline_path`, ordered exactly as the trend series is
89
+ ordered so "the last point" and "the base of a default diff" cannot disagree.
90
+ - **`ask verify` carries the history for free.** The gate is the run that already happens
91
+ on every push and already builds the IR a baseline is extracted from, so where a
92
+ repository keeps `.ask/baselines` the gate adds the current commit to it and publishes
93
+ what it did under `architectural_history` — on every run, including the ones that
94
+ captured nothing, because a series that silently stopped growing is invisible until the
95
+ day somebody needs it (I-8). Measured on BroadleafCommerce: 3.9 s with the capture
96
+ against 4.0 s without, i.e. inside the noise; eureka 1.8 s against 0.8 s (its IR is
97
+ smaller, the extraction is not). The passenger cannot move the gate: the verdict, the
98
+ exit code and every other field are identical with and without it, and an exception
99
+ inside it is swallowed. `ASK_BASELINE_AUTOCAPTURE=0/1` overrides in both directions.
100
+ - ⚠One measured cost stated rather than hidden: a baseline is ~730 KB on a 3 300-file
101
+ monolith, because it stores the full endpoint surface and fan-in map so a later
102
+ `baseline diff` is faithful. A point per merge is a megabyte-scale history; a point
103
+ per release is not. `--dir` sends them outside the repository.
104
+ - ⚠Found by the battery, not by the field: the first capture writes an untracked file
105
+ **inside the repository**, so a plain `git status --porcelain` check would have
106
+ reported a dirty tree from then on and every later run would have skipped — a
107
+ history of exactly one. The dirtiness question excludes this tool's own footprint
108
+ (`.ask/`) and nothing else, because everything else is what the baseline measures —
109
+ and the second half of that came from eureka, where `verify --init` writes
110
+ `.ask/contracts.yml` and, counted as a modification, would stop the history from
111
+ ever starting.
112
+ - **`ask enrich --sarif <log>` — somebody else's detection, ranked by what this
113
+ repository does with it** (roadmap M10, first deliverable). This product does not
114
+ detect injection, CVEs or secrets and says so in every security payload (NC-001,
115
+ NC-002); the scanners that do have no bean graph, no profile model and no endpoint
116
+ id they share with anything, so their output is a list nobody can order. `enrich`
117
+ reads a SARIF 2.1.0 log from Semgrep, CodeQL or Trivy and runs the **same
118
+ composition** `ask risk` runs over each finding — same axes, same weights, same
119
+ `RiskComposer` — with one difference: `defect_severity` is the scanner's own
120
+ verdict (`security-severity` when the tool published one, `level` otherwise),
121
+ carried through with the scanner named as its authority. Nothing re-rates,
122
+ confirms or contradicts a finding. Results sharing (tool, rule, symbol) are one
123
+ defect with several witnesses; a result the join could not place — a file outside
124
+ the population this build read, a line with no declaration above it — is published
125
+ under `unresolved` with the reason, never dropped.
126
+ - **The CVE half of the same command: a dependency finding is joined through the
127
+ coordinate, not through a line.** A result located on `pom.xml` or
128
+ `build.gradle` is about a library, so the coordinate is read back out of the
129
+ manifest the scanner named and the reach is the worst of the types that import
130
+ it — *of forty vulnerable dependencies, which ones does an unauthenticated route
131
+ actually reach?* Importers are found from the IR's existing `imports` edges, by
132
+ the coordinate's group id or by its artifact id as a package segment, and each
133
+ row publishes which basis found them. A library nothing imports is `unresolved`
134
+ and never "unreachable": reflection, a service loader and use through another
135
+ dependency all leave no import edge. Both kinds rank in one list, because a CVE
136
+ in a reachable library and an injection finding in a handler are the same
137
+ question to whoever decides what to fix first.
138
+ - **`--profile <set>` on `ask risk` and `ask enrich` — profile context per finding**
139
+ (M10 exit criterion). The access axis stops answering for *the repository as
140
+ configured* and answers for *that deployment*: `posture` resolves the conditional
141
+ bean graph and the request chain under the named set, through a new published
142
+ seam (`posture.endpoint_access_under`, `posture.access_verdict`), so a composed
143
+ row and a `posture` run can never disagree about the same profile set. A decision
144
+ resolves an endpoint the repository-wide surface left at `coverage_unknown`, in
145
+ either direction — measured on a fixture, one defect scores 11.52/`open` under
146
+ `dev`, 8.06/`unknown` with no set named, and 5.76/`protected` under `prod`. When
147
+ both authorities decided, the worse of them wins, per endpoint.
148
+ - **`ask risk` gains a fifth factor: `query_construction`** (roadmap F.4-1). The
149
+ field asked the question this answers the structural half of — *"con 618 HQL
150
+ concatenados, ¿alguno concatena entrada de request?"* Following request input to
151
+ a query is dataflow, is declared out of scope in NC-001, and stays there. What
152
+ is publishable without it is the adjacency: this defect's own code assembles a
153
+ query string by concatenation, and the four factors beside it already say whether
154
+ that code is reachable, unauthenticated and writing. Read from the α
155
+ argument-shape atoms the IR already carries (`dynamic_argument_surface`) — no new
156
+ analysis, one pass, joined per defect. `not_observed` means the shape was absent
157
+ from the body facts; it is never a claim that a query is safely parameterised.
158
+ - **…and a sixth: `input_constraints`** — the other half of the same field question
159
+ (*"1 201 bodies sin validación"*). Joined by route against `validation`'s gap
160
+ list: `absent` means one of the endpoints reaching this defect accepts a request
161
+ body with no declared constraint, taking the worst of the reached routes for the
162
+ reason the auth axis does. `ask risk` now publishes the `non_coverage` block too,
163
+ because two axes describing the input path, composed with an open access verdict,
164
+ read as *injection* unless the payload states that no dataflow was followed.
165
+
166
+ ### Fixed
167
+
168
+ - **`validation` counted handlers that take no argument as body endpoints.** The
169
+ body surface was the verb alone (POST/PUT/PATCH) and the declared limitation said
170
+ the parameter list was not captured. It is now captured (`_handler_params`) and
171
+ read in the negative direction only: an empty parameter list proves no body can
172
+ bind. A handler whose parameters are all path or query values still counts, and
173
+ the limitation says so.
174
+
175
+ - **The α argument-shape surface was blind to every controller body.**
176
+ `dynamic_argument_surface` walked `kind="method"` and `kind="constructor"` symbol
177
+ nodes; a request handler is a `kind="endpoint"` node. The owner population is now
178
+ the body-fact layer's own (`ContextGraph.body_owners()`).
179
+
180
+ ### Changed
181
+
182
+ - `severity_effective` in `ask risk` can now be larger for a row whose code
183
+ concatenates a query. Every factor's neutral value is 1.0, so a new axis only
184
+ ever moves a row **up**: no band a reader has already acted on is demoted by
185
+ this release.
186
+
187
+ ## [4.2.0] — 2026-08-03
188
+
189
+ Minor, not a patch, by this project's own criterion: two published figures move
190
+ and a verdict changes, so a pipeline reading either can change colour.
191
+ `posture --resolve-environments` answers `NOT DECIDED IN THIS REPOSITORY` where
192
+ it answered `artefacts_disagree` on a repository whose build properties nothing
193
+ consumes (C1-22), and `ask risk` publishes defects where it published findings,
194
+ so `total_defects` and `by_band` move (C1-23) — 20 → 15 on BroadleafCommerce.
195
+ `risk` also drops `rule_id` for `rule_ids`: it is in the `experimental` tier,
196
+ whose published promise is exactly that its shape may change in a minor.
197
+
198
+ Field evaluation #9 (8/10, same 3 337-file monolith as #6–#8) opened nine rows
199
+ and this release closes seven of them. The two left open are open on purpose:
200
+ `C3-39` needs a Windows runner before it needs a fix, and `P-7` is a pricing
201
+ decision. Every complaint was re-measured against HEAD before a row was written
202
+ — five reproduced, one was half false, one was not reproducible here, and one
203
+ was a capability that already shipped.
204
+
205
+ ### Added
206
+
207
+ - **`ask posture --diff-ref <base>:<head>` and `--since <ref>` — one profile set,
208
+ two git refs** (roadmap M10.5 item 1). `--diff` holds the tree fixed and moves
209
+ the profile set; this holds the profile set fixed and moves the tree, which is
210
+ the question a pull request asks: *does this change what a client can reach
211
+ without authenticating?* `--since` compares a ref with the working tree,
212
+ uncommitted edits included. Both refs are read with `git archive`: nothing is
213
+ written to the repository, no worktree is created and the index is not touched.
214
+ `docs/posture.md` had declared this as the one requested extension with no
215
+ feature behind it.
216
+ - **`--fail-on opened|any|never` — the gate half.** Default `never`, so no
217
+ invocation that worked yesterday changes colour today; `opened` exits 1 when a
218
+ request a readable rule leaves reachable unauthenticated was not one before.
219
+ The payload is emitted before the exit code, because a red pipeline with no
220
+ statement of what opened is a gate nobody keeps. It requires a ref comparison —
221
+ gating a single run would gate on pre-existing debt, which is `spring-audit --ci`.
222
+ - **`endpoint_request_identity` registered as a fact** (ADR-0008 R11,
223
+ `sourcecode.canonical_ir:request_identity`). The comparison unit is the request
224
+ (`METHOD path`), not the endpoint id, which carries the controller FQN and the
225
+ handler symbol and therefore changes when a handler moves between classes
226
+ without the URL changing. `contract_diff` re-derived the same identity and now
227
+ binds to the authority. Path-variable patterns are deliberately **not**
228
+ normalised: `{id:.*}` and `{id:[^0-9].*}` are different URLs to a caller, and
229
+ one field repository moved 93 requests with exactly that edit in a single commit.
230
+
231
+ ### Added
232
+
233
+ - **`ask endpoints --compact` — the census instead of the rows** (C2-22, field
234
+ evaluation #9). Asked how exposed a repository was, the command answered with
235
+ 1.9 MB of JSON for 3 574 endpoints and no summary mode, and the evaluator
236
+ aggregated it by hand. Every answer now carries an `exposure` block — counts by
237
+ method, by security policy, by controller and by first path area — and
238
+ `--compact` returns it without the rows, declaring what it dropped. Two rules
239
+ it obeys against itself: the census is measured over the population the filters
240
+ chose and never over what `--limit` left rendered, and every ranked rollup
241
+ states its own total when it cuts. Measured on BroadleafCommerce: 95 KB → 11 KB,
242
+ every count unchanged. (The other half of the complaint is recorded as false:
243
+ `spring-audit` has shipped `--compact`, `--min-severity` and `--scope` for
244
+ releases.)
245
+
246
+ - **NC-007 — the endpoint population is declared** (CL-12, field evaluation #9).
247
+ `endpoints` projects Spring handler mappings; a servlet declared in `web.xml`
248
+ or registered as a `ServletRegistrationBean` is reachable over HTTP and is in
249
+ no part of that model. Six published non-coverage rows are exactly what let a
250
+ reader treat the list as the whole HTTP surface, and the evaluation lost a
251
+ monitoring console that way — at a path behind the credential the same run
252
+ reported as SEC-007. The row is published in the `endpoints` payload and inside
253
+ `posture.endpoints`, because the reader who counts open requests is reading
254
+ `posture`. Admission of a servlet surface is deliberately **not** in this
255
+ change: it is a second population and merging it into `endpoints.total` would
256
+ move a published count and every ratio keyed on it.
257
+
258
+ ### Fixed
259
+
260
+ - **A reach figure that did not name its scope** (C2-23, field evaluation #9).
261
+ `risk` reported `endpoints_reached: 1` for a symbol whose class `impact-chain`
262
+ said reached 8 — both correct, both documented, in two payloads, so reconciling
263
+ them cost the reader three unit notes. Each row now carries
264
+ `endpoints_reached_basis`: what the figure is a reach *of* (a defect sits at the
265
+ symbol that carries the remedy, so a method-level defect walks from the method)
266
+ and, where that is narrower than a class, the command that answers the wider
267
+ question. The relationship is asserted by measurement rather than stated in
268
+ prose.
269
+
270
+ - **The remedy registry now follows the status, not only the limitation** (C4-13,
271
+ field evaluation #9 — the sixth appearance of the C4 shape). The evaluation met
272
+ `verify`'s `contract_count: 0` → `unverified` → exit 2 under a read-only
273
+ constraint, concluded the command was unusable and asked for a `--dry-run` that
274
+ shipped in 3.7.0. The state named one next move and the reader could not take
275
+ it. `Remedy` gained `also` (the further options an answer needs — a remedy is an
276
+ invocation, not a flag), the new entry is `ask verify . --init --dry-run`, and
277
+ the `unverified` reason names both forms. The guard grew with it: every option
278
+ of an invocation must be accepted by the command it names, and the README check
279
+ matches a line carrying the command with all of its options, so a front page
280
+ that lists `--init` and omits `--dry-run` fails the build.
281
+
282
+ - **The hub-class guard contradicted the payload beside it** (C2-21, field
283
+ evaluation #9). It printed *"symbol has > 500 direct callers"* while the same
284
+ run published 215 of them on openmrs-core's `Context`: the guard trips on
285
+ caller **reference sites** (method-level keys included) and the payload
286
+ publishes caller **classes**, so the stated reason was checkably false while
287
+ the decision was right. `caller_reach.bfs_callers` now returns the population it
288
+ read, and the warning names it with its unit next to the class count it takes
289
+ from `caller_metrics.caller_classes` — *"792 caller reference sites … exceed the
290
+ cap of 500 … The 215 direct caller classes this run publishes stay exact"*.
291
+
292
+ - **`ask risk` ranked findings under the label `spring-audit` deduplicates**
293
+ (C1-23, field evaluation #9). One SEC-004 appeared three times for three call
294
+ sites in one class and `by_band` was an observation census under a defect
295
+ label — measured on BroadleafCommerce, 20 rows over 15 distinct `defect_id`
296
+ beside `spring-audit`'s own 15 defects / 20 findings. `build_risk` now iterates
297
+ `defect_identity.group_by_defect`, so one row is one thing to fix and both
298
+ commands report the same count (asserted against each other, not against a
299
+ literal). Nothing is dropped: `witness_count` and `witness_sites` carry where
300
+ each observation was seen, `total_findings` publishes the census under its own
301
+ name, and `rule_id` becomes **`rule_ids`** because one defect can be witnessed
302
+ by TX-001 and TX-006 at once and a singular field would have to pick one.
303
+ `severity` is the strongest across the witnesses, and
304
+ `factors.defect_severity.basis` says so.
305
+
306
+ - **A Maven build property was published as a runtime activation** (C1-22, field
307
+ evaluation #9 — the row it called the most expensive in its report). Two
308
+ `<properties>` entries setting `spring.profiles.active` made
309
+ `posture --resolve-environments` answer `artefacts_disagree` — *"different
310
+ deployments, pick one"* — on a repository where **nothing activates a profile at
311
+ run time**. The honest verdict, which the command already implements, is
312
+ `NOT DECIDED IN THIS REPOSITORY`: the default set applies and the permissive
313
+ profile wins, which is exactly where that audit's most severe finding lived. The
314
+ command turned a fail-open into a deployment ambiguity, in the scenario it is
315
+ sold for. A build property is now admitted as an activation only when a resource
316
+ in the repository consumes it (`@spring.profiles.active@`, or
317
+ `${spring.profiles.active}` where the build declares its resources filtered).
318
+ Unconsumed, the value is kept — it is still the profile set a build of it would
319
+ produce, so the worst case keeps ranking it — and carries the reason it decides
320
+ nothing, beside a `build_properties_not_consumed` count. The positive control is
321
+ half the battery: before this, the case where the property genuinely does decide
322
+ produced the identical verdict, which is how the defect stayed invisible. No
323
+ movement on the field repositories.
324
+
325
+ - **A rule that disappeared was reported as protection gained.** Found by the
326
+ negative control, not in the field: delete a security configuration and every
327
+ request it decided goes `permit_all` → undecided, which a two-bucket
328
+ opened/closed split published as *"2 requests no longer reachable
329
+ unauthenticated"*. Four buckets now: `opened` and `closed` (attributable to the
330
+ change), `no_longer_decided` (coverage lost) and `now_open_previously_undecided`
331
+ (our reading moved, not necessarily the system — it never turns a gate red on
332
+ its own). Requests undecided on either side are counted in
333
+ `access_not_decided_either_side`, the delta publishes `direction`, and
334
+ `gate.reading` states the floor (I-8).
335
+ - **`git_checkout` no longer offers a remedy half its callers do not have.** The
336
+ not-a-repository message told every caller to "pass two checkouts positionally";
337
+ `posture` takes none. The message states the fact and each command supplies its
338
+ own hint.
339
+
5
340
  ## [4.1.0] — 2026-08-03
6
341
 
7
342
  Minor, not a patch, and the criterion is this project's own: a new rule can trip
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: sourcecode
3
- Version: 4.1.0
3
+ Version: 4.3.0
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
@@ -156,8 +156,12 @@ ask posture /path/to/repo --resolve-environments
156
156
  # writing it, and populate .ask/contracts.yml from the measurement instead of by hand.
157
157
  ask verify /path/to/repo --init
158
158
 
159
- # What each defect actually costs once reach, access and write effect are in it:
160
- # severity × reachability × auth_verdict × write_effect, ordered, every factor traceable.
159
+ # Same derivation under a read-only constraint: prints what it would declare and
160
+ # writes nothing the form an audit of somebody else's repository can run.
161
+ ask verify /path/to/repo --init --dry-run
162
+
163
+ # What each defect actually costs once reach, access, write effect and the shape of
164
+ # the input path are in it — ordered, every factor traceable to the command that owns it.
161
165
  ask risk /path/to/repo
162
166
  ```
163
167
 
@@ -230,6 +234,9 @@ What a profile set **actually wires**: which conditional beans register, which d
230
234
  `ask posture` · `ask posture --diff dev:prod` · `ask posture --property k=v`
231
235
  → [posture.md](docs/posture.md)
232
236
 
237
+ **`--diff-ref` makes it a gate instead of a report.** `--diff` moves the profile set; `--diff-ref origin/main:HEAD` (or `--since origin/main`, which compares a ref with the working tree) moves the *tree* under one profile set and answers *did this branch open an endpoint*. `--fail-on opened` exits 1 when it did. Both refs are read with `git archive` — nothing is written to the repository. The comparison is keyed on the request (`METHOD path`), counts requests only one side serves, and never reports a rule that disappeared as protection gained.
238
+ `ask posture . --since origin/main --fail-on opened`
239
+
233
240
  **`--resolve-environments` carries it past the edge of the repository.** Every answer above
234
241
  is conditional on a profile set, and which set runs is decided by the deployment. This flag
235
242
  reads every artefact in the tree that can set `spring.profiles.active` — Maven/Gradle,
@@ -247,12 +254,16 @@ guesses is a confident security falsehood — the worst failure mode this tool h
247
254
  ### 5c · Composed Risk *(experimental)*
248
255
  Every command above answers one axis, and a reader composes them by hand. `ask risk` does the
249
256
  join over the endpoint and symbol ids these commands already share with each other:
250
- `severity_effective = defect_severity × reachability × auth_verdict × write_effect`. The
251
- product of the published factors **is** the published score — decomposable to the four
257
+ `severity_effective = defect_severity × reachability × auth_verdict × write_effect × query_construction × input_constraints`. The
258
+ product of the published factors **is** the published score — decomposable to the six
252
259
  figures and the authority behind each — and an axis this build cannot measure is `unknown`,
253
260
  weighted 1.0 and named in `blind_axes` rather than silently treated as safe. Measured on a
254
261
  field case: a defect both `spring-audit` and `impact-chain` called *medium* composes to
255
262
  **high (8.06)** once *reachable unauthenticated* and *writes to the database* are in it.
263
+ The last two factors describe the input path — a query assembled by concatenation, a route
264
+ accepting a body with no declared constraint. They are **adjacencies, not dataflow**: no
265
+ value is followed from a request to a sink, which is `NC-001` and is published in the
266
+ payload's own `non_coverage` block.
256
267
  `ask risk .` · `ask risk . --min-band high` · `ask risk . --limit 10`
257
268
  → [reference](docs/USER_GUIDE.md)
258
269
 
@@ -278,7 +289,7 @@ experimental: both are true, and they are two different facts.
278
289
  |---|---|---|
279
290
  | **core** | contract stable within a major — safe to gate CI on | `endpoints` · `spring-audit` · `migrate-check` · `impact` · `impact-chain` · `pr-impact` · `verify` |
280
291
  | **supported** | maintained; fields are added, never removed without a major | every command not named in another row |
281
- | **experimental** | shape may change in a minor — do not gate CI on it | `risk` · `posture` · `archetype` |
292
+ | **experimental** | shape may change in a minor — do not gate CI on it | `risk` · `enrich` · `data-exposure` · `migrate-recipe` · `posture` · `archetype` |
282
293
  | **parked** | kept working, no longer developed | `retrieve` |
283
294
 
284
295
  The same table is printed by `ask --help`, and both are generated from one authority
@@ -295,7 +306,10 @@ from it.
295
306
  | Command | Tier | Answers | Note |
296
307
  |---|---|---|---|
297
308
  | `posture` | experimental | which beans a profile set wires, and how effective endpoint access differs between two sets | the most differentiated capability here |
298
- | `risk` | experimental | what each defect actually costs, once reach, access and write effect are in it | `defect_severity × reachability × auth_verdict × write_effect`; every factor names its authority |
309
+ | `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 |
310
+ | `enrich` | experimental | another scanner's SARIF findings, ranked by what this repository does with them | `--sarif <log>`; the same composition as `risk`, with the scanner as the severity authority |
311
+ | `migrate-recipe` | experimental | the migration report as the OpenRewrite recipe that applies it | only recipes a finding named; the manual remainder published beside them; writes nothing without `--write`, and never a runnable command for an empty recipe list |
312
+ | `data-exposure` | experimental | which routes can carry the data you labelled, and who reaches them | labels declared in `sourcecode.config.json` — never inferred from a name; `signature` and `call_reach` evidence published apart, field-level flow out of scope (NC-008) |
299
313
  | `endpoints` | core | every REST endpoint, effective path, security policy, confidence | Spring MVC + JAX-RS (~65 % recall on JAX-RS sub-resource locators) |
300
314
  | `spring-audit` | core | transactional anomalies + security surface + validation gaps | `--ci`, `-f github-comment` |
301
315
  | `migrate-check` | core | Boot 2→3 readiness: located blockers, per-dimension score, effort | `--blast-radius` orders the re-test plan |
@@ -310,7 +324,7 @@ from it.
310
324
  | `review-pr` / `fix-bug` / `prepare-context` | supported | diff review, symptom triage, task-shaped context | |
311
325
  | `plan` / `compare` / `delta` / `contract-diff` | supported | what to review for a change; candidates by measured cost; outcome of a change; public-contract break | no verdicts, measured cost only |
312
326
  | `validation` | supported | request-body validation coverage and gaps | |
313
- | `baseline capture\|diff` · `trend` | supported | versioned architectural metrics over time; `ask trend <dir>` reads the series | trend reporting, not gating. Baselines land in `.ask/baselines` **inside the repository** — the history travels with the code, not with a vendor; an audit that must not write passes `--dir`. Automate it: [baseline-ci.yml](docs/baseline-ci.yml) |
327
+ | `baseline capture\|diff` · `trend` | supported | versioned architectural metrics over time; `ask trend .` reads the series (a repository path or a baselines directory), `ask baseline diff .` compares the tree against its newest point | trend reporting, not gating. Baselines land in `.ask/baselines` **inside the repository** — the history travels with the code, not with a vendor; an audit that must not write passes `--dir`. `capture --auto` is the unattended form (one baseline per commit, never rewrites one, never fails the build) — automate it: [baseline-ci.yml](docs/baseline-ci.yml) |
314
328
  | `retrieve` | parked | typed knowledge queries over the model | |
315
329
  | `archetype` | experimental | evidence-based architectural archetype | |
316
330
  | `rename-class` / `chunk-file` | supported | word-boundary Java rename; split a large file for an agent | |
@@ -354,6 +368,25 @@ Two more boundaries worth stating in the same voice:
354
368
  | **Applying a migration — nothing here edits source.** | This is the diagnosis layer: it measures what must change and what each change would reach. Rewriting code is an execution problem with an established executor, and duplicating it would mean maintaining a second, worse one. | OpenRewrite. `migrate-check` publishes the recipe each finding carries (`recipes[]`), which is the input that executor takes. |
355
369
  | **What the process environment sets at start-up — the profile set, properties and secrets a container is given.** | Nothing in a repository can observe the environment of a process that has not started. A value read from a file here is the default the repository ships, never a guarantee of what runs. | `ask posture --resolve-environments` reads every artefact in the repository that names the profile set, says when none of them decides it, and ranks the admissible sets by what each leaves open. |
356
370
 
371
+
372
+ And one about the endpoint surface itself:
373
+
374
+ | Not covered | Why | What answers it |
375
+ |---|---|---|
376
+ | **HTTP surface that is not a Spring handler mapping — a servlet declared in `web.xml` or registered as a `ServletRegistrationBean`, a container-level mapping, a static console mounted by a library.** | The endpoint population is projected from the Spring route model: one entry per handler mapping. A servlet is reachable over HTTP and is not in that model, so it is absent from `endpoints`, from the access verdicts derived from it, and from every ratio keyed on the total. Merging a second population into that count would move a published figure and every ratio with it, so the population is declared before it is widened. | Read the deployment descriptors for `<servlet-mapping>` entries and the Spring configuration for `ServletRegistrationBean` beans. Field evaluation #9 found a monitoring console mounted this way, behind a credential `ask spring-audit` did report (SEC-007) at a path nothing here listed. |
377
+
378
+ And one about labelled data:
379
+
380
+ | Not covered | Why | What answers it |
381
+ |---|---|---|
382
+ | **Whether a labelled member actually leaves the process on a given route — field-level dataflow through mappers, DTOs, serializers and projections.** | Exposure here is measured at TYPE granularity over the same call reach every other command walks: a route reaches the labelled type, or its signature names it. Whether the mapping in between keeps the labelled member is a dataflow question, and answering it by approximation would put a confident `no` on a route that does leak. So `call_reach` is published as a supremum and says so. | Read the mapping on the routes this answer ranks first — they are the ones worth a human — and label the DTO too if it carries the member, which makes the route `signature` instead of `call_reach`. |
383
+
384
+ And one about who calls a route:
385
+
386
+ | Not covered | Why | What answers it |
387
+ |---|---|---|
388
+ | **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. |
389
+
357
390
  **Positioning.** Until an executor ships, this is the **diagnosis layer**: it measures what
358
391
  must change, what each change reaches, and what a gate should block — and it removes none of
359
392
  it. Field evaluation scored it 7/10 as a report generator and 5.5/10 as a development tool,
@@ -118,8 +118,12 @@ ask posture /path/to/repo --resolve-environments
118
118
  # writing it, and populate .ask/contracts.yml from the measurement instead of by hand.
119
119
  ask verify /path/to/repo --init
120
120
 
121
- # What each defect actually costs once reach, access and write effect are in it:
122
- # severity × reachability × auth_verdict × write_effect, ordered, every factor traceable.
121
+ # Same derivation under a read-only constraint: prints what it would declare and
122
+ # writes nothing the form an audit of somebody else's repository can run.
123
+ ask verify /path/to/repo --init --dry-run
124
+
125
+ # What each defect actually costs once reach, access, write effect and the shape of
126
+ # the input path are in it — ordered, every factor traceable to the command that owns it.
123
127
  ask risk /path/to/repo
124
128
  ```
125
129
 
@@ -192,6 +196,9 @@ What a profile set **actually wires**: which conditional beans register, which d
192
196
  `ask posture` · `ask posture --diff dev:prod` · `ask posture --property k=v`
193
197
  → [posture.md](docs/posture.md)
194
198
 
199
+ **`--diff-ref` makes it a gate instead of a report.** `--diff` moves the profile set; `--diff-ref origin/main:HEAD` (or `--since origin/main`, which compares a ref with the working tree) moves the *tree* under one profile set and answers *did this branch open an endpoint*. `--fail-on opened` exits 1 when it did. Both refs are read with `git archive` — nothing is written to the repository. The comparison is keyed on the request (`METHOD path`), counts requests only one side serves, and never reports a rule that disappeared as protection gained.
200
+ `ask posture . --since origin/main --fail-on opened`
201
+
195
202
  **`--resolve-environments` carries it past the edge of the repository.** Every answer above
196
203
  is conditional on a profile set, and which set runs is decided by the deployment. This flag
197
204
  reads every artefact in the tree that can set `spring.profiles.active` — Maven/Gradle,
@@ -209,12 +216,16 @@ guesses is a confident security falsehood — the worst failure mode this tool h
209
216
  ### 5c · Composed Risk *(experimental)*
210
217
  Every command above answers one axis, and a reader composes them by hand. `ask risk` does the
211
218
  join over the endpoint and symbol ids these commands already share with each other:
212
- `severity_effective = defect_severity × reachability × auth_verdict × write_effect`. The
213
- product of the published factors **is** the published score — decomposable to the four
219
+ `severity_effective = defect_severity × reachability × auth_verdict × write_effect × query_construction × input_constraints`. The
220
+ product of the published factors **is** the published score — decomposable to the six
214
221
  figures and the authority behind each — and an axis this build cannot measure is `unknown`,
215
222
  weighted 1.0 and named in `blind_axes` rather than silently treated as safe. Measured on a
216
223
  field case: a defect both `spring-audit` and `impact-chain` called *medium* composes to
217
224
  **high (8.06)** once *reachable unauthenticated* and *writes to the database* are in it.
225
+ The last two factors describe the input path — a query assembled by concatenation, a route
226
+ accepting a body with no declared constraint. They are **adjacencies, not dataflow**: no
227
+ value is followed from a request to a sink, which is `NC-001` and is published in the
228
+ payload's own `non_coverage` block.
218
229
  `ask risk .` · `ask risk . --min-band high` · `ask risk . --limit 10`
219
230
  → [reference](docs/USER_GUIDE.md)
220
231
 
@@ -240,7 +251,7 @@ experimental: both are true, and they are two different facts.
240
251
  |---|---|---|
241
252
  | **core** | contract stable within a major — safe to gate CI on | `endpoints` · `spring-audit` · `migrate-check` · `impact` · `impact-chain` · `pr-impact` · `verify` |
242
253
  | **supported** | maintained; fields are added, never removed without a major | every command not named in another row |
243
- | **experimental** | shape may change in a minor — do not gate CI on it | `risk` · `posture` · `archetype` |
254
+ | **experimental** | shape may change in a minor — do not gate CI on it | `risk` · `enrich` · `data-exposure` · `migrate-recipe` · `posture` · `archetype` |
244
255
  | **parked** | kept working, no longer developed | `retrieve` |
245
256
 
246
257
  The same table is printed by `ask --help`, and both are generated from one authority
@@ -257,7 +268,10 @@ from it.
257
268
  | Command | Tier | Answers | Note |
258
269
  |---|---|---|---|
259
270
  | `posture` | experimental | which beans a profile set wires, and how effective endpoint access differs between two sets | the most differentiated capability here |
260
- | `risk` | experimental | what each defect actually costs, once reach, access and write effect are in it | `defect_severity × reachability × auth_verdict × write_effect`; every factor names its authority |
271
+ | `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 |
272
+ | `enrich` | experimental | another scanner's SARIF findings, ranked by what this repository does with them | `--sarif <log>`; the same composition as `risk`, with the scanner as the severity authority |
273
+ | `migrate-recipe` | experimental | the migration report as the OpenRewrite recipe that applies it | only recipes a finding named; the manual remainder published beside them; writes nothing without `--write`, and never a runnable command for an empty recipe list |
274
+ | `data-exposure` | experimental | which routes can carry the data you labelled, and who reaches them | labels declared in `sourcecode.config.json` — never inferred from a name; `signature` and `call_reach` evidence published apart, field-level flow out of scope (NC-008) |
261
275
  | `endpoints` | core | every REST endpoint, effective path, security policy, confidence | Spring MVC + JAX-RS (~65 % recall on JAX-RS sub-resource locators) |
262
276
  | `spring-audit` | core | transactional anomalies + security surface + validation gaps | `--ci`, `-f github-comment` |
263
277
  | `migrate-check` | core | Boot 2→3 readiness: located blockers, per-dimension score, effort | `--blast-radius` orders the re-test plan |
@@ -272,7 +286,7 @@ from it.
272
286
  | `review-pr` / `fix-bug` / `prepare-context` | supported | diff review, symptom triage, task-shaped context | |
273
287
  | `plan` / `compare` / `delta` / `contract-diff` | supported | what to review for a change; candidates by measured cost; outcome of a change; public-contract break | no verdicts, measured cost only |
274
288
  | `validation` | supported | request-body validation coverage and gaps | |
275
- | `baseline capture\|diff` · `trend` | supported | versioned architectural metrics over time; `ask trend <dir>` reads the series | trend reporting, not gating. Baselines land in `.ask/baselines` **inside the repository** — the history travels with the code, not with a vendor; an audit that must not write passes `--dir`. Automate it: [baseline-ci.yml](docs/baseline-ci.yml) |
289
+ | `baseline capture\|diff` · `trend` | supported | versioned architectural metrics over time; `ask trend .` reads the series (a repository path or a baselines directory), `ask baseline diff .` compares the tree against its newest point | trend reporting, not gating. Baselines land in `.ask/baselines` **inside the repository** — the history travels with the code, not with a vendor; an audit that must not write passes `--dir`. `capture --auto` is the unattended form (one baseline per commit, never rewrites one, never fails the build) — automate it: [baseline-ci.yml](docs/baseline-ci.yml) |
276
290
  | `retrieve` | parked | typed knowledge queries over the model | |
277
291
  | `archetype` | experimental | evidence-based architectural archetype | |
278
292
  | `rename-class` / `chunk-file` | supported | word-boundary Java rename; split a large file for an agent | |
@@ -316,6 +330,25 @@ Two more boundaries worth stating in the same voice:
316
330
  | **Applying a migration — nothing here edits source.** | This is the diagnosis layer: it measures what must change and what each change would reach. Rewriting code is an execution problem with an established executor, and duplicating it would mean maintaining a second, worse one. | OpenRewrite. `migrate-check` publishes the recipe each finding carries (`recipes[]`), which is the input that executor takes. |
317
331
  | **What the process environment sets at start-up — the profile set, properties and secrets a container is given.** | Nothing in a repository can observe the environment of a process that has not started. A value read from a file here is the default the repository ships, never a guarantee of what runs. | `ask posture --resolve-environments` reads every artefact in the repository that names the profile set, says when none of them decides it, and ranks the admissible sets by what each leaves open. |
318
332
 
333
+
334
+ And one about the endpoint surface itself:
335
+
336
+ | Not covered | Why | What answers it |
337
+ |---|---|---|
338
+ | **HTTP surface that is not a Spring handler mapping — a servlet declared in `web.xml` or registered as a `ServletRegistrationBean`, a container-level mapping, a static console mounted by a library.** | The endpoint population is projected from the Spring route model: one entry per handler mapping. A servlet is reachable over HTTP and is not in that model, so it is absent from `endpoints`, from the access verdicts derived from it, and from every ratio keyed on the total. Merging a second population into that count would move a published figure and every ratio with it, so the population is declared before it is widened. | Read the deployment descriptors for `<servlet-mapping>` entries and the Spring configuration for `ServletRegistrationBean` beans. Field evaluation #9 found a monitoring console mounted this way, behind a credential `ask spring-audit` did report (SEC-007) at a path nothing here listed. |
339
+
340
+ And one about labelled data:
341
+
342
+ | Not covered | Why | What answers it |
343
+ |---|---|---|
344
+ | **Whether a labelled member actually leaves the process on a given route — field-level dataflow through mappers, DTOs, serializers and projections.** | Exposure here is measured at TYPE granularity over the same call reach every other command walks: a route reaches the labelled type, or its signature names it. Whether the mapping in between keeps the labelled member is a dataflow question, and answering it by approximation would put a confident `no` on a route that does leak. So `call_reach` is published as a supremum and says so. | Read the mapping on the routes this answer ranks first — they are the ones worth a human — and label the DTO too if it carries the member, which makes the route `signature` instead of `call_reach`. |
345
+
346
+ And one about who calls a route:
347
+
348
+ | Not covered | Why | What answers it |
349
+ |---|---|---|
350
+ | **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. |
351
+
319
352
  **Positioning.** Until an executor ships, this is the **diagnosis layer**: it measures what
320
353
  must change, what each change reaches, and what a gate should block — and it removes none of
321
354
  it. Field evaluation scored it 7/10 as a report generator and 5.5/10 as a development tool,
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "sourcecode"
7
- version = "4.1.0"
7
+ version = "4.3.0"
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.1.0"
7
+ __version__ = "4.3.0"
@@ -312,6 +312,25 @@ def load_baseline(path: Path) -> dict:
312
312
  return data
313
313
 
314
314
 
315
+ def latest_baseline_path(directory: Path) -> "Path | None":
316
+ """The most recently captured baseline in `directory`, or None if there is none.
317
+
318
+ Ordered exactly as `load_baselines_dir` orders its series (capture time, commit
319
+ as the tie-break), so "the last point in the trend" and "the base a diff uses by
320
+ default" can never disagree about which artifact that is.
321
+ """
322
+ dated: list[tuple[str, str, Path]] = []
323
+ for p in sorted(Path(directory).glob("*.json")):
324
+ try:
325
+ b = load_baseline(p)
326
+ except (OSError, ValueError, json.JSONDecodeError):
327
+ continue
328
+ dated.append((str(b.get("captured_at", "")), str(b.get("commit", "")), p))
329
+ if not dated:
330
+ return None
331
+ return max(dated, key=lambda t: (t[0], t[1]))[2]
332
+
333
+
315
334
  def load_baselines_dir(directory: Path) -> list[dict]:
316
335
  """Load every architectural baseline in `directory`, sorted by capture time."""
317
336
  out: list[dict] = []