sourcecode 4.12.0__tar.gz → 4.15.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 (231) hide show
  1. sourcecode-4.15.0/.github/workflows/perf-gate.yml +109 -0
  2. {sourcecode-4.12.0 → sourcecode-4.15.0}/CHANGELOG.md +247 -0
  3. {sourcecode-4.12.0 → sourcecode-4.15.0}/PKG-INFO +51 -11
  4. {sourcecode-4.12.0 → sourcecode-4.15.0}/README.md +50 -10
  5. {sourcecode-4.12.0 → sourcecode-4.15.0}/pyproject.toml +1 -1
  6. sourcecode-4.15.0/scripts/perf_gate.py +176 -0
  7. {sourcecode-4.12.0 → sourcecode-4.15.0}/src/sourcecode/__init__.py +1 -1
  8. {sourcecode-4.12.0 → sourcecode-4.15.0}/src/sourcecode/architectural_baseline.py +5 -0
  9. {sourcecode-4.12.0 → sourcecode-4.15.0}/src/sourcecode/cache_model.py +53 -1
  10. {sourcecode-4.12.0 → sourcecode-4.15.0}/src/sourcecode/cli.py +245 -7
  11. sourcecode-4.15.0/src/sourcecode/parallel.py +241 -0
  12. {sourcecode-4.12.0 → sourcecode-4.15.0}/src/sourcecode/parse_cache.py +183 -1
  13. {sourcecode-4.12.0 → sourcecode-4.15.0}/src/sourcecode/perf.py +268 -4
  14. {sourcecode-4.12.0 → sourcecode-4.15.0}/src/sourcecode/phased_run.py +33 -0
  15. {sourcecode-4.12.0 → sourcecode-4.15.0}/src/sourcecode/progress.py +99 -46
  16. {sourcecode-4.12.0 → sourcecode-4.15.0}/src/sourcecode/readiness_timeline.py +2 -0
  17. sourcecode-4.15.0/src/sourcecode/readonly.py +171 -0
  18. {sourcecode-4.12.0 → sourcecode-4.15.0}/src/sourcecode/release_info.py +1 -1
  19. {sourcecode-4.12.0 → sourcecode-4.15.0}/src/sourcecode/repository_ir.py +24 -1
  20. sourcecode-4.15.0/src/sourcecode/rule_pass.py +277 -0
  21. {sourcecode-4.12.0 → sourcecode-4.15.0}/src/sourcecode/runs.py +3 -0
  22. {sourcecode-4.12.0 → sourcecode-4.15.0}/src/sourcecode/security_config_scan.py +43 -5
  23. {sourcecode-4.12.0 → sourcecode-4.15.0}/src/sourcecode/spring_findings.py +82 -0
  24. {sourcecode-4.12.0 → sourcecode-4.15.0}/src/sourcecode/spring_security_audit.py +108 -13
  25. {sourcecode-4.12.0 → sourcecode-4.15.0}/src/sourcecode/spring_tx_analyzer.py +88 -14
  26. {sourcecode-4.12.0 → sourcecode-4.15.0}/src/sourcecode/verify_edit.py +3 -0
  27. {sourcecode-4.12.0 → sourcecode-4.15.0}/src/sourcecode/verify_repo.py +3 -0
  28. sourcecode-4.12.0/src/sourcecode/rule_pass.py +0 -112
  29. {sourcecode-4.12.0 → sourcecode-4.15.0}/.github/workflows/build-windows.yml +0 -0
  30. {sourcecode-4.12.0 → sourcecode-4.15.0}/.gitignore +0 -0
  31. {sourcecode-4.12.0 → sourcecode-4.15.0}/.ruff.toml +0 -0
  32. {sourcecode-4.12.0 → sourcecode-4.15.0}/CLAUDE.md +0 -0
  33. {sourcecode-4.12.0 → sourcecode-4.15.0}/CONTRIBUTING.md +0 -0
  34. {sourcecode-4.12.0 → sourcecode-4.15.0}/LICENSE +0 -0
  35. {sourcecode-4.12.0 → sourcecode-4.15.0}/SECURITY.md +0 -0
  36. {sourcecode-4.12.0 → sourcecode-4.15.0}/raw +0 -0
  37. {sourcecode-4.12.0 → sourcecode-4.15.0}/scripts/compare_integration_engines.py +0 -0
  38. {sourcecode-4.12.0 → sourcecode-4.15.0}/scripts/customer_smoke_test.sh +0 -0
  39. {sourcecode-4.12.0 → sourcecode-4.15.0}/scripts/generate_jdk_exports.py +0 -0
  40. {sourcecode-4.12.0 → sourcecode-4.15.0}/scripts/perf_harness.py +0 -0
  41. {sourcecode-4.12.0 → sourcecode-4.15.0}/src/sourcecode/adaptive_scanner.py +0 -0
  42. {sourcecode-4.12.0 → sourcecode-4.15.0}/src/sourcecode/archetype.py +0 -0
  43. {sourcecode-4.12.0 → sourcecode-4.15.0}/src/sourcecode/architectural_delta.py +0 -0
  44. {sourcecode-4.12.0 → sourcecode-4.15.0}/src/sourcecode/architecture_analyzer.py +0 -0
  45. {sourcecode-4.12.0 → sourcecode-4.15.0}/src/sourcecode/architecture_summary.py +0 -0
  46. {sourcecode-4.12.0 → sourcecode-4.15.0}/src/sourcecode/ast_extractor.py +0 -0
  47. {sourcecode-4.12.0 → sourcecode-4.15.0}/src/sourcecode/audit_report.py +0 -0
  48. {sourcecode-4.12.0 → sourcecode-4.15.0}/src/sourcecode/baseline_autocapture.py +0 -0
  49. {sourcecode-4.12.0 → sourcecode-4.15.0}/src/sourcecode/cache.py +0 -0
  50. {sourcecode-4.12.0 → sourcecode-4.15.0}/src/sourcecode/call_surface.py +0 -0
  51. {sourcecode-4.12.0 → sourcecode-4.15.0}/src/sourcecode/caller_metrics.py +0 -0
  52. {sourcecode-4.12.0 → sourcecode-4.15.0}/src/sourcecode/caller_reach.py +0 -0
  53. {sourcecode-4.12.0 → sourcecode-4.15.0}/src/sourcecode/canonical_ir.py +0 -0
  54. {sourcecode-4.12.0 → sourcecode-4.15.0}/src/sourcecode/chain_rules.py +0 -0
  55. {sourcecode-4.12.0 → sourcecode-4.15.0}/src/sourcecode/change_plan.py +0 -0
  56. {sourcecode-4.12.0 → sourcecode-4.15.0}/src/sourcecode/cir_graphs.py +0 -0
  57. {sourcecode-4.12.0 → sourcecode-4.15.0}/src/sourcecode/classifier.py +0 -0
  58. {sourcecode-4.12.0 → sourcecode-4.15.0}/src/sourcecode/client_calls.py +0 -0
  59. {sourcecode-4.12.0 → sourcecode-4.15.0}/src/sourcecode/code_notes_analyzer.py +0 -0
  60. {sourcecode-4.12.0 → sourcecode-4.15.0}/src/sourcecode/compare.py +0 -0
  61. {sourcecode-4.12.0 → sourcecode-4.15.0}/src/sourcecode/confidence_analyzer.py +0 -0
  62. {sourcecode-4.12.0 → sourcecode-4.15.0}/src/sourcecode/constraint_diff.py +0 -0
  63. {sourcecode-4.12.0 → sourcecode-4.15.0}/src/sourcecode/container_wiring.py +0 -0
  64. {sourcecode-4.12.0 → sourcecode-4.15.0}/src/sourcecode/context_cache.py +0 -0
  65. {sourcecode-4.12.0 → sourcecode-4.15.0}/src/sourcecode/context_graph.py +0 -0
  66. {sourcecode-4.12.0 → sourcecode-4.15.0}/src/sourcecode/context_scorer.py +0 -0
  67. {sourcecode-4.12.0 → sourcecode-4.15.0}/src/sourcecode/context_summarizer.py +0 -0
  68. {sourcecode-4.12.0 → sourcecode-4.15.0}/src/sourcecode/contract_diff.py +0 -0
  69. {sourcecode-4.12.0 → sourcecode-4.15.0}/src/sourcecode/contract_init.py +0 -0
  70. {sourcecode-4.12.0 → sourcecode-4.15.0}/src/sourcecode/contract_model.py +0 -0
  71. {sourcecode-4.12.0 → sourcecode-4.15.0}/src/sourcecode/contract_pipeline.py +0 -0
  72. {sourcecode-4.12.0 → sourcecode-4.15.0}/src/sourcecode/coverage_parser.py +0 -0
  73. {sourcecode-4.12.0 → sourcecode-4.15.0}/src/sourcecode/data_exposure.py +0 -0
  74. {sourcecode-4.12.0 → sourcecode-4.15.0}/src/sourcecode/data_labels.py +0 -0
  75. {sourcecode-4.12.0 → sourcecode-4.15.0}/src/sourcecode/defect_identity.py +0 -0
  76. {sourcecode-4.12.0 → sourcecode-4.15.0}/src/sourcecode/degradation.py +0 -0
  77. {sourcecode-4.12.0 → sourcecode-4.15.0}/src/sourcecode/dependency_analyzer.py +0 -0
  78. {sourcecode-4.12.0 → sourcecode-4.15.0}/src/sourcecode/deployment_prefix.py +0 -0
  79. {sourcecode-4.12.0 → sourcecode-4.15.0}/src/sourcecode/detach.py +0 -0
  80. {sourcecode-4.12.0 → sourcecode-4.15.0}/src/sourcecode/detectors/__init__.py +0 -0
  81. {sourcecode-4.12.0 → sourcecode-4.15.0}/src/sourcecode/detectors/base.py +0 -0
  82. {sourcecode-4.12.0 → sourcecode-4.15.0}/src/sourcecode/detectors/csproj_parser.py +0 -0
  83. {sourcecode-4.12.0 → sourcecode-4.15.0}/src/sourcecode/detectors/dart.py +0 -0
  84. {sourcecode-4.12.0 → sourcecode-4.15.0}/src/sourcecode/detectors/dotnet.py +0 -0
  85. {sourcecode-4.12.0 → sourcecode-4.15.0}/src/sourcecode/detectors/elixir.py +0 -0
  86. {sourcecode-4.12.0 → sourcecode-4.15.0}/src/sourcecode/detectors/go.py +0 -0
  87. {sourcecode-4.12.0 → sourcecode-4.15.0}/src/sourcecode/detectors/heuristic.py +0 -0
  88. {sourcecode-4.12.0 → sourcecode-4.15.0}/src/sourcecode/detectors/hybrid.py +0 -0
  89. {sourcecode-4.12.0 → sourcecode-4.15.0}/src/sourcecode/detectors/java.py +0 -0
  90. {sourcecode-4.12.0 → sourcecode-4.15.0}/src/sourcecode/detectors/jvm_ext.py +0 -0
  91. {sourcecode-4.12.0 → sourcecode-4.15.0}/src/sourcecode/detectors/nodejs.py +0 -0
  92. {sourcecode-4.12.0 → sourcecode-4.15.0}/src/sourcecode/detectors/parsers.py +0 -0
  93. {sourcecode-4.12.0 → sourcecode-4.15.0}/src/sourcecode/detectors/php.py +0 -0
  94. {sourcecode-4.12.0 → sourcecode-4.15.0}/src/sourcecode/detectors/project.py +0 -0
  95. {sourcecode-4.12.0 → sourcecode-4.15.0}/src/sourcecode/detectors/python.py +0 -0
  96. {sourcecode-4.12.0 → sourcecode-4.15.0}/src/sourcecode/detectors/ruby.py +0 -0
  97. {sourcecode-4.12.0 → sourcecode-4.15.0}/src/sourcecode/detectors/rust.py +0 -0
  98. {sourcecode-4.12.0 → sourcecode-4.15.0}/src/sourcecode/detectors/systems.py +0 -0
  99. {sourcecode-4.12.0 → sourcecode-4.15.0}/src/sourcecode/detectors/terraform.py +0 -0
  100. {sourcecode-4.12.0 → sourcecode-4.15.0}/src/sourcecode/detectors/tooling.py +0 -0
  101. {sourcecode-4.12.0 → sourcecode-4.15.0}/src/sourcecode/doc_analyzer.py +0 -0
  102. {sourcecode-4.12.0 → sourcecode-4.15.0}/src/sourcecode/dynamic_argument_surface.py +0 -0
  103. {sourcecode-4.12.0 → sourcecode-4.15.0}/src/sourcecode/endpoint_literals.py +0 -0
  104. {sourcecode-4.12.0 → sourcecode-4.15.0}/src/sourcecode/endpoint_metrics.py +0 -0
  105. {sourcecode-4.12.0 → sourcecode-4.15.0}/src/sourcecode/entrypoint_classifier.py +0 -0
  106. {sourcecode-4.12.0 → sourcecode-4.15.0}/src/sourcecode/env_analyzer.py +0 -0
  107. {sourcecode-4.12.0 → sourcecode-4.15.0}/src/sourcecode/envelope.py +0 -0
  108. {sourcecode-4.12.0 → sourcecode-4.15.0}/src/sourcecode/environment_resolution.py +0 -0
  109. {sourcecode-4.12.0 → sourcecode-4.15.0}/src/sourcecode/error_schema.py +0 -0
  110. {sourcecode-4.12.0 → sourcecode-4.15.0}/src/sourcecode/evidence_provider.py +0 -0
  111. {sourcecode-4.12.0 → sourcecode-4.15.0}/src/sourcecode/execution_plan.py +0 -0
  112. {sourcecode-4.12.0 → sourcecode-4.15.0}/src/sourcecode/explain.py +0 -0
  113. {sourcecode-4.12.0 → sourcecode-4.15.0}/src/sourcecode/facts/__init__.py +0 -0
  114. {sourcecode-4.12.0 → sourcecode-4.15.0}/src/sourcecode/facts/registry.json +0 -0
  115. {sourcecode-4.12.0 → sourcecode-4.15.0}/src/sourcecode/file_chunker.py +0 -0
  116. {sourcecode-4.12.0 → sourcecode-4.15.0}/src/sourcecode/file_classifier.py +0 -0
  117. {sourcecode-4.12.0 → sourcecode-4.15.0}/src/sourcecode/filter_surface.py +0 -0
  118. {sourcecode-4.12.0 → sourcecode-4.15.0}/src/sourcecode/format_contract.py +0 -0
  119. {sourcecode-4.12.0 → sourcecode-4.15.0}/src/sourcecode/fqn_utils.py +0 -0
  120. {sourcecode-4.12.0 → sourcecode-4.15.0}/src/sourcecode/git_analyzer.py +0 -0
  121. {sourcecode-4.12.0 → sourcecode-4.15.0}/src/sourcecode/git_checkout.py +0 -0
  122. {sourcecode-4.12.0 → sourcecode-4.15.0}/src/sourcecode/graph_analyzer.py +0 -0
  123. {sourcecode-4.12.0 → sourcecode-4.15.0}/src/sourcecode/graph_evidence.py +0 -0
  124. {sourcecode-4.12.0 → sourcecode-4.15.0}/src/sourcecode/hibernate_strat.py +0 -0
  125. {sourcecode-4.12.0 → sourcecode-4.15.0}/src/sourcecode/identity_fallback.py +0 -0
  126. {sourcecode-4.12.0 → sourcecode-4.15.0}/src/sourcecode/integration_coordinates.py +0 -0
  127. {sourcecode-4.12.0 → sourcecode-4.15.0}/src/sourcecode/jdk_exports.py +0 -0
  128. {sourcecode-4.12.0 → sourcecode-4.15.0}/src/sourcecode/license.py +0 -0
  129. {sourcecode-4.12.0 → sourcecode-4.15.0}/src/sourcecode/mcp/__init__.py +0 -0
  130. {sourcecode-4.12.0 → sourcecode-4.15.0}/src/sourcecode/mcp/dependency_import.py +0 -0
  131. {sourcecode-4.12.0 → sourcecode-4.15.0}/src/sourcecode/mcp/onboarding/__init__.py +0 -0
  132. {sourcecode-4.12.0 → sourcecode-4.15.0}/src/sourcecode/mcp/onboarding/applier.py +0 -0
  133. {sourcecode-4.12.0 → sourcecode-4.15.0}/src/sourcecode/mcp/onboarding/backup.py +0 -0
  134. {sourcecode-4.12.0 → sourcecode-4.15.0}/src/sourcecode/mcp/onboarding/detector.py +0 -0
  135. {sourcecode-4.12.0 → sourcecode-4.15.0}/src/sourcecode/mcp/onboarding/planner.py +0 -0
  136. {sourcecode-4.12.0 → sourcecode-4.15.0}/src/sourcecode/mcp/orchestrator.py +0 -0
  137. {sourcecode-4.12.0 → sourcecode-4.15.0}/src/sourcecode/mcp/registry.py +0 -0
  138. {sourcecode-4.12.0 → sourcecode-4.15.0}/src/sourcecode/mcp/runner.py +0 -0
  139. {sourcecode-4.12.0 → sourcecode-4.15.0}/src/sourcecode/mcp/server.py +0 -0
  140. {sourcecode-4.12.0 → sourcecode-4.15.0}/src/sourcecode/mcp_nudge.py +0 -0
  141. {sourcecode-4.12.0 → sourcecode-4.15.0}/src/sourcecode/metrics_analyzer.py +0 -0
  142. {sourcecode-4.12.0 → sourcecode-4.15.0}/src/sourcecode/migrate_check.py +0 -0
  143. {sourcecode-4.12.0 → sourcecode-4.15.0}/src/sourcecode/migration_blast.py +0 -0
  144. {sourcecode-4.12.0 → sourcecode-4.15.0}/src/sourcecode/non_coverage.py +0 -0
  145. {sourcecode-4.12.0 → sourcecode-4.15.0}/src/sourcecode/openapi_surface.py +0 -0
  146. {sourcecode-4.12.0 → sourcecode-4.15.0}/src/sourcecode/openrewrite_recipe.py +0 -0
  147. {sourcecode-4.12.0 → sourcecode-4.15.0}/src/sourcecode/output_budget.py +0 -0
  148. {sourcecode-4.12.0 → sourcecode-4.15.0}/src/sourcecode/output_encoding.py +0 -0
  149. {sourcecode-4.12.0 → sourcecode-4.15.0}/src/sourcecode/path_admission.py +0 -0
  150. {sourcecode-4.12.0 → sourcecode-4.15.0}/src/sourcecode/path_filters.py +0 -0
  151. {sourcecode-4.12.0 → sourcecode-4.15.0}/src/sourcecode/pipe_contract.py +0 -0
  152. {sourcecode-4.12.0 → sourcecode-4.15.0}/src/sourcecode/posture.py +0 -0
  153. {sourcecode-4.12.0 → sourcecode-4.15.0}/src/sourcecode/pr_comment_renderer.py +0 -0
  154. {sourcecode-4.12.0 → sourcecode-4.15.0}/src/sourcecode/pr_impact.py +0 -0
  155. {sourcecode-4.12.0 → sourcecode-4.15.0}/src/sourcecode/prepare_context.py +0 -0
  156. {sourcecode-4.12.0 → sourcecode-4.15.0}/src/sourcecode/provenance.py +0 -0
  157. {sourcecode-4.12.0 → sourcecode-4.15.0}/src/sourcecode/ranking_engine.py +0 -0
  158. {sourcecode-4.12.0 → sourcecode-4.15.0}/src/sourcecode/reconciliation.py +0 -0
  159. {sourcecode-4.12.0 → sourcecode-4.15.0}/src/sourcecode/redactor.py +0 -0
  160. {sourcecode-4.12.0 → sourcecode-4.15.0}/src/sourcecode/reference_facts.py +0 -0
  161. {sourcecode-4.12.0 → sourcecode-4.15.0}/src/sourcecode/relevance_scorer.py +0 -0
  162. {sourcecode-4.12.0 → sourcecode-4.15.0}/src/sourcecode/remedies.py +0 -0
  163. {sourcecode-4.12.0 → sourcecode-4.15.0}/src/sourcecode/rename_refactor.py +0 -0
  164. {sourcecode-4.12.0 → sourcecode-4.15.0}/src/sourcecode/repo_classifier.py +0 -0
  165. {sourcecode-4.12.0 → sourcecode-4.15.0}/src/sourcecode/retrieval/__init__.py +0 -0
  166. {sourcecode-4.12.0 → sourcecode-4.15.0}/src/sourcecode/retrieval/context.py +0 -0
  167. {sourcecode-4.12.0 → sourcecode-4.15.0}/src/sourcecode/retrieval/errors.py +0 -0
  168. {sourcecode-4.12.0 → sourcecode-4.15.0}/src/sourcecode/retrieval/executor.py +0 -0
  169. {sourcecode-4.12.0 → sourcecode-4.15.0}/src/sourcecode/retrieval/planner.py +0 -0
  170. {sourcecode-4.12.0 → sourcecode-4.15.0}/src/sourcecode/retrieval/query.py +0 -0
  171. {sourcecode-4.12.0 → sourcecode-4.15.0}/src/sourcecode/retrieval/request.py +0 -0
  172. {sourcecode-4.12.0 → sourcecode-4.15.0}/src/sourcecode/retrieval/resolution.py +0 -0
  173. {sourcecode-4.12.0 → sourcecode-4.15.0}/src/sourcecode/retrieval/result.py +0 -0
  174. {sourcecode-4.12.0 → sourcecode-4.15.0}/src/sourcecode/retrieval/retriever.py +0 -0
  175. {sourcecode-4.12.0 → sourcecode-4.15.0}/src/sourcecode/retrieval/runtime.py +0 -0
  176. {sourcecode-4.12.0 → sourcecode-4.15.0}/src/sourcecode/retrieval/steps.py +0 -0
  177. {sourcecode-4.12.0 → sourcecode-4.15.0}/src/sourcecode/retrieval/steps_endpoint.py +0 -0
  178. {sourcecode-4.12.0 → sourcecode-4.15.0}/src/sourcecode/retrieval/steps_graph.py +0 -0
  179. {sourcecode-4.12.0 → sourcecode-4.15.0}/src/sourcecode/retrieval/steps_impact.py +0 -0
  180. {sourcecode-4.12.0 → sourcecode-4.15.0}/src/sourcecode/retrieval/steps_intf.py +0 -0
  181. {sourcecode-4.12.0 → sourcecode-4.15.0}/src/sourcecode/retrieval/steps_struct.py +0 -0
  182. {sourcecode-4.12.0 → sourcecode-4.15.0}/src/sourcecode/retrieval/steps_txsec.py +0 -0
  183. {sourcecode-4.12.0 → sourcecode-4.15.0}/src/sourcecode/ris.py +0 -0
  184. {sourcecode-4.12.0 → sourcecode-4.15.0}/src/sourcecode/risk.py +0 -0
  185. {sourcecode-4.12.0 → sourcecode-4.15.0}/src/sourcecode/rule_catalog.py +0 -0
  186. {sourcecode-4.12.0 → sourcecode-4.15.0}/src/sourcecode/runtime_classifier.py +0 -0
  187. {sourcecode-4.12.0 → sourcecode-4.15.0}/src/sourcecode/sarif.py +0 -0
  188. {sourcecode-4.12.0 → sourcecode-4.15.0}/src/sourcecode/scanner.py +0 -0
  189. {sourcecode-4.12.0 → sourcecode-4.15.0}/src/sourcecode/schema.py +0 -0
  190. {sourcecode-4.12.0 → sourcecode-4.15.0}/src/sourcecode/schemas/envelope-v1.schema.json +0 -0
  191. {sourcecode-4.12.0 → sourcecode-4.15.0}/src/sourcecode/security_config.py +0 -0
  192. {sourcecode-4.12.0 → sourcecode-4.15.0}/src/sourcecode/security_posture.py +0 -0
  193. {sourcecode-4.12.0 → sourcecode-4.15.0}/src/sourcecode/semantic_analyzer.py +0 -0
  194. {sourcecode-4.12.0 → sourcecode-4.15.0}/src/sourcecode/semantic_impact_engine.py +0 -0
  195. {sourcecode-4.12.0 → sourcecode-4.15.0}/src/sourcecode/semantic_integration_engine.py +0 -0
  196. {sourcecode-4.12.0 → sourcecode-4.15.0}/src/sourcecode/semantic_services.py +0 -0
  197. {sourcecode-4.12.0 → sourcecode-4.15.0}/src/sourcecode/serializer.py +0 -0
  198. {sourcecode-4.12.0 → sourcecode-4.15.0}/src/sourcecode/servlet_surface.py +0 -0
  199. {sourcecode-4.12.0 → sourcecode-4.15.0}/src/sourcecode/source_text.py +0 -0
  200. {sourcecode-4.12.0 → sourcecode-4.15.0}/src/sourcecode/spring_event_topology.py +0 -0
  201. {sourcecode-4.12.0 → sourcecode-4.15.0}/src/sourcecode/spring_impact.py +0 -0
  202. {sourcecode-4.12.0 → sourcecode-4.15.0}/src/sourcecode/spring_model.py +0 -0
  203. {sourcecode-4.12.0 → sourcecode-4.15.0}/src/sourcecode/spring_profiles.py +0 -0
  204. {sourcecode-4.12.0 → sourcecode-4.15.0}/src/sourcecode/spring_properties.py +0 -0
  205. {sourcecode-4.12.0 → sourcecode-4.15.0}/src/sourcecode/spring_semantic.py +0 -0
  206. {sourcecode-4.12.0 → sourcecode-4.15.0}/src/sourcecode/summarizer.py +0 -0
  207. {sourcecode-4.12.0 → sourcecode-4.15.0}/src/sourcecode/target_admission.py +0 -0
  208. {sourcecode-4.12.0 → sourcecode-4.15.0}/src/sourcecode/telemetry/__init__.py +0 -0
  209. {sourcecode-4.12.0 → sourcecode-4.15.0}/src/sourcecode/telemetry/config.py +0 -0
  210. {sourcecode-4.12.0 → sourcecode-4.15.0}/src/sourcecode/telemetry/consent.py +0 -0
  211. {sourcecode-4.12.0 → sourcecode-4.15.0}/src/sourcecode/telemetry/events.py +0 -0
  212. {sourcecode-4.12.0 → sourcecode-4.15.0}/src/sourcecode/telemetry/filters.py +0 -0
  213. {sourcecode-4.12.0 → sourcecode-4.15.0}/src/sourcecode/telemetry/transport.py +0 -0
  214. {sourcecode-4.12.0 → sourcecode-4.15.0}/src/sourcecode/test_gap_ranking.py +0 -0
  215. {sourcecode-4.12.0 → sourcecode-4.15.0}/src/sourcecode/test_sources.py +0 -0
  216. {sourcecode-4.12.0 → sourcecode-4.15.0}/src/sourcecode/text_input.py +0 -0
  217. {sourcecode-4.12.0 → sourcecode-4.15.0}/src/sourcecode/token_estimate.py +0 -0
  218. {sourcecode-4.12.0 → sourcecode-4.15.0}/src/sourcecode/tree_utils.py +0 -0
  219. {sourcecode-4.12.0 → sourcecode-4.15.0}/src/sourcecode/type_usage_surface.py +0 -0
  220. {sourcecode-4.12.0 → sourcecode-4.15.0}/src/sourcecode/validation_inference.py +0 -0
  221. {sourcecode-4.12.0 → sourcecode-4.15.0}/src/sourcecode/validation_surface.py +0 -0
  222. {sourcecode-4.12.0 → sourcecode-4.15.0}/src/sourcecode/verify_rules.py +0 -0
  223. {sourcecode-4.12.0 → sourcecode-4.15.0}/src/sourcecode/version_check.py +0 -0
  224. {sourcecode-4.12.0 → sourcecode-4.15.0}/src/sourcecode/workspace.py +0 -0
  225. {sourcecode-4.12.0 → sourcecode-4.15.0}/supabase/functions/README.md +0 -0
  226. {sourcecode-4.12.0 → sourcecode-4.15.0}/supabase/functions/get-license/index.ts +0 -0
  227. {sourcecode-4.12.0 → sourcecode-4.15.0}/supabase/functions/lemonsqueezy-webhook/index.ts +0 -0
  228. {sourcecode-4.12.0 → sourcecode-4.15.0}/supabase/functions/telemetry/index.ts +0 -0
  229. {sourcecode-4.12.0 → sourcecode-4.15.0}/supabase/sql/license_event_ordering.sql +0 -0
  230. {sourcecode-4.12.0 → sourcecode-4.15.0}/supabase/sql/licensing_schema.sql +0 -0
  231. {sourcecode-4.12.0 → sourcecode-4.15.0}/supabase/sql/telemetry_events.sql +0 -0
