sourcecode 3.7.0__tar.gz → 4.0.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 (205) hide show
  1. {sourcecode-3.7.0 → sourcecode-4.0.0}/CHANGELOG.md +452 -0
  2. {sourcecode-3.7.0 → sourcecode-4.0.0}/PKG-INFO +34 -4
  3. {sourcecode-3.7.0 → sourcecode-4.0.0}/README.md +33 -3
  4. {sourcecode-3.7.0 → sourcecode-4.0.0}/pyproject.toml +1 -1
  5. {sourcecode-3.7.0 → sourcecode-4.0.0}/src/sourcecode/__init__.py +1 -1
  6. {sourcecode-3.7.0 → sourcecode-4.0.0}/src/sourcecode/archetype.py +43 -16
  7. {sourcecode-3.7.0 → sourcecode-4.0.0}/src/sourcecode/cache.py +48 -0
  8. {sourcecode-3.7.0 → sourcecode-4.0.0}/src/sourcecode/cache_model.py +17 -7
  9. {sourcecode-3.7.0 → sourcecode-4.0.0}/src/sourcecode/cli.py +562 -127
  10. {sourcecode-3.7.0 → sourcecode-4.0.0}/src/sourcecode/confidence_analyzer.py +7 -2
  11. sourcecode-4.0.0/src/sourcecode/contract_init.py +419 -0
  12. sourcecode-4.0.0/src/sourcecode/defect_identity.py +166 -0
  13. {sourcecode-3.7.0 → sourcecode-4.0.0}/src/sourcecode/degradation.py +52 -0
  14. {sourcecode-3.7.0 → sourcecode-4.0.0}/src/sourcecode/detectors/java.py +15 -31
  15. sourcecode-4.0.0/src/sourcecode/environment_resolution.py +361 -0
  16. sourcecode-4.0.0/src/sourcecode/filter_surface.py +404 -0
  17. sourcecode-4.0.0/src/sourcecode/git_checkout.py +149 -0
  18. sourcecode-4.0.0/src/sourcecode/identity_fallback.py +244 -0
  19. {sourcecode-3.7.0 → sourcecode-4.0.0}/src/sourcecode/migrate_check.py +79 -7
  20. sourcecode-4.0.0/src/sourcecode/non_coverage.py +198 -0
  21. {sourcecode-3.7.0 → sourcecode-4.0.0}/src/sourcecode/parse_cache.py +23 -0
  22. {sourcecode-3.7.0 → sourcecode-4.0.0}/src/sourcecode/posture.py +201 -6
  23. {sourcecode-3.7.0 → sourcecode-4.0.0}/src/sourcecode/pr_comment_renderer.py +13 -0
  24. {sourcecode-3.7.0 → sourcecode-4.0.0}/src/sourcecode/prepare_context.py +110 -3
  25. sourcecode-4.0.0/src/sourcecode/remedies.py +87 -0
  26. {sourcecode-3.7.0 → sourcecode-4.0.0}/src/sourcecode/repository_ir.py +43 -4
  27. {sourcecode-3.7.0 → sourcecode-4.0.0}/src/sourcecode/retrieval/result.py +24 -9
  28. {sourcecode-3.7.0 → sourcecode-4.0.0}/src/sourcecode/retrieval/steps.py +3 -0
  29. {sourcecode-3.7.0 → sourcecode-4.0.0}/src/sourcecode/retrieval/steps_endpoint.py +5 -5
  30. {sourcecode-3.7.0 → sourcecode-4.0.0}/src/sourcecode/retrieval/steps_graph.py +5 -5
  31. {sourcecode-3.7.0 → sourcecode-4.0.0}/src/sourcecode/retrieval/steps_impact.py +19 -7
  32. {sourcecode-3.7.0 → sourcecode-4.0.0}/src/sourcecode/retrieval/steps_intf.py +4 -4
  33. {sourcecode-3.7.0 → sourcecode-4.0.0}/src/sourcecode/retrieval/steps_struct.py +5 -5
  34. {sourcecode-3.7.0 → sourcecode-4.0.0}/src/sourcecode/retrieval/steps_txsec.py +5 -5
  35. sourcecode-4.0.0/src/sourcecode/risk.py +345 -0
  36. sourcecode-4.0.0/src/sourcecode/security_config_scan.py +262 -0
  37. {sourcecode-3.7.0 → sourcecode-4.0.0}/src/sourcecode/security_posture.py +216 -23
  38. {sourcecode-3.7.0 → sourcecode-4.0.0}/src/sourcecode/serializer.py +39 -5
  39. {sourcecode-3.7.0 → sourcecode-4.0.0}/src/sourcecode/spring_findings.py +67 -4
  40. {sourcecode-3.7.0 → sourcecode-4.0.0}/src/sourcecode/spring_profiles.py +199 -3
  41. {sourcecode-3.7.0 → sourcecode-4.0.0}/src/sourcecode/spring_properties.py +1 -1
  42. {sourcecode-3.7.0 → sourcecode-4.0.0}/src/sourcecode/spring_security_audit.py +88 -0
  43. {sourcecode-3.7.0 → sourcecode-4.0.0}/src/sourcecode/spring_tx_analyzer.py +52 -0
  44. {sourcecode-3.7.0 → sourcecode-4.0.0}/src/sourcecode/summarizer.py +7 -2
  45. sourcecode-4.0.0/src/sourcecode/test_gap_ranking.py +363 -0
  46. {sourcecode-3.7.0 → sourcecode-4.0.0}/src/sourcecode/token_estimate.py +36 -0
  47. {sourcecode-3.7.0 → sourcecode-4.0.0}/src/sourcecode/verify_repo.py +8 -0
  48. sourcecode-3.7.0/src/sourcecode/filter_surface.py +0 -173
  49. {sourcecode-3.7.0 → sourcecode-4.0.0}/.github/workflows/build-windows.yml +0 -0
  50. {sourcecode-3.7.0 → sourcecode-4.0.0}/.gitignore +0 -0
  51. {sourcecode-3.7.0 → sourcecode-4.0.0}/.ruff.toml +0 -0
  52. {sourcecode-3.7.0 → sourcecode-4.0.0}/CONTRIBUTING.md +0 -0
  53. {sourcecode-3.7.0 → sourcecode-4.0.0}/LICENSE +0 -0
  54. {sourcecode-3.7.0 → sourcecode-4.0.0}/SECURITY.md +0 -0
  55. {sourcecode-3.7.0 → sourcecode-4.0.0}/raw +0 -0
  56. {sourcecode-3.7.0 → sourcecode-4.0.0}/scripts/compare_integration_engines.py +0 -0
  57. {sourcecode-3.7.0 → sourcecode-4.0.0}/scripts/customer_smoke_test.sh +0 -0
  58. {sourcecode-3.7.0 → sourcecode-4.0.0}/scripts/generate_jdk_exports.py +0 -0
  59. {sourcecode-3.7.0 → sourcecode-4.0.0}/scripts/perf_harness.py +0 -0
  60. {sourcecode-3.7.0 → sourcecode-4.0.0}/src/sourcecode/adaptive_scanner.py +0 -0
  61. {sourcecode-3.7.0 → sourcecode-4.0.0}/src/sourcecode/architectural_baseline.py +0 -0
  62. {sourcecode-3.7.0 → sourcecode-4.0.0}/src/sourcecode/architectural_delta.py +0 -0
  63. {sourcecode-3.7.0 → sourcecode-4.0.0}/src/sourcecode/architecture_analyzer.py +0 -0
  64. {sourcecode-3.7.0 → sourcecode-4.0.0}/src/sourcecode/architecture_summary.py +0 -0
  65. {sourcecode-3.7.0 → sourcecode-4.0.0}/src/sourcecode/ast_extractor.py +0 -0
  66. {sourcecode-3.7.0 → sourcecode-4.0.0}/src/sourcecode/call_surface.py +0 -0
  67. {sourcecode-3.7.0 → sourcecode-4.0.0}/src/sourcecode/caller_metrics.py +0 -0
  68. {sourcecode-3.7.0 → sourcecode-4.0.0}/src/sourcecode/caller_reach.py +0 -0
  69. {sourcecode-3.7.0 → sourcecode-4.0.0}/src/sourcecode/canonical_ir.py +0 -0
  70. {sourcecode-3.7.0 → sourcecode-4.0.0}/src/sourcecode/chain_rules.py +0 -0
  71. {sourcecode-3.7.0 → sourcecode-4.0.0}/src/sourcecode/change_plan.py +0 -0
  72. {sourcecode-3.7.0 → sourcecode-4.0.0}/src/sourcecode/cir_graphs.py +0 -0
  73. {sourcecode-3.7.0 → sourcecode-4.0.0}/src/sourcecode/classifier.py +0 -0
  74. {sourcecode-3.7.0 → sourcecode-4.0.0}/src/sourcecode/code_notes_analyzer.py +0 -0
  75. {sourcecode-3.7.0 → sourcecode-4.0.0}/src/sourcecode/compare.py +0 -0
  76. {sourcecode-3.7.0 → sourcecode-4.0.0}/src/sourcecode/constraint_diff.py +0 -0
  77. {sourcecode-3.7.0 → sourcecode-4.0.0}/src/sourcecode/context_cache.py +0 -0
  78. {sourcecode-3.7.0 → sourcecode-4.0.0}/src/sourcecode/context_graph.py +0 -0
  79. {sourcecode-3.7.0 → sourcecode-4.0.0}/src/sourcecode/context_scorer.py +0 -0
  80. {sourcecode-3.7.0 → sourcecode-4.0.0}/src/sourcecode/context_summarizer.py +0 -0
  81. {sourcecode-3.7.0 → sourcecode-4.0.0}/src/sourcecode/contract_diff.py +0 -0
  82. {sourcecode-3.7.0 → sourcecode-4.0.0}/src/sourcecode/contract_model.py +0 -0
  83. {sourcecode-3.7.0 → sourcecode-4.0.0}/src/sourcecode/contract_pipeline.py +0 -0
  84. {sourcecode-3.7.0 → sourcecode-4.0.0}/src/sourcecode/coverage_parser.py +0 -0
  85. {sourcecode-3.7.0 → sourcecode-4.0.0}/src/sourcecode/dependency_analyzer.py +0 -0
  86. {sourcecode-3.7.0 → sourcecode-4.0.0}/src/sourcecode/deployment_prefix.py +0 -0
  87. {sourcecode-3.7.0 → sourcecode-4.0.0}/src/sourcecode/detectors/__init__.py +0 -0
  88. {sourcecode-3.7.0 → sourcecode-4.0.0}/src/sourcecode/detectors/base.py +0 -0
  89. {sourcecode-3.7.0 → sourcecode-4.0.0}/src/sourcecode/detectors/csproj_parser.py +0 -0
  90. {sourcecode-3.7.0 → sourcecode-4.0.0}/src/sourcecode/detectors/dart.py +0 -0
  91. {sourcecode-3.7.0 → sourcecode-4.0.0}/src/sourcecode/detectors/dotnet.py +0 -0
  92. {sourcecode-3.7.0 → sourcecode-4.0.0}/src/sourcecode/detectors/elixir.py +0 -0
  93. {sourcecode-3.7.0 → sourcecode-4.0.0}/src/sourcecode/detectors/go.py +0 -0
  94. {sourcecode-3.7.0 → sourcecode-4.0.0}/src/sourcecode/detectors/heuristic.py +0 -0
  95. {sourcecode-3.7.0 → sourcecode-4.0.0}/src/sourcecode/detectors/hybrid.py +0 -0
  96. {sourcecode-3.7.0 → sourcecode-4.0.0}/src/sourcecode/detectors/jvm_ext.py +0 -0
  97. {sourcecode-3.7.0 → sourcecode-4.0.0}/src/sourcecode/detectors/nodejs.py +0 -0
  98. {sourcecode-3.7.0 → sourcecode-4.0.0}/src/sourcecode/detectors/parsers.py +0 -0
  99. {sourcecode-3.7.0 → sourcecode-4.0.0}/src/sourcecode/detectors/php.py +0 -0
  100. {sourcecode-3.7.0 → sourcecode-4.0.0}/src/sourcecode/detectors/project.py +0 -0
  101. {sourcecode-3.7.0 → sourcecode-4.0.0}/src/sourcecode/detectors/python.py +0 -0
  102. {sourcecode-3.7.0 → sourcecode-4.0.0}/src/sourcecode/detectors/ruby.py +0 -0
  103. {sourcecode-3.7.0 → sourcecode-4.0.0}/src/sourcecode/detectors/rust.py +0 -0
  104. {sourcecode-3.7.0 → sourcecode-4.0.0}/src/sourcecode/detectors/systems.py +0 -0
  105. {sourcecode-3.7.0 → sourcecode-4.0.0}/src/sourcecode/detectors/terraform.py +0 -0
  106. {sourcecode-3.7.0 → sourcecode-4.0.0}/src/sourcecode/detectors/tooling.py +0 -0
  107. {sourcecode-3.7.0 → sourcecode-4.0.0}/src/sourcecode/doc_analyzer.py +0 -0
  108. {sourcecode-3.7.0 → sourcecode-4.0.0}/src/sourcecode/dynamic_argument_surface.py +0 -0
  109. {sourcecode-3.7.0 → sourcecode-4.0.0}/src/sourcecode/endpoint_literals.py +0 -0
  110. {sourcecode-3.7.0 → sourcecode-4.0.0}/src/sourcecode/endpoint_metrics.py +0 -0
  111. {sourcecode-3.7.0 → sourcecode-4.0.0}/src/sourcecode/entrypoint_classifier.py +0 -0
  112. {sourcecode-3.7.0 → sourcecode-4.0.0}/src/sourcecode/env_analyzer.py +0 -0
  113. {sourcecode-3.7.0 → sourcecode-4.0.0}/src/sourcecode/envelope.py +0 -0
  114. {sourcecode-3.7.0 → sourcecode-4.0.0}/src/sourcecode/error_schema.py +0 -0
  115. {sourcecode-3.7.0 → sourcecode-4.0.0}/src/sourcecode/evidence_provider.py +0 -0
  116. {sourcecode-3.7.0 → sourcecode-4.0.0}/src/sourcecode/explain.py +0 -0
  117. {sourcecode-3.7.0 → sourcecode-4.0.0}/src/sourcecode/facts/__init__.py +0 -0
  118. {sourcecode-3.7.0 → sourcecode-4.0.0}/src/sourcecode/facts/registry.json +0 -0
  119. {sourcecode-3.7.0 → sourcecode-4.0.0}/src/sourcecode/file_chunker.py +0 -0
  120. {sourcecode-3.7.0 → sourcecode-4.0.0}/src/sourcecode/file_classifier.py +0 -0
  121. {sourcecode-3.7.0 → sourcecode-4.0.0}/src/sourcecode/format_contract.py +0 -0
  122. {sourcecode-3.7.0 → sourcecode-4.0.0}/src/sourcecode/fqn_utils.py +0 -0
  123. {sourcecode-3.7.0 → sourcecode-4.0.0}/src/sourcecode/git_analyzer.py +0 -0
  124. {sourcecode-3.7.0 → sourcecode-4.0.0}/src/sourcecode/graph_analyzer.py +0 -0
  125. {sourcecode-3.7.0 → sourcecode-4.0.0}/src/sourcecode/graph_evidence.py +0 -0
  126. {sourcecode-3.7.0 → sourcecode-4.0.0}/src/sourcecode/hibernate_strat.py +0 -0
  127. {sourcecode-3.7.0 → sourcecode-4.0.0}/src/sourcecode/integration_coordinates.py +0 -0
  128. {sourcecode-3.7.0 → sourcecode-4.0.0}/src/sourcecode/jdk_exports.py +0 -0
  129. {sourcecode-3.7.0 → sourcecode-4.0.0}/src/sourcecode/license.py +0 -0
  130. {sourcecode-3.7.0 → sourcecode-4.0.0}/src/sourcecode/mcp/__init__.py +0 -0
  131. {sourcecode-3.7.0 → sourcecode-4.0.0}/src/sourcecode/mcp/onboarding/__init__.py +0 -0
  132. {sourcecode-3.7.0 → sourcecode-4.0.0}/src/sourcecode/mcp/onboarding/applier.py +0 -0
  133. {sourcecode-3.7.0 → sourcecode-4.0.0}/src/sourcecode/mcp/onboarding/backup.py +0 -0
  134. {sourcecode-3.7.0 → sourcecode-4.0.0}/src/sourcecode/mcp/onboarding/detector.py +0 -0
  135. {sourcecode-3.7.0 → sourcecode-4.0.0}/src/sourcecode/mcp/onboarding/planner.py +0 -0
  136. {sourcecode-3.7.0 → sourcecode-4.0.0}/src/sourcecode/mcp/orchestrator.py +0 -0
  137. {sourcecode-3.7.0 → sourcecode-4.0.0}/src/sourcecode/mcp/registry.py +0 -0
  138. {sourcecode-3.7.0 → sourcecode-4.0.0}/src/sourcecode/mcp/runner.py +0 -0
  139. {sourcecode-3.7.0 → sourcecode-4.0.0}/src/sourcecode/mcp/server.py +0 -0
  140. {sourcecode-3.7.0 → sourcecode-4.0.0}/src/sourcecode/mcp_nudge.py +0 -0
  141. {sourcecode-3.7.0 → sourcecode-4.0.0}/src/sourcecode/metrics_analyzer.py +0 -0
  142. {sourcecode-3.7.0 → sourcecode-4.0.0}/src/sourcecode/migration_blast.py +0 -0
  143. {sourcecode-3.7.0 → sourcecode-4.0.0}/src/sourcecode/openapi_surface.py +0 -0
  144. {sourcecode-3.7.0 → sourcecode-4.0.0}/src/sourcecode/output_budget.py +0 -0
  145. {sourcecode-3.7.0 → sourcecode-4.0.0}/src/sourcecode/path_admission.py +0 -0
  146. {sourcecode-3.7.0 → sourcecode-4.0.0}/src/sourcecode/path_filters.py +0 -0
  147. {sourcecode-3.7.0 → sourcecode-4.0.0}/src/sourcecode/perf.py +0 -0
  148. {sourcecode-3.7.0 → sourcecode-4.0.0}/src/sourcecode/pipe_contract.py +0 -0
  149. {sourcecode-3.7.0 → sourcecode-4.0.0}/src/sourcecode/pr_impact.py +0 -0
  150. {sourcecode-3.7.0 → sourcecode-4.0.0}/src/sourcecode/progress.py +0 -0
  151. {sourcecode-3.7.0 → sourcecode-4.0.0}/src/sourcecode/ranking_engine.py +0 -0
  152. {sourcecode-3.7.0 → sourcecode-4.0.0}/src/sourcecode/readiness_timeline.py +0 -0
  153. {sourcecode-3.7.0 → sourcecode-4.0.0}/src/sourcecode/reconciliation.py +0 -0
  154. {sourcecode-3.7.0 → sourcecode-4.0.0}/src/sourcecode/redactor.py +0 -0
  155. {sourcecode-3.7.0 → sourcecode-4.0.0}/src/sourcecode/reference_facts.py +0 -0
  156. {sourcecode-3.7.0 → sourcecode-4.0.0}/src/sourcecode/relevance_scorer.py +0 -0
  157. {sourcecode-3.7.0 → sourcecode-4.0.0}/src/sourcecode/rename_refactor.py +0 -0
  158. {sourcecode-3.7.0 → sourcecode-4.0.0}/src/sourcecode/repo_classifier.py +0 -0
  159. {sourcecode-3.7.0 → sourcecode-4.0.0}/src/sourcecode/retrieval/__init__.py +0 -0
  160. {sourcecode-3.7.0 → sourcecode-4.0.0}/src/sourcecode/retrieval/context.py +0 -0
  161. {sourcecode-3.7.0 → sourcecode-4.0.0}/src/sourcecode/retrieval/errors.py +0 -0
  162. {sourcecode-3.7.0 → sourcecode-4.0.0}/src/sourcecode/retrieval/executor.py +0 -0
  163. {sourcecode-3.7.0 → sourcecode-4.0.0}/src/sourcecode/retrieval/planner.py +0 -0
  164. {sourcecode-3.7.0 → sourcecode-4.0.0}/src/sourcecode/retrieval/query.py +0 -0
  165. {sourcecode-3.7.0 → sourcecode-4.0.0}/src/sourcecode/retrieval/request.py +0 -0
  166. {sourcecode-3.7.0 → sourcecode-4.0.0}/src/sourcecode/retrieval/resolution.py +0 -0
  167. {sourcecode-3.7.0 → sourcecode-4.0.0}/src/sourcecode/retrieval/retriever.py +0 -0
  168. {sourcecode-3.7.0 → sourcecode-4.0.0}/src/sourcecode/retrieval/runtime.py +0 -0
  169. {sourcecode-3.7.0 → sourcecode-4.0.0}/src/sourcecode/ris.py +0 -0
  170. {sourcecode-3.7.0 → sourcecode-4.0.0}/src/sourcecode/runtime_classifier.py +0 -0
  171. {sourcecode-3.7.0 → sourcecode-4.0.0}/src/sourcecode/scanner.py +0 -0
  172. {sourcecode-3.7.0 → sourcecode-4.0.0}/src/sourcecode/schema.py +0 -0
  173. {sourcecode-3.7.0 → sourcecode-4.0.0}/src/sourcecode/schemas/envelope-v1.schema.json +0 -0
  174. {sourcecode-3.7.0 → sourcecode-4.0.0}/src/sourcecode/security_config.py +0 -0
  175. {sourcecode-3.7.0 → sourcecode-4.0.0}/src/sourcecode/semantic_analyzer.py +0 -0
  176. {sourcecode-3.7.0 → sourcecode-4.0.0}/src/sourcecode/semantic_impact_engine.py +0 -0
  177. {sourcecode-3.7.0 → sourcecode-4.0.0}/src/sourcecode/semantic_integration_engine.py +0 -0
  178. {sourcecode-3.7.0 → sourcecode-4.0.0}/src/sourcecode/semantic_services.py +0 -0
  179. {sourcecode-3.7.0 → sourcecode-4.0.0}/src/sourcecode/spring_event_topology.py +0 -0
  180. {sourcecode-3.7.0 → sourcecode-4.0.0}/src/sourcecode/spring_impact.py +0 -0
  181. {sourcecode-3.7.0 → sourcecode-4.0.0}/src/sourcecode/spring_model.py +0 -0
  182. {sourcecode-3.7.0 → sourcecode-4.0.0}/src/sourcecode/spring_semantic.py +0 -0
  183. {sourcecode-3.7.0 → sourcecode-4.0.0}/src/sourcecode/target_admission.py +0 -0
  184. {sourcecode-3.7.0 → sourcecode-4.0.0}/src/sourcecode/telemetry/__init__.py +0 -0
  185. {sourcecode-3.7.0 → sourcecode-4.0.0}/src/sourcecode/telemetry/config.py +0 -0
  186. {sourcecode-3.7.0 → sourcecode-4.0.0}/src/sourcecode/telemetry/consent.py +0 -0
  187. {sourcecode-3.7.0 → sourcecode-4.0.0}/src/sourcecode/telemetry/events.py +0 -0
  188. {sourcecode-3.7.0 → sourcecode-4.0.0}/src/sourcecode/telemetry/filters.py +0 -0
  189. {sourcecode-3.7.0 → sourcecode-4.0.0}/src/sourcecode/telemetry/transport.py +0 -0
  190. {sourcecode-3.7.0 → sourcecode-4.0.0}/src/sourcecode/test_sources.py +0 -0
  191. {sourcecode-3.7.0 → sourcecode-4.0.0}/src/sourcecode/tree_utils.py +0 -0
  192. {sourcecode-3.7.0 → sourcecode-4.0.0}/src/sourcecode/type_usage_surface.py +0 -0
  193. {sourcecode-3.7.0 → sourcecode-4.0.0}/src/sourcecode/validation_inference.py +0 -0
  194. {sourcecode-3.7.0 → sourcecode-4.0.0}/src/sourcecode/validation_surface.py +0 -0
  195. {sourcecode-3.7.0 → sourcecode-4.0.0}/src/sourcecode/verify_edit.py +0 -0
  196. {sourcecode-3.7.0 → sourcecode-4.0.0}/src/sourcecode/verify_rules.py +0 -0
  197. {sourcecode-3.7.0 → sourcecode-4.0.0}/src/sourcecode/version_check.py +0 -0
  198. {sourcecode-3.7.0 → sourcecode-4.0.0}/src/sourcecode/workspace.py +0 -0
  199. {sourcecode-3.7.0 → sourcecode-4.0.0}/supabase/functions/README.md +0 -0
  200. {sourcecode-3.7.0 → sourcecode-4.0.0}/supabase/functions/get-license/index.ts +0 -0
  201. {sourcecode-3.7.0 → sourcecode-4.0.0}/supabase/functions/lemonsqueezy-webhook/index.ts +0 -0
  202. {sourcecode-3.7.0 → sourcecode-4.0.0}/supabase/functions/telemetry/index.ts +0 -0
  203. {sourcecode-3.7.0 → sourcecode-4.0.0}/supabase/sql/license_event_ordering.sql +0 -0
  204. {sourcecode-3.7.0 → sourcecode-4.0.0}/supabase/sql/licensing_schema.sql +0 -0
  205. {sourcecode-3.7.0 → sourcecode-4.0.0}/supabase/sql/telemetry_events.sql +0 -0
@@ -1,5 +1,457 @@
1
1
  # Changelog
2
2
 
3
+ ## [Unreleased]
4
+
5
+ ## [4.0.0] — 2026-08-02
6
+
7
+ Major because two published `gate_coverage` fields are removed, not because the
8
+ engine changed shape: `total_controller_handlers` / `gate_bearing` /
9
+ `not_carrying_gate` (C2-14, the announced end of their two-minor window) and
10
+ `possibly_filter_covered` (C1-20, which had no window — it counted the wrong thing).
11
+ `removed_fields` in the same block maps each retired name to its successor.
12
+
13
+ This release closes fourteen of the sixteen rows opened by the seventh field
14
+ evaluation, in the order that record argued for, and ships `ask risk` — the first
15
+ command that composes the other answers instead of adding one.
16
+
17
+ ### Added
18
+
19
+ - **`ask risk` — the composition layer** (M10 head; [EXPERIMENTAL]). The seventh
20
+ evaluation's thesis was *"ASK tiene todos los átomos y no forma moléculas"*: one
21
+ class was `medium` in `spring-audit`, `medium/5.0` in `impact-chain`,
22
+ `coverage_unknown → permit_all` in `posture`, and executed a stored procedure that
23
+ mutates the database. Composed, that is unauthenticated write access under the
24
+ release build; separately, it was two commands saying "medium" and a reader doing
25
+ the join by hand.
26
+ `severity_effective = defect_severity × reachability × auth_verdict × write_effect`,
27
+ emitted as an ordered list. No new analysis — every factor is read from the
28
+ authority that already publishes it, and every row carries its four factors with
29
+ their sources, so a reader can reject one and keep the rest. An axis that could
30
+ not be measured is `unknown`, multiplies by 1.0, and is named in `blind_axes`:
31
+ the composition may not invent what nobody measured. This is the item that
32
+ *"crea producto"* rather than correcting data, and the one nobody replicates by
33
+ combining three scanners, because none of them shares an endpoint id with the
34
+ others.
35
+
36
+ - **Three textbook security rules, because silence has to mean something** (CL-9).
37
+ The seventh evaluation got one security finding out of 3 342 files, then found
38
+ three more by hand in three files ASK had pointed it at. `SEC-004` (passwords
39
+ stored under a fast unsalted digest), `SEC-005` (CSRF disabled under
40
+ session-bearing authentication) and `SEC-006` (a cookie created without the Secure
41
+ attribute) ship in the `spring-audit` security surface, from one scan
42
+ (`sourcecode/security_config_scan.py`) with `file:line`. Each requires a
43
+ security-configuration context, so SHA-1 over a response body stays an ETag and a
44
+ stateless API that disables CSRF is not reported — a rule that cannot tell those
45
+ apart is one teams switch off, after which it protects nothing. These are table
46
+ stakes rather than differentiation: closing them avoids losing the sale.
47
+
48
+ - **A third verdict for a gate that authorises against an identity nobody proved**
49
+ (C1-21). 939 endpoints in the field were reported `protected_custom` for carrying a
50
+ real gate — whose aspect resolves the caller through a method that returns a
51
+ database user when the authentication is null. The check runs; what it decides on,
52
+ for a request carrying no credential, is an identity the application invented, and
53
+ the vocabulary had no way to say so.
54
+ - `sourcecode/identity_fallback.py` (extractor) reports a method that reads the
55
+ platform's identity and, in a branch guarded by that identity being absent,
56
+ returns one anyway. Throwing, denying and returning null are correct handling and
57
+ are never reported; nothing branches on a method or class name (VAI).
58
+ - `security_posture` follows the enforcement path — types carrying published AOP
59
+ advice vocabulary or implementing a request-chain SPI — over `calls` edges, and
60
+ emits `protected_custom_degraded` (confidence `RequiresManualReview`) with an
61
+ `identity_resolution` block naming the method, the absence test and what it
62
+ returns. A fallback the enforcement path does not reach is not charged to the
63
+ gate.
64
+
65
+ - **The remedy travels with the limitation** (C4-8, C3-37). The evaluation's requests
66
+ #1 and #5 — written by hand with invented syntax — are `posture
67
+ --resolve-environments` and `verify --init`, both shipped in the build it audited.
68
+ Four earlier rows say the same thing: discoverability cannot live in a document,
69
+ because a reader looking at an output does not go and read `--help`. One registry
70
+ (`sourcecode/remedies.py`), keyed by the question rather than by the flag, is read
71
+ by `posture.activation`, `posture --diff`, the `security_posture` limitation that is
72
+ conditional on the profile set, and `verify`'s exit-2 reason. A test refuses any
73
+ remedy naming a command or option the CLI does not accept, so a renamed flag breaks
74
+ the build instead of sending a reader to an invocation that no longer exists.
75
+
76
+ - **A filter that matches a path is not a filter that checks the caller** (C1-20).
77
+ `gate_coverage` published `possibly_filter_covered: 2635` over patterns `/*`,
78
+ `/api/*` and `/api/v1/*` — and those three filters were CORS, headers and logging,
79
+ while the only filter that authenticates covered two prefixes. The wording was
80
+ technically honest and the number was still *"falso consuelo"*: the corrected split
81
+ on that repository is 12 covered against 2 623 in the gap. Both halves of the join
82
+ were already in the same process, so the fix is an intersection **per filter**
83
+ rather than per pattern-set:
84
+ - `sourcecode/filter_surface.py` now records each declared filter (`@WebFilter`, and
85
+ `web.xml` mappings correlated with their `<filter-class>`) with a verdict —
86
+ `authenticates`, `does_not_authenticate`, `unknown` — decided structurally, never
87
+ by name (VAI): the filter establishes an identity, or it reads a credential *and*
88
+ refuses over it. A body that is not in this repository stays `unknown`, because
89
+ absence of evidence published as evidence of absence is the same defect mirrored.
90
+ - `gate_coverage` replaces the single count with four that partition the escape set:
91
+ `filter_covered_authenticating`, `filter_gap_non_authenticating`,
92
+ `filter_authentication_unknown`, `no_matching_filter_pattern`, plus a `filters`
93
+ list naming each filter, its patterns and the evidence behind its verdict.
94
+
95
+ - **Seven presentation rows, none of them an analysis error, two of which led a
96
+ reader to the inverse conclusion** (C2-15…C2-20, C1-19).
97
+ - `validation` printed *"0 body endpoints, 1179 gaps"* over a payload carrying
98
+ `body_endpoints_in_code: 1201` — the declared-constraint count under the
99
+ code-surface name. Both axes are named in their own units (C2-15).
100
+ - TX-006's witnesses all carried the callee's line, because that is where the
101
+ remedy goes, so several rows shared one number and read as duplicates. Each
102
+ finding now carries its `call_site` from the IR's span index, and the defect row
103
+ publishes the distinct sites with their count (C2-16).
104
+ - `limitations` merged across scopes repeated an entry verbatim; deduplicated once
105
+ in `finalize`, in first-seen order (C2-17).
106
+ - `spring_profiles.conditional_beans[].source_file` used the platform's native path
107
+ separator while the rest of the document used `/`; posix everywhere, including the
108
+ two other extractors that did the same (C2-18).
109
+ - `estimated_effort_range_days` published `{low: 60.7, high: 60.7}` — not a range,
110
+ at a precision the model does not have. The band declares `point_estimate` and
111
+ `precision_days`, and rounds to it (C2-19).
112
+ - `posture` cut four endpoint lists and its evidence map at 200 and declared
113
+ nothing, in the command whose declared caps the same evaluation calls a feature.
114
+ Each cut publishes total/shown/omitted and the registered cap effect; a list that
115
+ was not cut declares nothing (C2-20).
116
+ - Three commands published a file count for one repository — 3 337, 3 336, 3 342 —
117
+ and none said what it counted. Measured rather than equalised: all code-extension
118
+ files in any language, the non-test denominator of a test ratio, and the `.java`
119
+ files handed to the migration rules. Each names its population (C1-19).
120
+
121
+ - **`cache status` counts every store a warm fills** (C3-36). It printed `CAS blobs:
122
+ 0`, `Total size: 0.1 MB` immediately after an 89-second warm of 3 342 files: true of
123
+ the per-repository core store, and the warm's output mostly lands in the shared
124
+ Canonical IR and the content-addressed parse cache, which the command never counted.
125
+ The status now breaks down by store, says what each holds, and labels the parse
126
+ cache shared across repositories so its size is not read as this repository's.
127
+
128
+ ### Removed
129
+
130
+ - **BREAKING — `gate_coverage` no longer emits the three deprecated aliases** (C2-14).
131
+ `total_controller_handlers` counted *endpoints* under a name that says handlers,
132
+ `gate_bearing` counted *handler methods* while sitting beside an endpoint count, and
133
+ `not_carrying_gate` duplicated `endpoints_not_carrying_gate`. They were kept for a
134
+ two-minor window after C1-5 named the units; the seventh field evaluation read the
135
+ aliases anyway and quoted `total_controller_handlers: 3574` as handlers next to
136
+ `handler_methods_total: 913`. An alias that still ships is a live claim, and two of
137
+ these claimed the wrong unit. Read `endpoints_total`,
138
+ `handler_methods_carrying_gate` and `endpoints_not_carrying_gate`; the block now
139
+ carries `removed_fields` mapping each retired name to its successor, so a consumer
140
+ meets the answer rather than a `KeyError`. `possibly_filter_covered` is retired in
141
+ the same block and for the same reason (C1-20): it counted "a filter runs here" and
142
+ was read as "a filter checks here".
143
+
144
+ ## [3.8.0] — 2026-08-02
145
+
146
+ ### Added
147
+
148
+ - **The security surface publishes what it does not answer** (CL-2, CL-7, and the framing half
149
+ of CL-5). A report that lists what it found and says nothing about what it never looks at
150
+ invites silence to be read as absence — and the audit that raised this found a credential
151
+ versioned in three deployment descriptors *by hand*, because nothing here reads outside Java
152
+ and Spring configuration.
153
+ - One authority, `sourcecode/non_coverage.py`, read by three surfaces: the `non_coverage`
154
+ block in the `spring-audit` payload, the command's own `--help`, and the README section —
155
+ all rendered from the same table, because a curated list beside a generated one is how
156
+ `endpoints` went missing from every help list.
157
+ - Four rows for the security surface: no dataflow or taint (NC-001), no secrets outside Java
158
+ and Spring configuration (NC-002), filter-chain order not reconstructed (NC-003), no CVE
159
+ matching (NC-004). Each states why it is out of scope rather than unimplemented, and what
160
+ does answer it. Two more state the migration boundary (NC-005, OpenRewrite takes the
161
+ recipes this publishes) and the environment boundary (NC-006, answered as far as a
162
+ repository can by `posture --resolve-environments`).
163
+ - The evaluator's argument for publishing it is commercial, not ethical: *"un producto que
164
+ publica sus límites no se compara por amplitud; se compara por profundidad, que es donde
165
+ gana."*
166
+
167
+ ### Changed
168
+
169
+ - **Two claims corrected with measured figures.** `--compact` is documented as the smallest
170
+ answer, **not the cheapest run** — 13.3 s cold on BroadleafCommerce against `spring-audit`
171
+ 3.6 s and `posture` 1.9 s, 0.3 s warm — with the reason to warm before a session stated where
172
+ the claim is made (CL-3). And the product is positioned as the **diagnosis layer** until an
173
+ executor ships, in the field's own numbers (7/10 as a report generator, 5.5/10 as a
174
+ development tool) rather than argued with (CL-5).
175
+
176
+ - **`ask trend` is a top-level command, and capture is automatable** (P-4). The *series* is the
177
+ asset — a repository that captured a baseline at each release has a history nobody can
178
+ reconstruct afterwards, and one that did not never will — so reading it is no longer two words
179
+ deep, and [`docs/baseline-ci.yml`](docs/baseline-ci.yml) captures one per tag and publishes the
180
+ trend as a build artifact. `ask baseline trend` is the same command.
181
+ - The read-only half was a **documentation** gap and is closed where the auditor meets it:
182
+ `--dir` already existed, and the default now says *why* it is inside the repository (the
183
+ history travels with the code, not with a vendor) and that an audit which must leave the tree
184
+ untouched writes elsewhere. README and the user guide say the same.
185
+ - ⚠Adding the command surfaced the **C4-1 shape a sixth time**: `ask trend` was registered,
186
+ working and documented, and the CLI answered *"'trend' does not exist"* — because the
187
+ dispatcher matched against a **hand-written set of subcommand names**. It is derived from the
188
+ registry now, and the battery asserts every registered command is dispatchable.
189
+
190
+ - **`ask posture --resolve-environments` — which profile set actually runs, and the worst one
191
+ that could** (CL-8 / M9.5). `posture --diff` was called the strongest thing this product does
192
+ and it stopped at the repository boundary: which profile set runs is decided by the
193
+ deployment, so the answer was conditional and a field evaluator closed the last hops by hand
194
+ with `grep` (build profile → the property the build filters → a placeholder present in no
195
+ config file → no `context-param` in any descriptor → therefore nothing decides it).
196
+ - Those hops are now mechanical. Every artefact that can set `spring.profiles.active` is read
197
+ — config files, Maven/Gradle properties, `web.xml` context parameters, `Dockerfile` `ENV`
198
+ and `-D` arguments, Compose and Kubernetes manifests, launch scripts — each publishing what
199
+ it says with `file:line`. The verdict is `decided_in_repository`, `artefacts_disagree` (two
200
+ deployments, never a contradiction to resolve by picking one), or **`NOT DECIDED IN THIS
201
+ REPOSITORY`**.
202
+ - Every admissible profile set is then resolved over one parse and ranked by what it leaves
203
+ open, so the payload names the worst case and, where the repository does decide, how far the
204
+ shipped set is from it: *"one environment variable away from dev"*.
205
+ - **`open_by_rule` and `access_not_decided` are counted separately.** A readable rule that
206
+ permits a request unauthenticated is not the same fact as no readable rule matching it, and
207
+ folding them together would publish the confident security falsehood this command exists to
208
+ prevent. The reading says which is which.
209
+ - A value found in the repository is published as a default, never a guarantee:
210
+ `SPRING_PROFILES_ACTIVE` in the process environment outranks every artefact, and this
211
+ analysis cannot see the process environment.
212
+
213
+ - **`ask verify --init` derives the contracts a repository already satisfies** (C3-30). The gate
214
+ had no way to acquire what it gates on: nobody hand-writes contracts for a 3 300-file
215
+ monolith, so the honest gate (zero contracts is `unverified`, closed as C3-15) stayed empty —
216
+ and the gate is the recurring half of the value story, where an audit is bought once.
217
+ - Three shapes, each written with the measurement behind it: a path prefix whose endpoints all
218
+ carry the same policy today (`require_endpoint_security`), an audit pattern that fires
219
+ nowhere (`forbid_finding`), and an injection edge between two annotated populations that
220
+ does not occur, both populations large enough that the absence is a pattern rather than an
221
+ accident (`forbidden_edge`).
222
+ - **Every rule is executed before it is written.** The derived set runs through the same engine
223
+ `verify` runs, and anything that fails on the tree it came from is dropped and reported —
224
+ `verify --init` followed by `verify` passes by construction, asserted as a round trip in the
225
+ battery, together with the proof that the populated gate goes red when the invariant breaks.
226
+ - Violations that exist today are deliberately not proposed: that is debt for
227
+ `--capture-baseline`, a different claim from an invariant, and the payload says so per
228
+ rejected candidate.
229
+ - `--dry-run` prints without writing; an existing contracts file is never replaced without
230
+ `--force`.
231
+
232
+ - **`delta` and `contract-diff` take git refs** (C3-33). Both compared two *checkouts* while
233
+ `review-pr` in the same CLI already took `--since`, so comparing two commits meant
234
+ orchestrating worktrees first. In the evaluation that recorded this, that cost coverage rather
235
+ than convenience: the evaluator ran the full catalogue against a client monolith under a
236
+ promise to leave the environment byte-identical and **omitted both commands** rather than
237
+ create worktrees in someone else's repository.
238
+ - `ask delta --base-ref origin/main --head-ref HEAD [--repo <path>]`, same for
239
+ `contract-diff`. Two checkouts positionally still work, and the payload publishes a
240
+ `comparison` block saying which basis it used — with both refs and their resolved commits.
241
+ - **Reading a ref writes nothing to the repository.** `git archive` streams the tree into a
242
+ temporary directory that is removed on the way out: no `git worktree add` (which registers
243
+ administrative state under `.git/worktrees` and leaves it behind if the process dies), no
244
+ checkout, no stash, no index read. The battery asserts `git status` and `git worktree list`
245
+ are identical before and after.
246
+ - A ref this repository does not have is refused by name (`git_ref_not_found`, exit 1) and
247
+ never substituted with something nearby.
248
+
249
+ ### Fixed
250
+
251
+ - **`retrieve` stopped publishing scores nothing computed** (C3-19, **`entities[].score` and
252
+ `explanation.score` are nullable**). `retrieve blast-radius` returned eighty dependents each
253
+ carrying `"score": 0.0`, beside an explanation whose own score was 92.43 — and the step that
254
+ orders those entities says in its own docstring that no score is computed. The same default put
255
+ a zero on every entity of every intent, and an `explanation` block with `winner: null,
256
+ score: 0.0` on the intents that return what they found rather than choose a winner: the shape
257
+ the field called *a ranking block that never ran*.
258
+ - Both fields are `None` when nothing wrote them. The order is real and structural, so the
259
+ payload states it: `entities_ranked_by` — *"reach from the target (direct before indirect),
260
+ then identity — a structural order, not a per-entity score"*.
261
+ - `retrieve` remains `[PARKED]`; this is the honesty fix the tier does not excuse.
262
+
263
+ - **`archetype` no longer scores an unmeasured HTTP surface as an absent one** (C3-7). The
264
+ command declares `endpoints` as a missing signal on runs with no root to read — and then
265
+ scored as if the answer were **0**, which is a measured statement. Inside the scorer that zero
266
+ did two things at once: it refuted `api-first` and it fired `worker`'s `event_no_http`
267
+ evidence, so a repository nobody measured came back classified as an event worker with the
268
+ reason published as if it were a finding (I-3/R9, inside a score).
269
+ - The count is nullable now. Unmeasured contributes nothing and says so in its own evidence
270
+ row; `event_no_http` requires the absence of HTTP as a *measured* fact. A measured zero
271
+ behaves exactly as before, which the battery asserts alongside the unmeasured case.
272
+ - Measured while closing it, and recorded rather than acted on: `archetype` on
273
+ BroadleafCommerce takes **9.3 s** (the field reported 22 s) and returns two high-confidence
274
+ dimensions of four, so the tier stays `[EXPERIMENTAL]` — the cost complaint does not
275
+ reproduce at that magnitude, and a command with two high-confidence answers is not a
276
+ candidate for `parked`.
277
+
278
+ - **The summary stopped costing more than the analyses it summarises** (C3-6, C3-21). Measured on
279
+ BroadleafCommerce with nothing warm: `--compact` **19.3 s → 13.3 s**, and with the parse cache
280
+ warm **14.0 s → 7.9 s**; `endpoints` **3.3 s → 1.4 s**. Two duplications inside one process, both
281
+ removed:
282
+ - The **core view was built twice on every cold run** — once for the L1 cache write and once for
283
+ the RIS update — and building it rebuilds the CIR. One repository state has one core view; both
284
+ writers now read it.
285
+ - The **endpoint extractor parsed every file itself** while `build_repo_ir` read the
286
+ content-addressed parse cache for the same bytes. A run that does both paid for the same parse
287
+ twice, and a warm cache measurably bought `endpoints` nothing — a fact this product published
288
+ in its own cache model. Same key, same extractor, same capture signature: the entry either side
289
+ writes is the entry the other reads. The cache-model rows for `endpoints` and the root command
290
+ are re-measured accordingly.
291
+ - The inversion is **narrowed, not gone**: `--compact` is still slower than `spring-audit`
292
+ (3.6 s) or `posture` (1.9 s), because it builds the summary *and* the core view where those
293
+ build one analysis each.
294
+ - **C3-21 does not reproduce on 3.7.0**: the cache hit that cost 2 647 ms now costs 1.6 s for
295
+ `explain` against a 1.6 s cold run, and the snapshot hit for `--compact` is 0.29 s. Recorded as
296
+ measured, not assumed closed.
297
+ - The battery pins the two mechanisms rather than wall-clock figures: a second extraction must
298
+ re-parse nothing, the cached and uncached answers must be identical, and one root run must
299
+ build the core view once.
300
+
301
+ - **A comment can no longer take a whole file out of the graph** (E-1). The declaration joiner
302
+ decided whether a line *starts* a type declaration by scanning raw text, so a comment carrying
303
+ `class` or `interface` followed by an identifier looked like a declaration head with its brace
304
+ on a later line — `/** Implements the interface only for the legacy path. */`, or a trailing
305
+ `// starter class is not an utility class` on an annotation. The join then swallowed the
306
+ annotation and the real declaration into one entry beginning with `@`, which the parser reads
307
+ as a pending annotation and never examines: the file contributed **zero symbols** — no type,
308
+ no endpoint, no transaction boundary — and a file that contributes nothing looks exactly like
309
+ a file with nothing in it, which is why no field report could ever name this.
310
+ - Comments are stripped before the keyword scan (block state carried across lines, string
311
+ literal aware), and the brace that ends a join must also be code, so a commented `{` no
312
+ longer cuts a real multi-line declaration in half.
313
+ - Measured A/B over six repositories: **open-banking-gateway recovers 6 types, three of them
314
+ Spring Boot application classes**; petclinic, eureka, openmrs-core, BroadleafCommerce and
315
+ keycloak are unchanged, and **no repository loses a symbol**.
316
+
317
+ - **`generate-tests` ranks by what depends on the file, not by how the file is named**
318
+ (C3-13, **`untested_sources[]` entries change shape**). Two rules, both name matching, both
319
+ measured on openmrs-core: admission kept only files whose name ends in one of five suffixes
320
+ (`Service.java`, `Controller.java`, `Repository.java`, `Mapper.java`, `RestController.java`),
321
+ reducing **866 production files to 11 candidates**; and coverage was a filename pair, so
322
+ `PersonServiceImpl` was a gap for want of a `PersonServiceImplTest`. What remained was ordered
323
+ by how often the substring `"public "` appears in the first 16 KB — while `blast_radius`,
324
+ transaction boundaries and endpoint exposure were already computed elsewhere in the same
325
+ product and never consulted.
326
+ - **Coverage is now a reach fact**: a type is covered when a test source reaches it — named
327
+ directly, or reached along the call, instantiation and injection edges a blast radius
328
+ already walks, through the interface the container wires it behind, or as a supertype of
329
+ something a test exercises. One forward traversal from every test type: 0.01 s on
330
+ BroadleafCommerce. Reaching is not asserting, so the coverage figure is a floor and the gap
331
+ list is a ceiling, and `notes` says so.
332
+ - **Admission is the population**, not a naming convention: openmrs-core 866 production files
333
+ → **161 untested**, BroadleafCommerce 2 765 → **1 494**, published as `population` beside
334
+ the list.
335
+ - **Order is the measured axes** — endpoints reached, transaction boundaries declared, classes
336
+ that depend on it — reusing `caller_reach`, `spring_impact._collect_endpoints` and
337
+ `spring_semantic.boundaries_declared_within` rather than deriving them again. The weights
338
+ that fold the three into `score` are published with `rank_weights_basis: "assumption, not a
339
+ measurement"`, and the order is reproducible from the axes without accepting them.
340
+ - `untested_sources[]`/`test_gaps[]` rows drop `rank_score`, `public_method_count` and
341
+ `has_framework_annotations` — measurements of the replaced basis — and carry
342
+ `endpoints_reached`, `transaction_boundaries` and `caller_classes` instead. `path`, `score`
343
+ and `reason` are unchanged. The new `test_gap_ranking` block publishes the basis, the
344
+ population and the caps.
345
+ - Cost, measured cold: BroadleafCommerce 11.1 s → **15.3 s**, openmrs-core 5.1 s → 10.2 s. A
346
+ run whose IR cannot be built keeps the filename algorithm and publishes the
347
+ `test_reach_graph` signal with what taking it costs the answer (I-8).
348
+
349
+ - **`generate-tests` publishes its time budget, and a cache no longer defeats it** (C3-1). The
350
+ 30 s cap was reachable only through `SOURCECODE_TESTS_TIMEOUT_MS`, a name in no help text —
351
+ the one knob that turns an empty answer into an answer was invisible to whoever was holding
352
+ the empty answer. `--timeout <seconds>` is now a documented flag (the variable still works;
353
+ the flag wins), and an exhausted budget publishes `analysis_budget` carrying the new
354
+ `time_budget` cap: *"an empty list here means the walk stopped, NOT that the repository has
355
+ nothing"*, with the budget, its source, and how to raise it.
356
+ - Closing it surfaced a sharper defect, measured: **the cache key ignored the budget**, so a
357
+ run that exhausted 2 s answered the re-run at 30 s from cache — the remedy the payload
358
+ names did nothing at all. The budget is now part of the cache identity, and an exhausted
359
+ result is never stored: an unfinished walk is worth re-running.
360
+ - Measured while closing it: the full scan on openmrs-core (3 300 files, cold cache) takes
361
+ **3.35 s** and returns 13 untested sources, so the field's empty payload does not reproduce
362
+ and the default budget is not the constraint it was taken for. The ranking half of C3-13
363
+ stays open — the command still matches file names while `blast_radius`, transactional
364
+ writes and endpoint exposure are already computed.
365
+
366
+ - **`review-pr` no longer counts documentation as a runtime change** (C3-11b). The field
367
+ reported a diff of 227 `.md` files as `runtime_changes: 228` — while every one of those
368
+ entries carried `artifact_type: "documentation"` and `change_effect: "documentation file (no
369
+ runtime impact)"`. The list contradicted its own members. Reproduced on a real git repository
370
+ (12 `.md` files + one touched controller): **13 → 1**. The classifier was never wrong;
371
+ membership was "not noise and not a build manifest", which admits everything else, and the
372
+ admission seam (K2) now asks whether the admitted type can carry runtime behaviour at all.
373
+ - Nothing is dropped: the twelve are reported under `non_runtime_changes` with the same
374
+ evidence and effect statement, and the GitHub comment names them by count so it cannot look
375
+ like it missed part of the diff.
376
+ - The split is asserted **against the effect statements themselves** — a type whose published
377
+ statement disclaims impact must be in the non-runtime set — so it cannot drift from the
378
+ prose it is derived from (C4-1).
379
+
380
+ - **One profile population, whatever surface is asked** (C1-18, **`spring_profiles` changes on
381
+ repositories with resource bundles or resource folders**). Reproduced on a fixture first: the
382
+ same repository in one session answered `["qa","dev"]` in the default view, `["dev","prod",
383
+ "staging"]` in `posture` and `["dev","prod","qa","staging"]` under `--agent`. Three
384
+ populations under one name — and every conditional-security finding is keyed on that set, so
385
+ the default agent surface was answering the profile question with the population that had
386
+ lost the environments.
387
+ - Authority `spring_profiles.profile_population`: four named signals — the
388
+ `application-{profile}` filename, the per-environment overlay directory,
389
+ `spring.config.activate.on-profile` / `spring.profiles` inside config documents, and
390
+ `@Profile` on a bean — unioned once, with `by_signal` published so each name's provenance
391
+ is auditable. The Java stack detector, `posture` and the serializer's profile section all
392
+ read it, asserted per surface.
393
+ - Closing it exposed two false positives in the signals it inherited, both fixed
394
+ structurally rather than by name (VAI): an `application-{x}` file counts only **beside its
395
+ base config** — alfresco-community-repo's `alfresco/messages/application-model_de.properties`
396
+ and 19 siblings were reported as twenty environments, now none — and an overlay directory
397
+ counts only when it **holds a config file** — spring-petclinic's `db/`, `messages/`,
398
+ `static/` and `templates/` were reported as four environments, now `mysql, postgres`, its
399
+ real profiles.
400
+
401
+ - **The token-saving ratio is published, and published as a ceiling** (CL-1). `token_economy`
402
+ emitted `emitted`, `baseline_raw_read` and `saved` — three numbers a reader divides into a
403
+ multiple and then quotes. The multiple travelled without the label the block put on the
404
+ inputs, which is how "up to 55×" ends up in a room. `ratio_upper_bound` is now emitted with
405
+ a `ratio_basis` that states the counterfactual making it a ceiling — every cited file and
406
+ build manifest read **in full and once** — the band we measured for the ceiling itself
407
+ (**3.8×–37.6×** over `--compact` and `--agent` on spring-petclinic, BroadleafCommerce,
408
+ openmrs-core and keycloak; nothing near 55×), and the field's 10×–20× read of the saving an
409
+ agent actually realizes.
410
+ - `realized_saving` is `null` with its reason rather than a number: which files an agent would
411
+ truly have read is not observable from this process, and a `0` there would read as "no
412
+ saving" (I-3).
413
+
414
+ - **`spring-audit` counts defects as well as observations** (C2-5). A rule fires per
415
+ observation; a reader counts repairs. The audit published only the first number and let it
416
+ stand for the second: on openmrs-core `ConceptServiceImpl#checkIfLocked` carried **six
417
+ TX-006 findings, one per call site, for one annotated method with one fix**, and the
418
+ ledger's original witness is a private `@Transactional` method that draws TX-001 *and*
419
+ TX-006 for the same repair. Measured on the fleet: **openmrs-core 38 findings → 29
420
+ defects, BroadleafCommerce 19 → 14**.
421
+ - A defect is `(category, defect_kind, symbol)` — the thing you edit, and what is wrong
422
+ with it. `defect_kind` is **declared by the rule itself** (TX-001 and TX-006 both
423
+ declare `proxy_bypass`) and defaults to the rule's own id, so a rule that declares
424
+ nothing is never merged into another by omission, and there is no rule table maintained
425
+ beside the rules to drift out of date (C4-1).
426
+ - Nothing is filtered. `findings[]` keeps every observation and each one now names its
427
+ `defect_id`; the new `defects[]` rows carry `rule_ids`, `witness_count` and the witness
428
+ ids, so the grouping is auditable in both directions. `summary` publishes
429
+ `total_findings`, `total_defects`, `defects_by_severity` and a `counts_note` stating
430
+ which is which — `by_severity` and `by_category` keep counting observations, because a
431
+ count that changes basis under an unchanged name is the same defect wearing a new suit.
432
+ - A defect takes the **strongest** severity and confidence among its witnesses, and its id
433
+ is keyed on the identity, not the witnesses — acquiring a second witness next run does
434
+ not rename it, so a baseline keeps matching it.
435
+
436
+ - **`migrate-check` lists the blockers; hygiene is counted, not listed** (C2-6, **default
437
+ payload changes**). On openmrs-core the default report carried 310 findings of which **184
438
+ were `java_8_best_practice` advisory hygiene** — findings that block no version and that
439
+ every readiness score already excludes. A reader scanning the array met three advisory
440
+ entries for every two blockers. The emitted list now carries the blockers, ordered
441
+ most-severe first (**310 → 126 listed, 912 KB → 717 KB**), and `--include-hygiene` restores
442
+ the entries.
443
+ - **The floor cuts the list, never a figure.** `summary.by_severity`, `by_rule`,
444
+ `by_migration_target`, `total_findings`, `hygiene_findings`, `blocking_count` and every
445
+ dimension score are byte-identical to the unfloored run and still cover the whole
446
+ population — verified as an equality, not a claim.
447
+ - It is published as a cap, not applied in silence: `findings_floor` (the `severity_floor`
448
+ row of `CAP_EFFECTS`, I-8) states what was removed, what stayed exact, and the flag that
449
+ restores it, so `len(findings)` is never read as the total.
450
+ - The other half of the ledger row — "headline score reads 0/100 while real blockers are
451
+ 481" — was already closed and re-measured here: hygiene is out of the aggregate, and
452
+ openmrs's 0 is `min(jakarta 0, hibernate 0)` with `jdk_modernization` (58) excluded by
453
+ design. The score was honest; the finding list was the noise.
454
+
3
455
  ## [3.7.0] — 2026-08-01