@@ -0,0 +1,109 @@
1
+ name: Performance regression gate
2
+
3
+ # F-AP. Field evaluation #16 measured seven commands 2-3.4x slower on a minor
4
+ # release while every payload stayed byte-identical, and named the cause:
5
+ # "no es que haya regresiones - es que no hay nada que las detecte".
6
+ # This is the detector. The threshold, the repository and the gated command
7
+ # population are declared in `sourcecode.perf` and documented in
8
+ # `docs/perf/REGRESSION-GATE.md`; nothing here carries a number of its own.
9
+
10
+ on:
11
+ schedule:
12
+ # Nightly, after the day's merges have settled.
13
+ - cron: "0 3 * * *"
14
+ workflow_dispatch:
15
+ inputs:
16
+ baseline_ref:
17
+ description: "Baseline directory under docs/perf/baselines (default: gate-latest)"
18
+ required: false
19
+ default: "gate-latest"
20
+
21
+ concurrency:
22
+ group: perf-gate
23
+ cancel-in-progress: false
24
+
25
+ jobs:
26
+ gate:
27
+ runs-on: ubuntu-latest
28
+ timeout-minutes: 120
29
+ env:
30
+ # Declares the host class so nightly runs on ephemeral runners are
31
+ # comparable at all. Recorded in every artifact as `env.host_id_declared`,
32
+ # so the declaration is visible rather than silent.
33
+ SOURCECODE_PERF_HOST_ID: github-ubuntu-latest
34
+ BASELINE_DIR: docs/perf/baselines/${{ github.event.inputs.baseline_ref || 'gate-latest' }}
35
+
36
+ steps:
37
+ - name: Checkout
38
+ uses: actions/checkout@v4
39
+
40
+ - name: Setup Python
41
+ uses: actions/setup-python@v5
42
+ with:
43
+ python-version: "3.11"
44
+
45
+ - name: Install
46
+ run: |
47
+ python -m pip install --upgrade pip
48
+ pip install .
49
+
50
+ - name: Prove the gate is armed
51
+ # A green gate is evidence only when a red one is reachable in the same
52
+ # job with the same constants. This step fails if a synthetic 3x-slower
53
+ # cell would have passed.
54
+ run: python3 scripts/perf_gate.py --self-test
55
+
56
+ - name: Read the declared gate configuration
57
+ id: cfg
58
+ run: |
59
+ python3 scripts/perf_gate.py --print-config | tee gate-config.json
60
+ echo "repo_url=$(python3 -c "import json;print(json.load(open('gate-config.json'))['repository_url'])")" >> "$GITHUB_OUTPUT"
61
+ echo "repo=$(python3 -c "import json;print(json.load(open('gate-config.json'))['repository'])")" >> "$GITHUB_OUTPUT"
62
+ echo "mode=$(python3 -c "import json;print(json.load(open('gate-config.json'))['mode'])")" >> "$GITHUB_OUTPUT"
63
+ echo "runs=$(python3 -c "import json;print(json.load(open('gate-config.json'))['min_runs'])")" >> "$GITHUB_OUTPUT"
64
+ echo "commands=$(python3 -c "import json;print(' '.join(repr(c) for c in json.load(open('gate-config.json'))['commands']))")" >> "$GITHUB_OUTPUT"
65
+
66
+ - name: Clone the gate repository
67
+ run: |
68
+ mkdir -p fleet
69
+ git clone --depth 1 "${{ steps.cfg.outputs.repo_url }}" "fleet/${{ steps.cfg.outputs.repo }}"
70
+
71
+ - name: Measure
72
+ env:
73
+ PERF_FLEET_ROOT: fleet
74
+ run: |
75
+ python3 scripts/perf_harness.py \
76
+ --repos "${{ steps.cfg.outputs.repo }}" \
77
+ --commands ${{ steps.cfg.outputs.commands }} \
78
+ --modes "${{ steps.cfg.outputs.mode }}" \
79
+ --runs "${{ steps.cfg.outputs.runs }}" \
80
+ --fleet-root fleet \
81
+ --out perf-run
82
+
83
+ - name: Gate
84
+ run: |
85
+ python3 scripts/perf_gate.py \
86
+ --baseline "$BASELINE_DIR" \
87
+ --current perf-run \
88
+ --report perf-run/gate.json \
89
+ --table perf-run/RELEASE-TABLE.md
90
+
91
+ - name: Publish the measured table
92
+ if: always()
93
+ run: |
94
+ if [ -f perf-run/RELEASE-TABLE.md ]; then
95
+ {
96
+ echo "## Measured wall time per command"
97
+ echo
98
+ cat perf-run/RELEASE-TABLE.md
99
+ } >> "$GITHUB_STEP_SUMMARY"
100
+ fi
101
+
102
+ - name: Upload artifacts
103
+ if: always()
104
+ uses: actions/upload-artifact@v4
105
+ with:
106
+ name: perf-gate-${{ github.run_number }}
107
+ path: |
108
+ perf-run/**
109
+ gate-config.json
@@ -2,6 +2,253 @@
2
2
 
3
3
  ## [Unreleased]
4
4
 
5
+ ## [4.15.0] — 2026-08-10
6
+
7
+ **The Part 1 queue of Amendment O — the four rows field evaluation #18 opened,
8
+ one commit each, plus one row closed by measurement.** The fifth measurement of
9
+ the same repository at the same commit scored **8,0/10**, the highest of the
10
+ series, and it is the first round where **performance moves**: `spring-audit`
11
+ 2 377,9 → **816,0 s** (40 minutes to 13,6), the whole fast path under 16 s, and
12
+ the budget overshoot 5,66× → **1,94×**. It verified five of the previous
13
+ release's fixes from the outside. Every row it opened is a **residue of a fix
14
+ that landed**, which is what a fifth round on one subject produces.
15
+
16
+ **Fixed in this release:**
17
+
18
+ - **The heartbeat reports every unit; the clock still reads once per batch
19
+ (C3-82).** The field watched `1856/3342 java files` at 10,0 s, then **13,6
20
+ minutes with no line at all**, then `3328/3342`. C3-80 made the work emit
21
+ in-band and C3-73 gave the line its vocabulary, so the content was right —
22
+ what was wrong is that the only path to the emitter is
23
+ `RulePassProgress.tick()`, which returned early on a `done % sample_every`
24
+ remainder. A report falling between two boundaries 64 units apart is never
25
+ produced, so a stretch of expensive units is invisible for as long as it
26
+ lasts. One number was doing two jobs: the sampling constant belongs to the
27
+ **deadline** (a wall-clock budget buys no resolution from being asked 3 342
28
+ times instead of 52 — that is what took the overshoot to 1,94×) and not to the
29
+ **counter**, because `Progress` already throttles emission on an interval.
30
+ Asserted both ways: a thousand cheap units print at most one line, five units
31
+ that each outlast the interval print five.
32
+ - **A cut rule family names the stage it stopped in, and no stage claims a
33
+ population it did not finish (C3-81).** `rules_partially_run` published
34
+ `units_done: 3342, units_total: 3342` — a complete population, in a list
35
+ meaning *"this family did not finish"* — while `DEAD-001` returned 248
36
+ findings against 254 on the complete run. The `SEC-004` group walks four
37
+ populations in sequence (Java sources, configuration files, deployment
38
+ descriptors, MyBatis mappers) and the entry recorded whichever one held the
39
+ deadline; and the counter reported the unit it was *about to* process, so a
40
+ walk stopped at its own last file published a finished population. Every walk
41
+ now ticks with what it has **finished** and names itself, the entry carries
42
+ `stage_stopped_in` and a `units_basis` stating that the two numbers count the
43
+ stage rather than the family, and the `PARTIAL:` sentence carries the same
44
+ fact as the payload.
45
+ - **An inherited analysis budget says so, on the terminal and in the payload
46
+ (C3-83).** The same build answers 395 findings / 98 defects with no budget and
47
+ 267 / 11 with `ASK_MAX_ANALYSIS_SECONDS=420`. The truncation is declared
48
+ impeccably — `_partial`, `summary.partial`, `counts_are_floor`, a confidence
49
+ capped at `low` — and the variable is inherited from a shell or a CI runner,
50
+ so whoever reads `total_defects: 11` is routinely not whoever set the limit.
51
+ The budget now carries its origin verbatim from where it is read to where it
52
+ is published: the measured under-floor warning gains a line naming the
53
+ variable and its value, a budget **over** the floor prints a single provenance
54
+ line saying what a cut run publishes and how to get a complete audit, and
55
+ `_partial` carries `budget_source` beside `budget_seconds`. A value that does
56
+ not parse is not a budget and invents no source. The distinct exit code for a
57
+ partial answer and any renaming of a truncated total remain a published-contract
58
+ change (F-AV), deliberately not done here.
59
+
60
+ **Claims corrected:**
61
+
62
+ - **`--jobs` states which phase it does not cover (C3-84 / CL-18).** The
63
+ evaluation sampled the process and corrected four rounds of its own reporting:
64
+ parallelism exists and covers the phase that is not the cost — `threads=4` for
65
+ the first seconds (parsing), then `threads=1` with CPU/wall **0,97** for the
66
+ remaining ~99 % (the rule pass over a built IR), and on a warm cache there is
67
+ nothing left to parse at all. The help was true about what the flag does and
68
+ silent about what it does not, which is the half that decides whether setting
69
+ it is worth anything. `JOBS_OPTION_HELP` — the one string every command
70
+ declares the flag with — now says both; the README and the user guide are
71
+ qualifications of that claim rather than three versions of it; F-AQ's promise
72
+ (byte-identical at any value) is untouched. Making the rule pass itself
73
+ parallel is F-AT.
74
+
75
+ **Measured, not assumed:**
76
+
77
+ - **The three commands the field reports as regressed are flat here, for the
78
+ second consecutive A/B (C3-76c).** A/B/C of 4.10.7, 4.12.0 and HEAD on
79
+ BroadleafCommerce, each side with its own `HOME` and both cache roots, each
80
+ command warmed and then timed in isolation: `validation` 5,72 / 5,68 / 5,68 s,
81
+ `endpoints` 1,49 / 1,48 / 1,48 s, `posture --diff` 2,87 / 2,86 / 2,85 s. The
82
+ field measures the same three at 14,0 → 35,8 → 41,8 s, 3,5 → 4,2 → 4,7 s and
83
+ 10,5 → 27,6 → 32,8 s. A regression that reproduces on one platform and not the
84
+ other cannot be bisected from the platform where both sides are equal; the
85
+ row's only open item is the Windows runner (F-AW).
86
+
87
+ **Documentation:**
88
+
89
+ The front-page catch-up written after 4.14.0 ships here too — no code, no
90
+ `--help`, no output changed by it:
91
+
92
+ - **README stated a budget rule the product stopped following in 4.10.6.**
93
+ `ASK_MAX_ANALYSIS_SECONDS` was described as failing a repo-wide/deep command
94
+ before it starts when the value is below the class floor; C3-55 made the floor
95
+ advice and the budget honoured, and C3-79 moved the cut inside the rule family.
96
+ The paragraph now says what the code does: below the floor it warns and runs,
97
+ a cut publishes `rules_partially_run` / `rules_not_run` / `_partial`, and the
98
+ answer marks itself with `summary.partial`, `counts_are_floor`, `counts_basis`
99
+ and a `confidence_level` capped at `low` (C2-31).
100
+ - **`--no-write` / `ASK_READONLY=1` (F-AS, 4.13.0) reached the README**, beside
101
+ the third-party-audit note that is its audience. The list of what writes into a
102
+ repository is left to `ask --help`, which generates it from
103
+ `cli.COMMANDS_THAT_WRITE`, rather than copied into a second catalogue.
104
+ - **`--jobs` / `-j` / `ASK_JOBS` (F-AQ) and the in-band heartbeat (C3-80)** added
105
+ to the large-repo controls; `verify --allow-unverified` with its named
106
+ `unverified_reason` (C3-75) added to the gate-adoption note; the `spring-audit`
107
+ row now names the rule inventory fields (C1-42).
108
+ - **`docs/USER_GUIDE.md`**: the budget section still described a run stopping
109
+ *between phases* (4.12.0); it now describes the in-family cut. The flags table
110
+ gained the rows for `--jobs`, `--no-write` and `--progress`.
111
+
112
+ - `docs/DEFECT-LEDGER.md` — rows C3-81, C3-82, C3-83, C3-84, claim CL-18 and
113
+ measurement C3-76c, with the five rows 4.14.0 closed marked verified in the
114
+ field; `docs/DEVELOPMENT-ROADMAP.md` — the eval #18 phase update;
115
+ `.planning/ROADMAP-STRATEGIC-2026-07-28.md` — **Amendment O**, which
116
+ respecifies F-AT from the field's own analysis: the unit of parallelism is the
117
+ **file inside the per-file families**, the reduction is the
118
+ `(category, defect_kind, symbol)` identity `defect_identity` already
119
+ publishes, and graph-scope families stay in a serial tail.
120
+
121
+ **No behaviour changed for a complete run.** Answers stay byte-identical; what
122
+ moved is the heartbeat's cadence, the metadata of a truncated run, and what the
123
+ surface claims about `--jobs`.
124
+
125
+ ## [4.14.0] — 2026-08-09
126
+
127
+ **The Part 1 queue of Amendment N — the four rows field evaluation #17 opened,
128
+ one commit each.** The fourth measurement of the same repository at the same
129
+ commit scored **7,5/10**, the highest of the series, and verified six of the
130
+ previous release's fixes from the outside. Both rows it opened are in the fields
131
+ that describe ASK's *own* reliability, which is where this product can least
132
+ afford to be wrong.
133
+
134
+ **Fixed in this release:**
135
+
136
+ - **A truncated answer no longer raises its own confidence (C2-31).** Three
137
+ complete runs published 395 findings / 98 defects at `confidence_level:
138
+ medium`; the run the budget cut published 289 / 15 at **`high`**, because the
139
+ level is derived from the confidence of the high/critical findings *that
140
+ exist* and the family contributing the medium-confidence ones is the family
141
+ that did not run. `SpringAuditResult.partial` is now one flag — set by the
142
+ scopes, by the CLI for a phase that never started, and carried through
143
+ `merge` — and a partial answer is capped at `low` with `confidence_basis`
144
+ saying the cut is the reason. `summary` gains `partial`, `counts_are_floor`
145
+ and `counts_basis`, so the mark lives where the numbers a consumer reads are,
146
+ not only in `_partial` at the root. The cap is a ceiling and never a floor: a
147
+ complete run keeps its level and gains no fields.
148
+ - **The rule inventory names rules, and both scopes' (C1-42).** `rules_run`
149
+ listed four SEC ids in a payload whose findings carried DEAD-001, SEC-008,
150
+ TX-006, TX-001, SEC-005 and SEC-006, and `rules_not_run` said `[GATE-001]`
151
+ where the arithmetic proves GATE-004 did not run either. The lists were keyed
152
+ on the pattern *object's* identity, so a family emitting six rules stood for
153
+ itself, and `merge` overwrote the TX scope's inventory with the security
154
+ scope's. `rule_pass.rule_ids_of()` is the one authority, the two lists are
155
+ unioned across scopes, and `rules_run_count` / `rules_total` sit beside them.
156
+ Three invariants are asserted over a real audit: every rule that fired is in
157
+ `rules_run`, the lists never overlap, and a complete `--scope all` run
158
+ inventories exactly `rule_catalog.ids()`.
159
+ - **The heartbeat is emitted by the work, not only by a thread (C3-80).** Four
160
+ versions with the same shape: one line at `elapsed=20.1s`, 39 minutes of
161
+ nothing, then the same stage text seconds before the end. A line-mode
162
+ heartbeat printed only by a daemon thread depends on that thread being
163
+ scheduled during exactly the CPU-bound stretch the operator is asking about.
164
+ `Progress._emit()` is now one seam with one throttle and two callers — the
165
+ loop on its timer and the analysis in-band — sharing one `_last_emit` stamp,
166
+ so the line rate is unchanged and a running analysis is always heard from.
167
+ - **The budget cuts inside a rule family (C3-79).** Budget 420 s, elapsed
168
+ 2 376 s: `exhausted()` was asked on a whole-family boundary and one family
169
+ lasts 39 minutes. `RulePassProgress.tick()` reports counted work and answers
170
+ *"is the time spent"* in one call, sampling the clock once per 64 units; five
171
+ families that walk a population take a `FamilyBudget` and stop on a batch
172
+ boundary. A family cut in flight is in neither list — it is
173
+ `rules_partially_run` with the count it reached, and the findings it produced
174
+ are kept, because they were measured. Measured on BroadleafCommerce: a 4,5 s
175
+ budget stops at 1 408 of 2 766 Java files and ends at 5,1 s.
176
+
177
+ **Verified in the field, not changed here:** `verify` exiting 2 without contracts
178
+ is C3-75's deliberate half (the waiver `--allow-unverified` and the named
179
+ `unverified_reason` are the fix; a distinct code is a contract change, F-AV), and
180
+ the 4.10.7 performance that never came back is C3-76, which does not reproduce on
181
+ this platform and waits on the Windows runner (F-AW).
182
+
183
+ Suite 7 787.
184
+
185
+ ## [4.13.0] — 2026-08-08
186
+
187
+ **The capability queue of Amendment M — the four features field evaluation #16
188
+ asked for, one commit each, after Part 1 closed in 4.12.0.** The evaluation's
189
+ verdict on engineering was *"no es que haya regresiones — es que no hay nada que
190
+ las detecte"*, and its "if you could only do two things" was F-AP and F-AQ, in
191
+ that order. Both ship here, with F-AR and F-AS beside them.
192
+
193
+ **New in this release:**
194
+
195
+ - **A release performance gate (F-AP).** `perf.gate_report()` turns a whole run
196
+ into one verdict against a whole baseline, and three of its four outcomes are
197
+ not a pass: a cell over the threshold **fails**, a baselined cell this run did
198
+ not measure **fails** (silence is how "nothing detects a regression" happens),
199
+ and a cell under the ADR-0006 sample floor **fails**. `scripts/perf_gate.py
200
+ --self-test` proves the gate is armed by failing a synthetic 3×-slower cell —
201
+ CI runs it *before* it runs the measurement, because a green gate is evidence
202
+ only when a red one is reachable on the same constants. Threshold **20 %**,
203
+ warm mode, one ~3 000-file repository, six repository-wide commands, and the
204
+ three exclusions published with every verdict. All of it lives in
205
+ `sourcecode.perf`; `docs/perf/REGRESSION-GATE.md` embeds `--print-config`'s
206
+ output verbatim and a test asserts they are the same bytes.
207
+ - **The measured times are published, generated (F-AP, second rider).**
208
+ `perf.release_table()` builds the per-command / per-repository-scale table a
209
+ release note carries, from the run's own artifacts. An axis that was not
210
+ measured prints `unknown`, never `0`. And `cache model`'s figures now name the
211
+ build they were measured on (3.2.2) beside the build you are running, so a
212
+ table nine releases old cannot read as this build's measurement.
213
+ - **`--jobs N` / `-j` / `ASK_JOBS` (F-AQ)**, default `cpu_count() - 1`. The
214
+ fourth consecutive evaluation to ask for parallelism was the first to sample
215
+ it: `threads=1`, `CPU/wall = 0,92…0,95`, 54 minutes, 20 cores. Worker
216
+ processes now parse files into the *same* content-addressed cache the IR loop
217
+ is about to read, so the loop is untouched and **byte-identity is structural,
218
+ not inspected** — no worker output reaches the payload by any route. Measured
219
+ on 2 766 Java files, both sides parse-cold with their own cache root: 5,36 s →
220
+ 3,46 s (**1,55×**), CPU/wall 2,07, IR hash identical. Every failure mode — no
221
+ pool, a faulting worker, a frozen build, a disabled cache, a repository under
222
+ the 200-file floor — degrades to today's sequential parse and returns a receipt
223
+ naming the reason.
224
+ - **`ASK_PARSE_CACHE_MAX_MB` (F-AR)**, default **512 MB**, least-recently-used,
225
+ enforced on write and published in `cache status` beside the size it bounds.
226
+ C3-70 retires the generation that can never be read again — an exact rule, and
227
+ exact rules only cover what they can foresee. This bounds what they cannot:
228
+ many repositories, many branches, one machine, and an owner who never runs
229
+ `ask cache clear`. Reads refresh recency (hourly granularity, so a hit is not a
230
+ disk write), an entry and its body-fact blob are evicted together, and
231
+ `ASK_PARSE_CACHE_MAX_MB=0` turns the guard off deliberately and says so.
232
+ - **`--no-write` / `ASK_READONLY=1` (F-AS)** — nothing is created inside the
233
+ analysed repository, and a command that cannot answer without writing says so
234
+ instead of writing, in the same error envelope every other refusal uses.
235
+ Accepted by **every** command (consumed before the parser, the `--detach`
236
+ precedent), because a mode five commands accept and seventy-nine reject is a
237
+ mode whose one refusing run is the run that writes. Each refusal is announced
238
+ once on stderr with its path. Shared caches outside the repository are
239
+ untouched — an auditor is protecting a checkout, not a home directory.
240
+ - **`ask --help` names every command that writes into the repository**, with the
241
+ condition beside it ("only with `--snapshot`"), generated from one authority.
242
+
243
+ **Measured, not fixed, and said so:** the second half of F-AQ — *"one audit per
244
+ run, shared by the compositions"* — was measured before being touched.
245
+ Instrumenting `build_risk` on a real repository counts `run_tx_audit` **1×** and
246
+ `run_security_audit` **1×**: `risk` already hands its findings to every impact
247
+ chain it composes (C3-42-b), so the duplication the field named is between two
248
+ *processes*, not inside one. That needs a persisted audit keyed on the worktree
249
+ signature, and it is not in this release. What ships is the regression test that
250
+ keeps the in-run property true.
251
+
5
252
  ## [4.12.0] — 2026-08-08
6
253
 
7
254
  **Field evaluation #16 — the third round on the same repository and commit, and the
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: sourcecode
3
- Version: 4.12.0
3
+ Version: 4.15.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
@@ -42,7 +42,7 @@ Description-Content-Type: text/markdown
42
42
 
43
43
  **Context · Impact · Migration · Architecture · Review — everything from one structural model.**
44
44
 
45
- ![Version](https://img.shields.io/badge/version-4.12.0-blue)
45
+ ![Version](https://img.shields.io/badge/version-4.15.0-blue)
46
46
  ![Python](https://img.shields.io/badge/python-3.9%2B-green)
47
47
 
48
48
  > **ASK Engine** is the product. The CLI command is **`ask`**. The legacy **`sourcecode`**
@@ -76,13 +76,31 @@ With the right command class, ASK Engine becomes **constant infrastructure** ins
76
76
  **Large-repo controls.** Pass `--progress stderr` (or `--progress file:run.log`)
77
77
  for line heartbeats in a non-TTY supervised run — with the file being read so
78
78
  far and an ETA for the stage being measured. `ASK_PROGRESS` sets the same thing
79
- in the environment. Long repo-wide/deep runs also write durable records under
80
- `~/.sourcecode/runs/<repo-hash>/` by default, not inside the audited repository;
81
- set `ASK_RUNS_IN_REPO=1` only when repo-local `.ask/runs` records are intentional.
82
- Set `ASK_MAX_ANALYSIS_SECONDS=<seconds>` to fail before starting a repo-wide/deep
83
- command whose configured budget is below its safe floor. Use
84
- `ask audit-report --from-risk risk.json` to package an existing risk run instead
85
- of recomputing it.
79
+ in the environment, and the heartbeat is emitted by the analysis itself, not only
80
+ by a timer thread, so a CPU-bound stretch is never silent. `--jobs N` / `-j`
81
+ (env `ASK_JOBS`) sets the worker processes that parse files — default CPU count
82
+ 1; parallelism only warms the content-addressed parse cache, so the answer is
83
+ byte-identical at any value. It does **not** parallelise the rule pass, which is
84
+ where a repository-wide audit spends most of its time, and a warm cache leaves it
85
+ nothing to parse — so raising it there buys nothing. Long repo-wide/deep runs also write durable records
86
+ under `~/.sourcecode/runs/<repo-hash>/` by default, not inside the audited
87
+ repository; set `ASK_RUNS_IN_REPO=1` only when repo-local `.ask/runs` records are
88
+ intentional. Use `ask audit-report --from-risk risk.json` to package an existing
89
+ risk run instead of recomputing it.
90
+
91
+ **A budget is honoured, never a veto.** `ASK_MAX_ANALYSIS_SECONDS=<seconds>`
92
+ bounds a repo-wide/deep command. A value below the class floor prints what that
93
+ class typically needs and **runs anyway** — refusing to answer is the opposite of
94
+ this product's doctrine. A run that spends its budget stops on the loop that is
95
+ spending the time, not only between phases: a rule family cut in flight is
96
+ published as `rules_partially_run` with how far it reached, families that never
97
+ started are named in `rules_not_run`, `_partial` names the phases that completed
98
+ and the ones that did not, and the findings measured before the cut are kept.
99
+ The answer marks itself where the numbers are — `summary.partial`,
100
+ `counts_are_floor`, `counts_basis` — and `confidence_level` is capped at `low`,
101
+ because the confidence of the findings that exist says nothing about the family
102
+ that did not run. Measured on BroadleafCommerce (2 766 Java files): a 4.5s budget
103
+ stops at 1 408 files and ends at 5.1s.
86
104
 
87
105
  **What a warm actually covers.** `ask cache warm` runs the compact analysis: it rebuilds the
88
106
  shared structural layers (L1/L2 + the Repository Intelligence Snapshot + the shared Canonical
@@ -108,7 +126,7 @@ brew tap haroundominique/sourcecode && brew install sourcecode
108
126
  # pip / pipx
109
127
  pipx install sourcecode # or: pip install sourcecode
110
128
 
111
- ask version # ask 4.12.0 — and, on a build that has aged,
129
+ ask version # ask 4.15.0 — and, on a build that has aged,
112
130
  # how many releases have probably shipped since
113
131
  ```
114
132
 
@@ -204,6 +222,9 @@ ask verify /path/to/repo # then: only new violations block
204
222
  > A repository that starts declaring contracts already violates them somewhere; `ask verify`
205
223
  > is **baseline-relative by default** (`--fail-on new`) so the gate survives contact with
206
224
  > reality instead of being switched off on day one.
225
+ > A pipeline wired before the contracts exist exits 2 (`unverified`, with
226
+ > `unverified_reason` naming which state it is); `--allow-unverified` exits 0 while the
227
+ > verdict stays `unverified` — the declared form of `|| true`, and violations still block.
207
228
  > `ask baseline capture|diff|trend` is a different thing: versioned architectural metrics over
208
229
  > time, for trend reporting rather than blocking.
209
230
 
@@ -324,7 +345,7 @@ from it.
324
345
  | `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 |
325
346
  | `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). With nothing declared, `ask data-exposure /path/to/repo` answers `answered: false` and hands back the file, the key and an example to declare — it never reports zero exposed routes |
326
347
  | `endpoints` | core | every REST endpoint, effective path, security policy, confidence | Spring MVC + JAX-RS (~65 % recall on JAX-RS sub-resource locators). `--compact` answers the exposure census without the rows; `--servlets` lists the servlet-mounted surface as its own population; `--client-usage` says which routes the TS/JS client in this repository actually calls |
327
- | `spring-audit` | core | transactional anomalies + security configuration/exposure + validation gaps | `--ci`, `-f github-comment`; `--table --rule SEC-008 --top-n 20` for human-scale review |
348
+ | `spring-audit` | core | transactional anomalies + security configuration/exposure + validation gaps | `--ci`, `-f github-comment`; `--table --rule SEC-008 --top-n 20` for human-scale review. Every run inventories its own rules — `rules_run`, `rules_not_run`, `rules_partially_run`, `rules_run_count`/`rules_total` — so "all of them" is a fact, not an assumption |
328
349
  | `migrate-check` | core | Boot 2→3 readiness + Java LTS/licensing inventory: located blockers, per-dimension score, effort, detected Java 8/11/17/21/25 evidence and explicit licensing-review signals | `--target-jdk 25` sets the target LTS route; `--blast-radius` orders the re-test plan; `--table --rule MIG-001 --band critical --top-n 20` for blocker triage |
329
350
  | `impact` / `impact-chain` | core | blast radius of a change, to the endpoints it reaches | target the **interface**, not the `Impl` |
330
351
  | `pr-impact` | core | the same, scoped to a PR diff | gating command: `--fail-on`, exit codes |
@@ -499,6 +520,25 @@ range, and errors: **no source code, paths, secrets, or output**. Turn it off ag
499
520
  > default you must remember to disable is the wrong default for third-party code. An explicit
500
521
  > choice you made before is unchanged.
501
522
 
523
+ **A question is not a write — `--no-write` / `ASK_READONLY=1`.** One contract over
524
+ every command: nothing is created inside the analysed repository, and a command
525
+ that cannot answer without writing says so instead of writing. A refusal is never
526
+ silent — each one names the path that was not created, on stderr. The scope is the
527
+ tree you pointed at; the shared caches under `~/.sourcecode` and an `--output` path
528
+ elsewhere on the machine are not refused, because refusing them would make the mode
529
+ unusable without making it safer.
530
+
531
+ Most commands read only, and the few that create anything inside the repository do
532
+ it under `.ask/` and only behind an explicit flag (`baseline`, `migrate-check
533
+ --history`, `verify --update-baseline`, `verify-edit --install-hook`, and `.ask/runs`
534
+ when `ASK_RUNS_IN_REPO=1`). `ask --help` prints that list in full, generated from the
535
+ one authority the battery checks — a write seam added without a row there fails the
536
+ suite.
537
+
538
+ ```bash
539
+ ask spring-audit /path/to/client-repo --no-write -o audit.json
540
+ ```
541
+
502
542
  **Custom security annotations.** Teach `endpoints`, `spring-audit`, and `explain` about
503
543
  project-specific authorization annotations via an optional `sourcecode.config.json` at the
504
544
  repo root (otherwise they report `policy: "none_detected"`):
@@ -4,7 +4,7 @@
4
4
 
5
5
  **Context · Impact · Migration · Architecture · Review — everything from one structural model.**
6
6
 
7
- ![Version](https://img.shields.io/badge/version-4.12.0-blue)
7
+ ![Version](https://img.shields.io/badge/version-4.15.0-blue)
8
8
  ![Python](https://img.shields.io/badge/python-3.9%2B-green)
9
9
 
10
10
  > **ASK Engine** is the product. The CLI command is **`ask`**. The legacy **`sourcecode`**
@@ -38,13 +38,31 @@ With the right command class, ASK Engine becomes **constant infrastructure** ins
38
38
  **Large-repo controls.** Pass `--progress stderr` (or `--progress file:run.log`)
39
39
  for line heartbeats in a non-TTY supervised run — with the file being read so
40
40
  far and an ETA for the stage being measured. `ASK_PROGRESS` sets the same thing
41
- in the environment. Long repo-wide/deep runs also write durable records under
42
- `~/.sourcecode/runs/<repo-hash>/` by default, not inside the audited repository;
43
- set `ASK_RUNS_IN_REPO=1` only when repo-local `.ask/runs` records are intentional.
44
- Set `ASK_MAX_ANALYSIS_SECONDS=<seconds>` to fail before starting a repo-wide/deep
45
- command whose configured budget is below its safe floor. Use
46
- `ask audit-report --from-risk risk.json` to package an existing risk run instead
47
- of recomputing it.
41
+ in the environment, and the heartbeat is emitted by the analysis itself, not only
42
+ by a timer thread, so a CPU-bound stretch is never silent. `--jobs N` / `-j`
43
+ (env `ASK_JOBS`) sets the worker processes that parse files — default CPU count
44
+ 1; parallelism only warms the content-addressed parse cache, so the answer is
45
+ byte-identical at any value. It does **not** parallelise the rule pass, which is
46
+ where a repository-wide audit spends most of its time, and a warm cache leaves it
47
+ nothing to parse — so raising it there buys nothing. Long repo-wide/deep runs also write durable records
48
+ under `~/.sourcecode/runs/<repo-hash>/` by default, not inside the audited
49
+ repository; set `ASK_RUNS_IN_REPO=1` only when repo-local `.ask/runs` records are
50
+ intentional. Use `ask audit-report --from-risk risk.json` to package an existing
51
+ risk run instead of recomputing it.
52
+
53
+ **A budget is honoured, never a veto.** `ASK_MAX_ANALYSIS_SECONDS=<seconds>`
54
+ bounds a repo-wide/deep command. A value below the class floor prints what that
55
+ class typically needs and **runs anyway** — refusing to answer is the opposite of
56
+ this product's doctrine. A run that spends its budget stops on the loop that is
57
+ spending the time, not only between phases: a rule family cut in flight is
58
+ published as `rules_partially_run` with how far it reached, families that never
59
+ started are named in `rules_not_run`, `_partial` names the phases that completed
60
+ and the ones that did not, and the findings measured before the cut are kept.
61
+ The answer marks itself where the numbers are — `summary.partial`,
62
+ `counts_are_floor`, `counts_basis` — and `confidence_level` is capped at `low`,
63
+ because the confidence of the findings that exist says nothing about the family
64
+ that did not run. Measured on BroadleafCommerce (2 766 Java files): a 4.5s budget
65
+ stops at 1 408 files and ends at 5.1s.
48
66
 
49
67
  **What a warm actually covers.** `ask cache warm` runs the compact analysis: it rebuilds the
50
68
  shared structural layers (L1/L2 + the Repository Intelligence Snapshot + the shared Canonical
@@ -70,7 +88,7 @@ brew tap haroundominique/sourcecode && brew install sourcecode
70
88
  # pip / pipx
71
89
  pipx install sourcecode # or: pip install sourcecode
72
90
 
73
- ask version # ask 4.12.0 — and, on a build that has aged,
91
+ ask version # ask 4.15.0 — and, on a build that has aged,
74
92
  # how many releases have probably shipped since
75
93
  ```
76
94
 
@@ -166,6 +184,9 @@ ask verify /path/to/repo # then: only new violations block
166
184
  > A repository that starts declaring contracts already violates them somewhere; `ask verify`
167
185
  > is **baseline-relative by default** (`--fail-on new`) so the gate survives contact with
168
186
  > reality instead of being switched off on day one.
187
+ > A pipeline wired before the contracts exist exits 2 (`unverified`, with
188
+ > `unverified_reason` naming which state it is); `--allow-unverified` exits 0 while the
189
+ > verdict stays `unverified` — the declared form of `|| true`, and violations still block.
169
190
  > `ask baseline capture|diff|trend` is a different thing: versioned architectural metrics over
170
191
  > time, for trend reporting rather than blocking.
171
192
 
@@ -286,7 +307,7 @@ from it.
286
307
  | `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 |
287
308
  | `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). With nothing declared, `ask data-exposure /path/to/repo` answers `answered: false` and hands back the file, the key and an example to declare — it never reports zero exposed routes |
288
309
  | `endpoints` | core | every REST endpoint, effective path, security policy, confidence | Spring MVC + JAX-RS (~65 % recall on JAX-RS sub-resource locators). `--compact` answers the exposure census without the rows; `--servlets` lists the servlet-mounted surface as its own population; `--client-usage` says which routes the TS/JS client in this repository actually calls |
289
- | `spring-audit` | core | transactional anomalies + security configuration/exposure + validation gaps | `--ci`, `-f github-comment`; `--table --rule SEC-008 --top-n 20` for human-scale review |
310
+ | `spring-audit` | core | transactional anomalies + security configuration/exposure + validation gaps | `--ci`, `-f github-comment`; `--table --rule SEC-008 --top-n 20` for human-scale review. Every run inventories its own rules — `rules_run`, `rules_not_run`, `rules_partially_run`, `rules_run_count`/`rules_total` — so "all of them" is a fact, not an assumption |
290
311
  | `migrate-check` | core | Boot 2→3 readiness + Java LTS/licensing inventory: located blockers, per-dimension score, effort, detected Java 8/11/17/21/25 evidence and explicit licensing-review signals | `--target-jdk 25` sets the target LTS route; `--blast-radius` orders the re-test plan; `--table --rule MIG-001 --band critical --top-n 20` for blocker triage |
291
312
  | `impact` / `impact-chain` | core | blast radius of a change, to the endpoints it reaches | target the **interface**, not the `Impl` |
292
313
  | `pr-impact` | core | the same, scoped to a PR diff | gating command: `--fail-on`, exit codes |
@@ -461,6 +482,25 @@ range, and errors: **no source code, paths, secrets, or output**. Turn it off ag
461
482
  > default you must remember to disable is the wrong default for third-party code. An explicit
462
483
  > choice you made before is unchanged.
463
484
 
485
+ **A question is not a write — `--no-write` / `ASK_READONLY=1`.** One contract over
486
+ every command: nothing is created inside the analysed repository, and a command
487
+ that cannot answer without writing says so instead of writing. A refusal is never
488
+ silent — each one names the path that was not created, on stderr. The scope is the
489
+ tree you pointed at; the shared caches under `~/.sourcecode` and an `--output` path
490
+ elsewhere on the machine are not refused, because refusing them would make the mode
491
+ unusable without making it safer.
492
+
493
+ Most commands read only, and the few that create anything inside the repository do
494
+ it under `.ask/` and only behind an explicit flag (`baseline`, `migrate-check
495
+ --history`, `verify --update-baseline`, `verify-edit --install-hook`, and `.ask/runs`
496
+ when `ASK_RUNS_IN_REPO=1`). `ask --help` prints that list in full, generated from the
497
+ one authority the battery checks — a write seam added without a row there fails the
498
+ suite.
499
+
500
+ ```bash
501
+ ask spring-audit /path/to/client-repo --no-write -o audit.json
502
+ ```
503
+
464
504
  **Custom security annotations.** Teach `endpoints`, `spring-audit`, and `explain` about
465
505
  project-specific authorization annotations via an optional `sourcecode.config.json` at the
466
506
  repo root (otherwise they report `policy: "none_detected"`):
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "sourcecode"
7
- version = "4.12.0"
7
+ version = "4.15.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"