4
456
 
5
457
  **The exit-code contract and the C3 surface block.** Seven rows closed: the two the field named
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: sourcecode
3
- Version: 3.7.0
3
+ Version: 4.0.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
@@ -220,7 +220,7 @@ experimental: both are true, and they are two different facts.
220
220
  |---|---|---|
221
221
  | **core** | contract stable within a major — safe to gate CI on | `endpoints` · `spring-audit` · `migrate-check` · `impact` · `impact-chain` · `pr-impact` · `verify` |
222
222
  | **supported** | maintained; fields are added, never removed without a major | every command not named in another row |
223
- | **experimental** | shape may change in a minor — do not gate CI on it | `posture` · `archetype` |
223
+ | **experimental** | shape may change in a minor — do not gate CI on it | `risk` · `posture` · `archetype` |
224
224
  | **parked** | kept working, no longer developed | `retrieve` |
225
225
 
226
226
  The same table is printed by `ask --help`, and both are generated from one authority
@@ -237,6 +237,7 @@ from it.
237
237
  | Command | Tier | Answers | Note |
238
238
  |---|---|---|---|
239
239
  | `posture` | experimental | which beans a profile set wires, and how effective endpoint access differs between two sets | the most differentiated capability here |
240
+ | `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 |
240
241
  | `endpoints` | core | every REST endpoint, effective path, security policy, confidence | Spring MVC + JAX-RS (~65 % recall on JAX-RS sub-resource locators) |
241
242
  | `spring-audit` | core | transactional anomalies + security surface + validation gaps | `--ci`, `-f github-comment` |
242
243
  | `migrate-check` | core | Boot 2→3 readiness: located blockers, per-dimension score, effort | `--blast-radius` orders the re-test plan |
@@ -251,7 +252,7 @@ from it.
251
252
  | `review-pr` / `fix-bug` / `prepare-context` | supported | diff review, symptom triage, task-shaped context | |
252
253
  | `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 |
253
254
  | `validation` | supported | request-body validation coverage and gaps | |
254
- | `baseline capture\|diff\|trend` | supported | versioned architectural metrics over time | trend reporting, not gating |
255
+ | `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) |
255
256
  | `retrieve` | parked | typed knowledge queries over the model | |
256
257
  | `archetype` | experimental | evidence-based architectural archetype | |
257
258
  | `rename-class` / `chunk-file` | supported | word-boundary Java rename; split a large file for an agent | |
@@ -275,6 +276,34 @@ Honest limits worth knowing before you rely on it:
275
276
  - Architecture classification is tuned for Spring MVC layered apps; SPI/plugin models (e.g. Quarkus extensions) may be misclassified. JAX-RS subresource-locator endpoint recall is ~65%.
276
277
  - Self-invocation `@Transactional` bypass (same-class call skipping the proxy) is not detected.
277
278
 
279
+ ### What the security surface does not answer
280
+
281
+ Published because a product that states its limits is not compared on breadth — it is
282
+ compared on depth. Each row is emitted in the payload too (`non_coverage`), so an agent
283
+ reading JSON sees the same boundary a buyer reads here.
284
+
285
+ | Not covered | Why | What answers it |
286
+ |---|---|---|
287
+ | **Whether request input reaches a sink — no dataflow or taint analysis.** | This engine resolves structure and wiring without compiling. Taint needs value flow through a program, which is a different analysis with a different failure mode: an unsound one produces confident findings that are wrong, and every claim here is meant to be checkable against the line that produced it. | A dataflow scanner (Semgrep, CodeQL). What this product adds on top is reachability: which of that tool's findings sit behind an endpoint that is reachable unauthenticated. |
288
+ | **Secrets outside Java and Spring configuration — a credential in a deployment descriptor, a Helm value, a CI variable file.** | The file population this analyzer reads is the Java source and the Spring configuration convention. A secret elsewhere is not missed by a weak rule; it is outside the set of files anything here opens. | A dedicated secret scanner over the whole tree (gitleaks, trufflehog). |
289
+ | **Filter-chain order and per-filter URL patterns — the presence of a custom filter is structural only.** | Which filter runs first is decided by bean ordering this analyzer does not resolve. Where two active configurations both match a request, the answer published is `undecided` rather than a guess. | `ask posture --profile <set>` states per endpoint what the readable rules decide and what they leave undecided. |
290
+ | **Known vulnerabilities in dependencies — no CVE database, no version advisory matching.** | Enriching a vulnerability feed is a different product with a different update cadence; a stale embedded database is worse than no database, because it reads as a clean bill of health. | A dependency scanner (Trivy, OWASP Dependency-Check). `impact-chain` then answers which of its findings anything actually reaches. |
291
+
292
+ Two more boundaries worth stating in the same voice:
293
+
294
+ | Not covered | Why | What answers it |
295
+ |---|---|---|
296
+ | **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. |
297
+ | **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. |
298
+
299
+ **Positioning.** Until an executor ships, this is the **diagnosis layer**: it measures what
300
+ must change, what each change reaches, and what a gate should block — and it removes none of
301
+ it. Field evaluation scored it 7/10 as a report generator and 5.5/10 as a development tool,
302
+ and that gap is the honest description, not a defect to argue with. `migrate-check` publishes
303
+ the OpenRewrite recipe each finding carries so the executor that does apply changes has its
304
+ input.
305
+
306
+
278
307
  ---
279
308
 
280
309
  ## Pricing
@@ -348,7 +377,8 @@ Matching endpoints report `policy: "custom"` and drop out of the `no_security_si
348
377
  | Doc | What it covers |
349
378
  |-----|----------------|
350
379
  | [USER_GUIDE.md](docs/USER_GUIDE.md) | Full command reference, flags, output schema, workflows |
351
- | [contracts.md](docs/contracts.md) | Declare invariants in `.ask/contracts.yml`, enforce them in the edit loop and in CI |
380
+ | [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 |
381
+ | [baseline-ci.yml](docs/baseline-ci.yml) | Capture an architectural baseline per release, so the series exists when you want to read it |
352
382
  | [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) |
353
383
  | [migrate-check.md](docs/migrate-check.md) | Migration rule catalogue (MIG-001..043) + Hibernate stratification |
354
384
  | [MODERNIZATION.md](docs/MODERNIZATION.md) | The modernization product: assess → understand → plan → execute |
@@ -182,7 +182,7 @@ experimental: both are true, and they are two different facts.
182
182
  |---|---|---|
183
183
  | **core** | contract stable within a major — safe to gate CI on | `endpoints` · `spring-audit` · `migrate-check` · `impact` · `impact-chain` · `pr-impact` · `verify` |
184
184
  | **supported** | maintained; fields are added, never removed without a major | every command not named in another row |
185
- | **experimental** | shape may change in a minor — do not gate CI on it | `posture` · `archetype` |
185
+ | **experimental** | shape may change in a minor — do not gate CI on it | `risk` · `posture` · `archetype` |
186
186
  | **parked** | kept working, no longer developed | `retrieve` |
187
187
 
188
188
  The same table is printed by `ask --help`, and both are generated from one authority
@@ -199,6 +199,7 @@ from it.
199
199
  | Command | Tier | Answers | Note |
200
200
  |---|---|---|---|
201
201
  | `posture` | experimental | which beans a profile set wires, and how effective endpoint access differs between two sets | the most differentiated capability here |
202
+ | `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 |
202
203
  | `endpoints` | core | every REST endpoint, effective path, security policy, confidence | Spring MVC + JAX-RS (~65 % recall on JAX-RS sub-resource locators) |
203
204
  | `spring-audit` | core | transactional anomalies + security surface + validation gaps | `--ci`, `-f github-comment` |
204
205
  | `migrate-check` | core | Boot 2→3 readiness: located blockers, per-dimension score, effort | `--blast-radius` orders the re-test plan |
@@ -213,7 +214,7 @@ from it.
213
214
  | `review-pr` / `fix-bug` / `prepare-context` | supported | diff review, symptom triage, task-shaped context | |
214
215
  | `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 |
215
216
  | `validation` | supported | request-body validation coverage and gaps | |
216
- | `baseline capture\|diff\|trend` | supported | versioned architectural metrics over time | trend reporting, not gating |
217
+ | `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) |
217
218
  | `retrieve` | parked | typed knowledge queries over the model | |
218
219
  | `archetype` | experimental | evidence-based architectural archetype | |
219
220
  | `rename-class` / `chunk-file` | supported | word-boundary Java rename; split a large file for an agent | |
@@ -237,6 +238,34 @@ Honest limits worth knowing before you rely on it:
237
238
  - Architecture classification is tuned for Spring MVC layered apps; SPI/plugin models (e.g. Quarkus extensions) may be misclassified. JAX-RS subresource-locator endpoint recall is ~65%.
238
239
  - Self-invocation `@Transactional` bypass (same-class call skipping the proxy) is not detected.
239
240
 
241
+ ### What the security surface does not answer
242
+
243
+ Published because a product that states its limits is not compared on breadth — it is
244
+ compared on depth. Each row is emitted in the payload too (`non_coverage`), so an agent
245
+ reading JSON sees the same boundary a buyer reads here.
246
+
247
+ | Not covered | Why | What answers it |
248
+ |---|---|---|
249
+ | **Whether request input reaches a sink — no dataflow or taint analysis.** | This engine resolves structure and wiring without compiling. Taint needs value flow through a program, which is a different analysis with a different failure mode: an unsound one produces confident findings that are wrong, and every claim here is meant to be checkable against the line that produced it. | A dataflow scanner (Semgrep, CodeQL). What this product adds on top is reachability: which of that tool's findings sit behind an endpoint that is reachable unauthenticated. |
250
+ | **Secrets outside Java and Spring configuration — a credential in a deployment descriptor, a Helm value, a CI variable file.** | The file population this analyzer reads is the Java source and the Spring configuration convention. A secret elsewhere is not missed by a weak rule; it is outside the set of files anything here opens. | A dedicated secret scanner over the whole tree (gitleaks, trufflehog). |
251
+ | **Filter-chain order and per-filter URL patterns — the presence of a custom filter is structural only.** | Which filter runs first is decided by bean ordering this analyzer does not resolve. Where two active configurations both match a request, the answer published is `undecided` rather than a guess. | `ask posture --profile <set>` states per endpoint what the readable rules decide and what they leave undecided. |
252
+ | **Known vulnerabilities in dependencies — no CVE database, no version advisory matching.** | Enriching a vulnerability feed is a different product with a different update cadence; a stale embedded database is worse than no database, because it reads as a clean bill of health. | A dependency scanner (Trivy, OWASP Dependency-Check). `impact-chain` then answers which of its findings anything actually reaches. |
253
+
254
+ Two more boundaries worth stating in the same voice:
255
+
256
+ | Not covered | Why | What answers it |
257
+ |---|---|---|
258
+ | **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. |
259
+ | **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. |
260
+
261
+ **Positioning.** Until an executor ships, this is the **diagnosis layer**: it measures what
262
+ must change, what each change reaches, and what a gate should block — and it removes none of
263
+ it. Field evaluation scored it 7/10 as a report generator and 5.5/10 as a development tool,
264
+ and that gap is the honest description, not a defect to argue with. `migrate-check` publishes
265
+ the OpenRewrite recipe each finding carries so the executor that does apply changes has its
266
+ input.
267
+
268
+
240
269
  ---
241
270
 
242
271
  ## Pricing
@@ -310,7 +339,8 @@ Matching endpoints report `policy: "custom"` and drop out of the `no_security_si
310
339
  | Doc | What it covers |
311
340
  |-----|----------------|
312
341
  | [USER_GUIDE.md](docs/USER_GUIDE.md) | Full command reference, flags, output schema, workflows |
313
- | [contracts.md](docs/contracts.md) | Declare invariants in `.ask/contracts.yml`, enforce them in the edit loop and in CI |
342
+ | [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 |
343
+ | [baseline-ci.yml](docs/baseline-ci.yml) | Capture an architectural baseline per release, so the series exists when you want to read it |
314
344
  | [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) |
315
345
  | [migrate-check.md](docs/migrate-check.md) | Migration rule catalogue (MIG-001..043) + Hibernate stratification |
316
346
  | [MODERNIZATION.md](docs/MODERNIZATION.md) | The modernization product: assess → understand → plan → execute |
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "sourcecode"
7
- version = "3.7.0"
7
+ version = "4.0.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__ = "3.7.0"
7
+ __version__ = "4.0.0"