sourcecode 5.3.1__tar.gz → 5.4.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 (357) hide show
  1. {sourcecode-5.3.1 → sourcecode-5.4.0}/CHANGELOG.md +98 -0
  2. {sourcecode-5.3.1 → sourcecode-5.4.0}/PKG-INFO +3 -3
  3. {sourcecode-5.3.1 → sourcecode-5.4.0}/README.md +2 -2
  4. sourcecode-5.4.0/docs/CACHE.md +180 -0
  5. sourcecode-5.4.0/docs/COMMERCIAL-OFFER.md +115 -0
  6. sourcecode-5.4.0/docs/CUSTOMER-VALIDATION.md +202 -0
  7. sourcecode-5.4.0/docs/DEFECT-LEDGER.md +444 -0
  8. sourcecode-5.4.0/docs/DEMO-5MIN.md +134 -0
  9. sourcecode-5.4.0/docs/DEVELOPMENT-ROADMAP.md +2818 -0
  10. sourcecode-5.4.0/docs/EXECUTION-PLAN-12MO.md +173 -0
  11. sourcecode-5.4.0/docs/EXECUTIVE-ROADMAP.md +182 -0
  12. sourcecode-5.4.0/docs/MANUAL-USUARIO.md +1035 -0
  13. sourcecode-5.4.0/docs/MODERNIZATION.md +82 -0
  14. sourcecode-5.4.0/docs/PRODUCT_AUDIT.md +170 -0
  15. sourcecode-5.4.0/docs/PRODUCT_IDENTITY.md +106 -0
  16. sourcecode-5.4.0/docs/PRODUCT_TIERS.md +188 -0
  17. sourcecode-5.4.0/docs/RC1-CHECKLIST.md +62 -0
  18. sourcecode-5.4.0/docs/RELEASE-CHECKLIST.md +94 -0
  19. sourcecode-5.4.0/docs/USER_GUIDE.md +1511 -0
  20. sourcecode-5.4.0/docs/architecture/CATALOG-retrieval-intents.md +420 -0
  21. sourcecode-5.4.0/docs/architecture/DESIGN-knowledge-provider-integration.md +134 -0
  22. sourcecode-5.4.0/docs/architecture/DESIGN-p5.3b-statement-surface.md +505 -0
  23. sourcecode-5.4.0/docs/architecture/DESIGN-p5.5-span-index.md +533 -0
  24. sourcecode-5.4.0/docs/architecture/DESIGN-p6-semantic-impact-engine.md +95 -0
  25. sourcecode-5.4.0/docs/architecture/DESIGN-p6-semantic-integration-engine.md +89 -0
  26. sourcecode-5.4.0/docs/architecture/DESIGN-p7-semantic-services.md +177 -0
  27. sourcecode-5.4.0/docs/architecture/DESIGN-robustness-security-inference.md +423 -0
  28. sourcecode-5.4.0/docs/architecture/DESIGN-semantic-retrieval.md +492 -0
  29. sourcecode-5.4.0/docs/architecture/EPV-p6-class-typeref.md +103 -0
  30. sourcecode-5.4.0/docs/architecture/REPORT-p6-flow-analyzer-comparison.md +201 -0
  31. sourcecode-5.4.0/docs/architecture/REPORT-p6-integration-detector-comparison.md +121 -0
  32. sourcecode-5.4.0/docs/architecture/REPORT-p8-flow-analyzer-migration.md +157 -0
  33. sourcecode-5.4.0/docs/architecture/REPORT-p9-integration-detector-migration.md +151 -0
  34. sourcecode-5.4.0/docs/architecture/adr/0001-semantic-ir.md +890 -0
  35. sourcecode-5.4.0/docs/architecture/adr/0002-source-evidence-boundary.md +256 -0
  36. sourcecode-5.4.0/docs/architecture/adr/0003-architectural-characterization.md +107 -0
  37. sourcecode-5.4.0/docs/architecture/adr/0004-semantic-retrieval.md +177 -0
  38. sourcecode-5.4.0/docs/architecture/adr/0005-evidence-reconciliation.md +418 -0
  39. sourcecode-5.4.0/docs/architecture/adr/0006-performance-harness.md +133 -0
  40. sourcecode-5.4.0/docs/architecture/adr/0007-composition-semantics.md +437 -0
  41. sourcecode-5.4.0/docs/architecture/adr/0008-answer-coherence.md +180 -0
  42. sourcecode-5.4.0/docs/architecture/consumer-disposition-inventory.md +137 -0
  43. sourcecode-5.4.0/docs/architecture/overview.md +49 -0
  44. sourcecode-5.4.0/docs/architecture/product-architecture-review.md +209 -0
  45. sourcecode-5.4.0/docs/architecture/product-strategy-layering.md +167 -0
  46. sourcecode-5.4.0/docs/architecture/semantic-ir-consumer-matrix.md +110 -0
  47. sourcecode-5.4.0/docs/architecture/semantic-ir-roadmap.md +299 -0
  48. sourcecode-5.4.0/docs/baseline-ci.yml +82 -0
  49. sourcecode-5.4.0/docs/commercial-pipeline-audit.md +142 -0
  50. sourcecode-5.4.0/docs/contracts-ci.yml +51 -0
  51. sourcecode-5.4.0/docs/contracts.md +313 -0
  52. sourcecode-5.4.0/docs/eval/2026-06-15-petclinic-rest-issue11-vets-pagination.md +47 -0
  53. sourcecode-5.4.0/docs/eval/2026-06-15-petclinic-rest-issue147-validation.md +93 -0
  54. sourcecode-5.4.0/docs/eval/2026-06-15-petclinic-rest-workflow.md +122 -0
  55. sourcecode-5.4.0/docs/eval/2026-06-15-phase18-openapi-surface.md +47 -0
  56. sourcecode-5.4.0/docs/eval/2026-06-15-phase20-validation-surface.md +48 -0
  57. sourcecode-5.4.0/docs/eval/2026-06-16-broadleaf-checkout-impact-fieldtest.md +106 -0
  58. sourcecode-5.4.0/docs/eval/2026-06-16-petclinic-rest-issue11-weakness2-closed.md +71 -0
  59. sourcecode-5.4.0/docs/eval/2026-06-16-spring-petclinic-issue2333-dead-vets.md +146 -0
  60. sourcecode-5.4.0/docs/licensing-schema.md +78 -0
  61. sourcecode-5.4.0/docs/migrate-check.md +363 -0
  62. sourcecode-5.4.0/docs/perf/README.md +63 -0
  63. sourcecode-5.4.0/docs/perf/REGRESSION-GATE.md +274 -0
  64. sourcecode-5.4.0/docs/perf/baselines/2.5.15/SUMMARY.md +68 -0
  65. sourcecode-5.4.0/docs/perf/baselines/2.5.15/alfresco__ask__cold.json +52 -0
  66. sourcecode-5.4.0/docs/perf/baselines/2.5.15/alfresco__ask__warm.json +40 -0
  67. sourcecode-5.4.0/docs/perf/baselines/2.5.15/broadleaf__ask__cold.json +52 -0
  68. sourcecode-5.4.0/docs/perf/baselines/2.5.15/broadleaf__ask__warm.json +40 -0
  69. sourcecode-5.4.0/docs/perf/baselines/2.5.15/eureka__ask__cold.json +52 -0
  70. sourcecode-5.4.0/docs/perf/baselines/2.5.15/eureka__ask__warm.json +40 -0
  71. sourcecode-5.4.0/docs/perf/baselines/2.5.15/jenkins__ask__cold.json +52 -0
  72. sourcecode-5.4.0/docs/perf/baselines/2.5.15/jenkins__ask__warm.json +40 -0
  73. sourcecode-5.4.0/docs/perf/baselines/2.5.15/jobrunr__ask__cold.json +52 -0
  74. sourcecode-5.4.0/docs/perf/baselines/2.5.15/jobrunr__ask__warm.json +40 -0
  75. sourcecode-5.4.0/docs/perf/baselines/2.5.15/keycloak__ask__cold.json +52 -0
  76. sourcecode-5.4.0/docs/perf/baselines/2.5.15/keycloak__ask__warm.json +40 -0
  77. sourcecode-5.4.0/docs/perf/baselines/2.5.15/neo4j__ask__cold.json +52 -0
  78. sourcecode-5.4.0/docs/perf/baselines/2.5.15/neo4j__ask__warm.json +40 -0
  79. sourcecode-5.4.0/docs/perf/baselines/2.5.15/ofbiz__ask__cold.json +52 -0
  80. sourcecode-5.4.0/docs/perf/baselines/2.5.15/ofbiz__ask__warm.json +40 -0
  81. sourcecode-5.4.0/docs/perf/baselines/2.5.15/openmrs__ask__cold.json +52 -0
  82. sourcecode-5.4.0/docs/perf/baselines/2.5.15/openmrs__ask__warm.json +40 -0
  83. sourcecode-5.4.0/docs/perf/baselines/2.5.15/petclinic__ask__cold.json +52 -0
  84. sourcecode-5.4.0/docs/perf/baselines/2.5.15/petclinic__ask__warm.json +40 -0
  85. sourcecode-5.4.0/docs/perf/baselines/2.5.16/SUMMARY.md +112 -0
  86. sourcecode-5.4.0/docs/perf/baselines/2.5.16/alfresco__ask__cold.json +52 -0
  87. sourcecode-5.4.0/docs/perf/baselines/2.5.16/alfresco__ask__warm.json +40 -0
  88. sourcecode-5.4.0/docs/perf/baselines/2.5.16/broadleaf__ask__cold.json +52 -0
  89. sourcecode-5.4.0/docs/perf/baselines/2.5.16/broadleaf__ask__warm.json +40 -0
  90. sourcecode-5.4.0/docs/perf/baselines/2.5.16/eureka__ask__cold.json +52 -0
  91. sourcecode-5.4.0/docs/perf/baselines/2.5.16/eureka__ask__warm.json +40 -0
  92. sourcecode-5.4.0/docs/perf/baselines/2.5.16/jenkins__ask__cold.json +52 -0
  93. sourcecode-5.4.0/docs/perf/baselines/2.5.16/jenkins__ask__warm.json +40 -0
  94. sourcecode-5.4.0/docs/perf/baselines/2.5.16/jobrunr__ask__cold.json +52 -0
  95. sourcecode-5.4.0/docs/perf/baselines/2.5.16/jobrunr__ask__warm.json +40 -0
  96. sourcecode-5.4.0/docs/perf/baselines/2.5.16/keycloak__ask__cold.json +52 -0
  97. sourcecode-5.4.0/docs/perf/baselines/2.5.16/keycloak__ask__warm.json +40 -0
  98. sourcecode-5.4.0/docs/perf/baselines/2.5.16/neo4j__ask__cold.json +52 -0
  99. sourcecode-5.4.0/docs/perf/baselines/2.5.16/neo4j__ask__warm.json +40 -0
  100. sourcecode-5.4.0/docs/perf/baselines/2.5.16/ofbiz__ask__cold.json +52 -0
  101. sourcecode-5.4.0/docs/perf/baselines/2.5.16/ofbiz__ask__warm.json +40 -0
  102. sourcecode-5.4.0/docs/perf/baselines/2.5.16/openmrs__ask__cold.json +52 -0
  103. sourcecode-5.4.0/docs/perf/baselines/2.5.16/openmrs__ask__warm.json +40 -0
  104. sourcecode-5.4.0/docs/perf/baselines/2.5.16/petclinic__ask__cold.json +52 -0
  105. sourcecode-5.4.0/docs/perf/baselines/2.5.16/petclinic__ask__warm.json +40 -0
  106. sourcecode-5.4.0/docs/perf/baselines/gate-latest/README.md +79 -0
  107. sourcecode-5.4.0/docs/perf/baselines/gate-latest/broadleaf__ask__warm.json +47 -0
  108. sourcecode-5.4.0/docs/perf/baselines/gate-latest/broadleaf__endpoints__warm.json +47 -0
  109. sourcecode-5.4.0/docs/perf/baselines/gate-latest/broadleaf__migrate-check__warm.json +47 -0
  110. sourcecode-5.4.0/docs/perf/baselines/gate-latest/broadleaf__posture__warm.json +47 -0
  111. sourcecode-5.4.0/docs/perf/baselines/gate-latest/broadleaf__spring-audit__warm.json +47 -0
  112. sourcecode-5.4.0/docs/perf/baselines/gate-latest/broadleaf__validation__warm.json +47 -0
  113. sourcecode-5.4.0/docs/perf/baselines/reference-best/README.md +34 -0
  114. sourcecode-5.4.0/docs/posture.md +446 -0
  115. sourcecode-5.4.0/docs/privacy.md +205 -0
  116. sourcecode-5.4.0/docs/pro-experience-audit.md +115 -0
  117. sourcecode-5.4.0/docs/schema.md +894 -0
  118. sourcecode-5.4.0/docs/spec/envelope-v1.md +84 -0
  119. sourcecode-5.4.0/docs/spring-audit-ci.yml +56 -0
  120. {sourcecode-5.3.1 → sourcecode-5.4.0}/pyproject.toml +9 -2
  121. {sourcecode-5.3.1 → sourcecode-5.4.0}/src/sourcecode/__init__.py +1 -1
  122. {sourcecode-5.3.1 → sourcecode-5.4.0}/src/sourcecode/baseline_autocapture.py +43 -17
  123. sourcecode-5.4.0/src/sourcecode/bundled_docs.py +64 -0
  124. {sourcecode-5.3.1 → sourcecode-5.4.0}/src/sourcecode/cli.py +304 -87
  125. {sourcecode-5.3.1 → sourcecode-5.4.0}/src/sourcecode/client_calls.py +114 -13
  126. {sourcecode-5.3.1 → sourcecode-5.4.0}/src/sourcecode/consumer_join.py +35 -6
  127. {sourcecode-5.3.1 → sourcecode-5.4.0}/src/sourcecode/data_labels.py +31 -21
  128. sourcecode-5.4.0/src/sourcecode/declarations.py +179 -0
  129. {sourcecode-5.3.1 → sourcecode-5.4.0}/src/sourcecode/release_info.py +15 -4
  130. {sourcecode-5.3.1 → sourcecode-5.4.0}/src/sourcecode/repository_ir.py +159 -24
  131. {sourcecode-5.3.1 → sourcecode-5.4.0}/src/sourcecode/security_config.py +58 -17
  132. {sourcecode-5.3.1 → sourcecode-5.4.0}/src/sourcecode/serializer.py +22 -1
  133. {sourcecode-5.3.1 → sourcecode-5.4.0}/src/sourcecode/spring_impact.py +11 -0
  134. {sourcecode-5.3.1 → sourcecode-5.4.0}/src/sourcecode/sql_taint.py +229 -23
  135. sourcecode-5.3.1/src/sourcecode/declarations.py +0 -81
  136. {sourcecode-5.3.1 → sourcecode-5.4.0}/.github/workflows/build-windows.yml +0 -0
  137. {sourcecode-5.3.1 → sourcecode-5.4.0}/.github/workflows/perf-gate.yml +0 -0
  138. {sourcecode-5.3.1 → sourcecode-5.4.0}/.gitignore +0 -0
  139. {sourcecode-5.3.1 → sourcecode-5.4.0}/.ruff.toml +0 -0
  140. {sourcecode-5.3.1 → sourcecode-5.4.0}/CLAUDE.md +0 -0
  141. {sourcecode-5.3.1 → sourcecode-5.4.0}/CONTRIBUTING.md +0 -0
  142. {sourcecode-5.3.1 → sourcecode-5.4.0}/LICENSE +0 -0
  143. {sourcecode-5.3.1 → sourcecode-5.4.0}/SECURITY.md +0 -0
  144. {sourcecode-5.3.1 → sourcecode-5.4.0}/raw +0 -0
  145. {sourcecode-5.3.1 → sourcecode-5.4.0}/scripts/compare_integration_engines.py +0 -0
  146. {sourcecode-5.3.1 → sourcecode-5.4.0}/scripts/customer_smoke_test.sh +0 -0
  147. {sourcecode-5.3.1 → sourcecode-5.4.0}/scripts/generate_jdk_exports.py +0 -0
  148. {sourcecode-5.3.1 → sourcecode-5.4.0}/scripts/perf_gate.py +0 -0
  149. {sourcecode-5.3.1 → sourcecode-5.4.0}/scripts/perf_harness.py +0 -0
  150. {sourcecode-5.3.1 → sourcecode-5.4.0}/scripts/sync_gate_anchors.py +0 -0
  151. {sourcecode-5.3.1 → sourcecode-5.4.0}/src/sourcecode/adaptive_scanner.py +0 -0
  152. {sourcecode-5.3.1 → sourcecode-5.4.0}/src/sourcecode/archetype.py +0 -0
  153. {sourcecode-5.3.1 → sourcecode-5.4.0}/src/sourcecode/architectural_baseline.py +0 -0
  154. {sourcecode-5.3.1 → sourcecode-5.4.0}/src/sourcecode/architectural_delta.py +0 -0
  155. {sourcecode-5.3.1 → sourcecode-5.4.0}/src/sourcecode/architecture_analyzer.py +0 -0
  156. {sourcecode-5.3.1 → sourcecode-5.4.0}/src/sourcecode/architecture_summary.py +0 -0
  157. {sourcecode-5.3.1 → sourcecode-5.4.0}/src/sourcecode/ast_extractor.py +0 -0
  158. {sourcecode-5.3.1 → sourcecode-5.4.0}/src/sourcecode/audit_report.py +0 -0
  159. {sourcecode-5.3.1 → sourcecode-5.4.0}/src/sourcecode/cache.py +0 -0
  160. {sourcecode-5.3.1 → sourcecode-5.4.0}/src/sourcecode/cache_model.py +0 -0
  161. {sourcecode-5.3.1 → sourcecode-5.4.0}/src/sourcecode/call_surface.py +0 -0
  162. {sourcecode-5.3.1 → sourcecode-5.4.0}/src/sourcecode/caller_metrics.py +0 -0
  163. {sourcecode-5.3.1 → sourcecode-5.4.0}/src/sourcecode/caller_reach.py +0 -0
  164. {sourcecode-5.3.1 → sourcecode-5.4.0}/src/sourcecode/canonical_ir.py +0 -0
  165. {sourcecode-5.3.1 → sourcecode-5.4.0}/src/sourcecode/chain_rules.py +0 -0
  166. {sourcecode-5.3.1 → sourcecode-5.4.0}/src/sourcecode/change_plan.py +0 -0
  167. {sourcecode-5.3.1 → sourcecode-5.4.0}/src/sourcecode/cir_graphs.py +0 -0
  168. {sourcecode-5.3.1 → sourcecode-5.4.0}/src/sourcecode/classifier.py +0 -0
  169. {sourcecode-5.3.1 → sourcecode-5.4.0}/src/sourcecode/code_notes_analyzer.py +0 -0
  170. {sourcecode-5.3.1 → sourcecode-5.4.0}/src/sourcecode/compare.py +0 -0
  171. {sourcecode-5.3.1 → sourcecode-5.4.0}/src/sourcecode/confidence_analyzer.py +0 -0
  172. {sourcecode-5.3.1 → sourcecode-5.4.0}/src/sourcecode/constraint_diff.py +0 -0
  173. {sourcecode-5.3.1 → sourcecode-5.4.0}/src/sourcecode/container_wiring.py +0 -0
  174. {sourcecode-5.3.1 → sourcecode-5.4.0}/src/sourcecode/context_cache.py +0 -0
  175. {sourcecode-5.3.1 → sourcecode-5.4.0}/src/sourcecode/context_graph.py +0 -0
  176. {sourcecode-5.3.1 → sourcecode-5.4.0}/src/sourcecode/context_scorer.py +0 -0
  177. {sourcecode-5.3.1 → sourcecode-5.4.0}/src/sourcecode/context_summarizer.py +0 -0
  178. {sourcecode-5.3.1 → sourcecode-5.4.0}/src/sourcecode/contract_diff.py +0 -0
  179. {sourcecode-5.3.1 → sourcecode-5.4.0}/src/sourcecode/contract_init.py +0 -0
  180. {sourcecode-5.3.1 → sourcecode-5.4.0}/src/sourcecode/contract_model.py +0 -0
  181. {sourcecode-5.3.1 → sourcecode-5.4.0}/src/sourcecode/contract_pipeline.py +0 -0
  182. {sourcecode-5.3.1 → sourcecode-5.4.0}/src/sourcecode/coverage_parser.py +0 -0
  183. {sourcecode-5.3.1 → sourcecode-5.4.0}/src/sourcecode/data_exposure.py +0 -0
  184. {sourcecode-5.3.1 → sourcecode-5.4.0}/src/sourcecode/defect_identity.py +0 -0
  185. {sourcecode-5.3.1 → sourcecode-5.4.0}/src/sourcecode/degradation.py +0 -0
  186. {sourcecode-5.3.1 → sourcecode-5.4.0}/src/sourcecode/dependency_analyzer.py +0 -0
  187. {sourcecode-5.3.1 → sourcecode-5.4.0}/src/sourcecode/deployment_prefix.py +0 -0
  188. {sourcecode-5.3.1 → sourcecode-5.4.0}/src/sourcecode/detach.py +0 -0
  189. {sourcecode-5.3.1 → sourcecode-5.4.0}/src/sourcecode/detectors/__init__.py +0 -0
  190. {sourcecode-5.3.1 → sourcecode-5.4.0}/src/sourcecode/detectors/base.py +0 -0
  191. {sourcecode-5.3.1 → sourcecode-5.4.0}/src/sourcecode/detectors/csproj_parser.py +0 -0
  192. {sourcecode-5.3.1 → sourcecode-5.4.0}/src/sourcecode/detectors/dart.py +0 -0
  193. {sourcecode-5.3.1 → sourcecode-5.4.0}/src/sourcecode/detectors/dotnet.py +0 -0
  194. {sourcecode-5.3.1 → sourcecode-5.4.0}/src/sourcecode/detectors/elixir.py +0 -0
  195. {sourcecode-5.3.1 → sourcecode-5.4.0}/src/sourcecode/detectors/go.py +0 -0
  196. {sourcecode-5.3.1 → sourcecode-5.4.0}/src/sourcecode/detectors/heuristic.py +0 -0
  197. {sourcecode-5.3.1 → sourcecode-5.4.0}/src/sourcecode/detectors/hybrid.py +0 -0
  198. {sourcecode-5.3.1 → sourcecode-5.4.0}/src/sourcecode/detectors/java.py +0 -0
  199. {sourcecode-5.3.1 → sourcecode-5.4.0}/src/sourcecode/detectors/jvm_ext.py +0 -0
  200. {sourcecode-5.3.1 → sourcecode-5.4.0}/src/sourcecode/detectors/nodejs.py +0 -0
  201. {sourcecode-5.3.1 → sourcecode-5.4.0}/src/sourcecode/detectors/parsers.py +0 -0
  202. {sourcecode-5.3.1 → sourcecode-5.4.0}/src/sourcecode/detectors/php.py +0 -0
  203. {sourcecode-5.3.1 → sourcecode-5.4.0}/src/sourcecode/detectors/project.py +0 -0
  204. {sourcecode-5.3.1 → sourcecode-5.4.0}/src/sourcecode/detectors/python.py +0 -0
  205. {sourcecode-5.3.1 → sourcecode-5.4.0}/src/sourcecode/detectors/ruby.py +0 -0
  206. {sourcecode-5.3.1 → sourcecode-5.4.0}/src/sourcecode/detectors/rust.py +0 -0
  207. {sourcecode-5.3.1 → sourcecode-5.4.0}/src/sourcecode/detectors/systems.py +0 -0
  208. {sourcecode-5.3.1 → sourcecode-5.4.0}/src/sourcecode/detectors/terraform.py +0 -0
  209. {sourcecode-5.3.1 → sourcecode-5.4.0}/src/sourcecode/detectors/tooling.py +0 -0
  210. {sourcecode-5.3.1 → sourcecode-5.4.0}/src/sourcecode/doc_analyzer.py +0 -0
  211. {sourcecode-5.3.1 → sourcecode-5.4.0}/src/sourcecode/dynamic_argument_surface.py +0 -0
  212. {sourcecode-5.3.1 → sourcecode-5.4.0}/src/sourcecode/endpoint_literals.py +0 -0
  213. {sourcecode-5.3.1 → sourcecode-5.4.0}/src/sourcecode/endpoint_metrics.py +0 -0
  214. {sourcecode-5.3.1 → sourcecode-5.4.0}/src/sourcecode/entrypoint_classifier.py +0 -0
  215. {sourcecode-5.3.1 → sourcecode-5.4.0}/src/sourcecode/env_analyzer.py +0 -0
  216. {sourcecode-5.3.1 → sourcecode-5.4.0}/src/sourcecode/envelope.py +0 -0
  217. {sourcecode-5.3.1 → sourcecode-5.4.0}/src/sourcecode/environment_resolution.py +0 -0
  218. {sourcecode-5.3.1 → sourcecode-5.4.0}/src/sourcecode/error_schema.py +0 -0
  219. {sourcecode-5.3.1 → sourcecode-5.4.0}/src/sourcecode/evidence_provider.py +0 -0
  220. {sourcecode-5.3.1 → sourcecode-5.4.0}/src/sourcecode/execution_plan.py +0 -0
  221. {sourcecode-5.3.1 → sourcecode-5.4.0}/src/sourcecode/explain.py +0 -0
  222. {sourcecode-5.3.1 → sourcecode-5.4.0}/src/sourcecode/facts/__init__.py +0 -0
  223. {sourcecode-5.3.1 → sourcecode-5.4.0}/src/sourcecode/facts/registry.json +0 -0
  224. {sourcecode-5.3.1 → sourcecode-5.4.0}/src/sourcecode/file_chunker.py +0 -0
  225. {sourcecode-5.3.1 → sourcecode-5.4.0}/src/sourcecode/file_classifier.py +0 -0
  226. {sourcecode-5.3.1 → sourcecode-5.4.0}/src/sourcecode/filter_surface.py +0 -0
  227. {sourcecode-5.3.1 → sourcecode-5.4.0}/src/sourcecode/format_contract.py +0 -0
  228. {sourcecode-5.3.1 → sourcecode-5.4.0}/src/sourcecode/fqn_utils.py +0 -0
  229. {sourcecode-5.3.1 → sourcecode-5.4.0}/src/sourcecode/gate_anchors.py +0 -0
  230. {sourcecode-5.3.1 → sourcecode-5.4.0}/src/sourcecode/git_analyzer.py +0 -0
  231. {sourcecode-5.3.1 → sourcecode-5.4.0}/src/sourcecode/git_checkout.py +0 -0
  232. {sourcecode-5.3.1 → sourcecode-5.4.0}/src/sourcecode/graph_analyzer.py +0 -0
  233. {sourcecode-5.3.1 → sourcecode-5.4.0}/src/sourcecode/graph_evidence.py +0 -0
  234. {sourcecode-5.3.1 → sourcecode-5.4.0}/src/sourcecode/hibernate_strat.py +0 -0
  235. {sourcecode-5.3.1 → sourcecode-5.4.0}/src/sourcecode/identity_fallback.py +0 -0
  236. {sourcecode-5.3.1 → sourcecode-5.4.0}/src/sourcecode/integration_coordinates.py +0 -0
  237. {sourcecode-5.3.1 → sourcecode-5.4.0}/src/sourcecode/jdk_exports.py +0 -0
  238. {sourcecode-5.3.1 → sourcecode-5.4.0}/src/sourcecode/license.py +0 -0
  239. {sourcecode-5.3.1 → sourcecode-5.4.0}/src/sourcecode/mcp/__init__.py +0 -0
  240. {sourcecode-5.3.1 → sourcecode-5.4.0}/src/sourcecode/mcp/dependency_import.py +0 -0
  241. {sourcecode-5.3.1 → sourcecode-5.4.0}/src/sourcecode/mcp/onboarding/__init__.py +0 -0
  242. {sourcecode-5.3.1 → sourcecode-5.4.0}/src/sourcecode/mcp/onboarding/applier.py +0 -0
  243. {sourcecode-5.3.1 → sourcecode-5.4.0}/src/sourcecode/mcp/onboarding/backup.py +0 -0
  244. {sourcecode-5.3.1 → sourcecode-5.4.0}/src/sourcecode/mcp/onboarding/detector.py +0 -0
  245. {sourcecode-5.3.1 → sourcecode-5.4.0}/src/sourcecode/mcp/onboarding/planner.py +0 -0
  246. {sourcecode-5.3.1 → sourcecode-5.4.0}/src/sourcecode/mcp/orchestrator.py +0 -0
  247. {sourcecode-5.3.1 → sourcecode-5.4.0}/src/sourcecode/mcp/registry.py +0 -0
  248. {sourcecode-5.3.1 → sourcecode-5.4.0}/src/sourcecode/mcp/runner.py +0 -0
  249. {sourcecode-5.3.1 → sourcecode-5.4.0}/src/sourcecode/mcp/server.py +0 -0
  250. {sourcecode-5.3.1 → sourcecode-5.4.0}/src/sourcecode/mcp_nudge.py +0 -0
  251. {sourcecode-5.3.1 → sourcecode-5.4.0}/src/sourcecode/metrics_analyzer.py +0 -0
  252. {sourcecode-5.3.1 → sourcecode-5.4.0}/src/sourcecode/migrate_check.py +0 -0
  253. {sourcecode-5.3.1 → sourcecode-5.4.0}/src/sourcecode/migration_blast.py +0 -0
  254. {sourcecode-5.3.1 → sourcecode-5.4.0}/src/sourcecode/non_coverage.py +0 -0
  255. {sourcecode-5.3.1 → sourcecode-5.4.0}/src/sourcecode/openapi_surface.py +0 -0
  256. {sourcecode-5.3.1 → sourcecode-5.4.0}/src/sourcecode/openrewrite_recipe.py +0 -0
  257. {sourcecode-5.3.1 → sourcecode-5.4.0}/src/sourcecode/output_budget.py +0 -0
  258. {sourcecode-5.3.1 → sourcecode-5.4.0}/src/sourcecode/output_encoding.py +0 -0
  259. {sourcecode-5.3.1 → sourcecode-5.4.0}/src/sourcecode/parallel.py +0 -0
  260. {sourcecode-5.3.1 → sourcecode-5.4.0}/src/sourcecode/parse_cache.py +0 -0
  261. {sourcecode-5.3.1 → sourcecode-5.4.0}/src/sourcecode/partial_contract.py +0 -0
  262. {sourcecode-5.3.1 → sourcecode-5.4.0}/src/sourcecode/path_admission.py +0 -0
  263. {sourcecode-5.3.1 → sourcecode-5.4.0}/src/sourcecode/path_filters.py +0 -0
  264. {sourcecode-5.3.1 → sourcecode-5.4.0}/src/sourcecode/perf.py +0 -0
  265. {sourcecode-5.3.1 → sourcecode-5.4.0}/src/sourcecode/phased_run.py +0 -0
  266. {sourcecode-5.3.1 → sourcecode-5.4.0}/src/sourcecode/pipe_contract.py +0 -0
  267. {sourcecode-5.3.1 → sourcecode-5.4.0}/src/sourcecode/posture.py +0 -0
  268. {sourcecode-5.3.1 → sourcecode-5.4.0}/src/sourcecode/pr_comment_renderer.py +0 -0
  269. {sourcecode-5.3.1 → sourcecode-5.4.0}/src/sourcecode/pr_impact.py +0 -0
  270. {sourcecode-5.3.1 → sourcecode-5.4.0}/src/sourcecode/prepare_context.py +0 -0
  271. {sourcecode-5.3.1 → sourcecode-5.4.0}/src/sourcecode/progress.py +0 -0
  272. {sourcecode-5.3.1 → sourcecode-5.4.0}/src/sourcecode/provenance.py +0 -0
  273. {sourcecode-5.3.1 → sourcecode-5.4.0}/src/sourcecode/ranking_engine.py +0 -0
  274. {sourcecode-5.3.1 → sourcecode-5.4.0}/src/sourcecode/readiness_timeline.py +0 -0
  275. {sourcecode-5.3.1 → sourcecode-5.4.0}/src/sourcecode/readonly.py +0 -0
  276. {sourcecode-5.3.1 → sourcecode-5.4.0}/src/sourcecode/reconciliation.py +0 -0
  277. {sourcecode-5.3.1 → sourcecode-5.4.0}/src/sourcecode/redactor.py +0 -0
  278. {sourcecode-5.3.1 → sourcecode-5.4.0}/src/sourcecode/reference_facts.py +0 -0
  279. {sourcecode-5.3.1 → sourcecode-5.4.0}/src/sourcecode/relevance_scorer.py +0 -0
  280. {sourcecode-5.3.1 → sourcecode-5.4.0}/src/sourcecode/remedies.py +0 -0
  281. {sourcecode-5.3.1 → sourcecode-5.4.0}/src/sourcecode/rename_refactor.py +0 -0
  282. {sourcecode-5.3.1 → sourcecode-5.4.0}/src/sourcecode/repo_classifier.py +0 -0
  283. {sourcecode-5.3.1 → sourcecode-5.4.0}/src/sourcecode/retrieval/__init__.py +0 -0
  284. {sourcecode-5.3.1 → sourcecode-5.4.0}/src/sourcecode/retrieval/context.py +0 -0
  285. {sourcecode-5.3.1 → sourcecode-5.4.0}/src/sourcecode/retrieval/errors.py +0 -0
  286. {sourcecode-5.3.1 → sourcecode-5.4.0}/src/sourcecode/retrieval/executor.py +0 -0
  287. {sourcecode-5.3.1 → sourcecode-5.4.0}/src/sourcecode/retrieval/planner.py +0 -0
  288. {sourcecode-5.3.1 → sourcecode-5.4.0}/src/sourcecode/retrieval/query.py +0 -0
  289. {sourcecode-5.3.1 → sourcecode-5.4.0}/src/sourcecode/retrieval/request.py +0 -0
  290. {sourcecode-5.3.1 → sourcecode-5.4.0}/src/sourcecode/retrieval/resolution.py +0 -0
  291. {sourcecode-5.3.1 → sourcecode-5.4.0}/src/sourcecode/retrieval/result.py +0 -0
  292. {sourcecode-5.3.1 → sourcecode-5.4.0}/src/sourcecode/retrieval/retriever.py +0 -0
  293. {sourcecode-5.3.1 → sourcecode-5.4.0}/src/sourcecode/retrieval/runtime.py +0 -0
  294. {sourcecode-5.3.1 → sourcecode-5.4.0}/src/sourcecode/retrieval/steps.py +0 -0
  295. {sourcecode-5.3.1 → sourcecode-5.4.0}/src/sourcecode/retrieval/steps_endpoint.py +0 -0
  296. {sourcecode-5.3.1 → sourcecode-5.4.0}/src/sourcecode/retrieval/steps_graph.py +0 -0
  297. {sourcecode-5.3.1 → sourcecode-5.4.0}/src/sourcecode/retrieval/steps_impact.py +0 -0
  298. {sourcecode-5.3.1 → sourcecode-5.4.0}/src/sourcecode/retrieval/steps_intf.py +0 -0
  299. {sourcecode-5.3.1 → sourcecode-5.4.0}/src/sourcecode/retrieval/steps_struct.py +0 -0
  300. {sourcecode-5.3.1 → sourcecode-5.4.0}/src/sourcecode/retrieval/steps_txsec.py +0 -0
  301. {sourcecode-5.3.1 → sourcecode-5.4.0}/src/sourcecode/ris.py +0 -0
  302. {sourcecode-5.3.1 → sourcecode-5.4.0}/src/sourcecode/risk.py +0 -0
  303. {sourcecode-5.3.1 → sourcecode-5.4.0}/src/sourcecode/rule_catalog.py +0 -0
  304. {sourcecode-5.3.1 → sourcecode-5.4.0}/src/sourcecode/rule_pass.py +0 -0
  305. {sourcecode-5.3.1 → sourcecode-5.4.0}/src/sourcecode/runs.py +0 -0
  306. {sourcecode-5.3.1 → sourcecode-5.4.0}/src/sourcecode/runtime_classifier.py +0 -0
  307. {sourcecode-5.3.1 → sourcecode-5.4.0}/src/sourcecode/sarif.py +0 -0
  308. {sourcecode-5.3.1 → sourcecode-5.4.0}/src/sourcecode/scanner.py +0 -0
  309. {sourcecode-5.3.1 → sourcecode-5.4.0}/src/sourcecode/schema.py +0 -0
  310. {sourcecode-5.3.1 → sourcecode-5.4.0}/src/sourcecode/schemas/envelope-v1.schema.json +0 -0
  311. {sourcecode-5.3.1 → sourcecode-5.4.0}/src/sourcecode/security_chain.py +0 -0
  312. {sourcecode-5.3.1 → sourcecode-5.4.0}/src/sourcecode/security_config_scan.py +0 -0
  313. {sourcecode-5.3.1 → sourcecode-5.4.0}/src/sourcecode/security_posture.py +0 -0
  314. {sourcecode-5.3.1 → sourcecode-5.4.0}/src/sourcecode/semantic_analyzer.py +0 -0
  315. {sourcecode-5.3.1 → sourcecode-5.4.0}/src/sourcecode/semantic_impact_engine.py +0 -0
  316. {sourcecode-5.3.1 → sourcecode-5.4.0}/src/sourcecode/semantic_integration_engine.py +0 -0
  317. {sourcecode-5.3.1 → sourcecode-5.4.0}/src/sourcecode/semantic_services.py +0 -0
  318. {sourcecode-5.3.1 → sourcecode-5.4.0}/src/sourcecode/servlet_surface.py +0 -0
  319. {sourcecode-5.3.1 → sourcecode-5.4.0}/src/sourcecode/source_text.py +0 -0
  320. {sourcecode-5.3.1 → sourcecode-5.4.0}/src/sourcecode/spring_event_topology.py +0 -0
  321. {sourcecode-5.3.1 → sourcecode-5.4.0}/src/sourcecode/spring_findings.py +0 -0
  322. {sourcecode-5.3.1 → sourcecode-5.4.0}/src/sourcecode/spring_model.py +0 -0
  323. {sourcecode-5.3.1 → sourcecode-5.4.0}/src/sourcecode/spring_profiles.py +0 -0
  324. {sourcecode-5.3.1 → sourcecode-5.4.0}/src/sourcecode/spring_properties.py +0 -0
  325. {sourcecode-5.3.1 → sourcecode-5.4.0}/src/sourcecode/spring_security_audit.py +0 -0
  326. {sourcecode-5.3.1 → sourcecode-5.4.0}/src/sourcecode/spring_semantic.py +0 -0
  327. {sourcecode-5.3.1 → sourcecode-5.4.0}/src/sourcecode/spring_tx_analyzer.py +0 -0
  328. {sourcecode-5.3.1 → sourcecode-5.4.0}/src/sourcecode/summarizer.py +0 -0
  329. {sourcecode-5.3.1 → sourcecode-5.4.0}/src/sourcecode/target_admission.py +0 -0
  330. {sourcecode-5.3.1 → sourcecode-5.4.0}/src/sourcecode/telemetry/__init__.py +0 -0
  331. {sourcecode-5.3.1 → sourcecode-5.4.0}/src/sourcecode/telemetry/config.py +0 -0
  332. {sourcecode-5.3.1 → sourcecode-5.4.0}/src/sourcecode/telemetry/consent.py +0 -0
  333. {sourcecode-5.3.1 → sourcecode-5.4.0}/src/sourcecode/telemetry/events.py +0 -0
  334. {sourcecode-5.3.1 → sourcecode-5.4.0}/src/sourcecode/telemetry/filters.py +0 -0
  335. {sourcecode-5.3.1 → sourcecode-5.4.0}/src/sourcecode/telemetry/transport.py +0 -0
  336. {sourcecode-5.3.1 → sourcecode-5.4.0}/src/sourcecode/test_gap_ranking.py +0 -0
  337. {sourcecode-5.3.1 → sourcecode-5.4.0}/src/sourcecode/test_sources.py +0 -0
  338. {sourcecode-5.3.1 → sourcecode-5.4.0}/src/sourcecode/text_input.py +0 -0
  339. {sourcecode-5.3.1 → sourcecode-5.4.0}/src/sourcecode/timeline.py +0 -0
  340. {sourcecode-5.3.1 → sourcecode-5.4.0}/src/sourcecode/token_estimate.py +0 -0
  341. {sourcecode-5.3.1 → sourcecode-5.4.0}/src/sourcecode/tree_utils.py +0 -0
  342. {sourcecode-5.3.1 → sourcecode-5.4.0}/src/sourcecode/type_usage_surface.py +0 -0
  343. {sourcecode-5.3.1 → sourcecode-5.4.0}/src/sourcecode/validation_inference.py +0 -0
  344. {sourcecode-5.3.1 → sourcecode-5.4.0}/src/sourcecode/validation_surface.py +0 -0
  345. {sourcecode-5.3.1 → sourcecode-5.4.0}/src/sourcecode/verify_edit.py +0 -0
  346. {sourcecode-5.3.1 → sourcecode-5.4.0}/src/sourcecode/verify_repo.py +0 -0
  347. {sourcecode-5.3.1 → sourcecode-5.4.0}/src/sourcecode/verify_rules.py +0 -0
  348. {sourcecode-5.3.1 → sourcecode-5.4.0}/src/sourcecode/version_check.py +0 -0
  349. {sourcecode-5.3.1 → sourcecode-5.4.0}/src/sourcecode/waivers.py +0 -0
  350. {sourcecode-5.3.1 → sourcecode-5.4.0}/src/sourcecode/workspace.py +0 -0
  351. {sourcecode-5.3.1 → sourcecode-5.4.0}/supabase/functions/README.md +0 -0
  352. {sourcecode-5.3.1 → sourcecode-5.4.0}/supabase/functions/get-license/index.ts +0 -0
  353. {sourcecode-5.3.1 → sourcecode-5.4.0}/supabase/functions/lemonsqueezy-webhook/index.ts +0 -0
  354. {sourcecode-5.3.1 → sourcecode-5.4.0}/supabase/functions/telemetry/index.ts +0 -0
  355. {sourcecode-5.3.1 → sourcecode-5.4.0}/supabase/sql/license_event_ordering.sql +0 -0
  356. {sourcecode-5.3.1 → sourcecode-5.4.0}/supabase/sql/licensing_schema.sql +0 -0
  357. {sourcecode-5.3.1 → sourcecode-5.4.0}/supabase/sql/telemetry_events.sql +0 -0
@@ -2,6 +2,104 @@
2
2
 
3
3
  ## [Unreleased]
4
4
 
5
+ ## [5.4.0] — 2026-08-12
6
+
7
+ **Fourteen rows from one audit, and the worst defect this ledger has recorded.**
8
+ ASK 5.3.1 was audited in the field under a written non-persistence protocol —
9
+ 113 instrumented invocations, 50 of 51 non-prohibited commands, zero crashes,
10
+ zero tracebacks, the repository byte-identical to its baseline at the end — and
11
+ 16 of its claims were cross-verified line by line against source. Thirteen held.
12
+ Three did not, and one of those three is the headline of this release.
13
+
14
+ **54,7 % of a monolith's HTTP surface was published as unguarded while carrying
15
+ a live authorization annotation.** A handler whose `@RequestMapping` is declared
16
+ on an abstract superclass was indexed under the *declaring* member, and the gate
17
+ lives on the *override* — so 1 955 of 3 574 endpoints read `none_detected` with
18
+ the annotation right there in source. It propagated to eight commands, ran in
19
+ the unsafe direction, and it retires this project's own most-quoted figure: the
20
+ "2 635 endpoints with no security policy" this repository has cited since
21
+ evaluation #7 is really ≈659.
22
+
23
+ ### Fixed
24
+ - **A handler keeps the gate it declares, not the one it inherits.** The
25
+ inheritance projection now names the member that *runs* (`effective_symbol`)
26
+ beside the one that declares the mapping, and every security lookup reads
27
+ both. The projection can only ever *add* a policy the override declares for
28
+ itself — the inherited verdict is never widened away. Second half, same root:
29
+ an inherited-mapping override was classified as a non-handler by the custom
30
+ gate predicate, putting the only members carrying the gate on the wrong side
31
+ of the specificity ratio and, on a repository where most controllers extend a
32
+ generic base, suppressing the gate outright.
33
+ - **A SQL statement's identity is its namespace, not its bare name.** `risk`
34
+ published as the repository's #1 critical row a `${}` that cannot be exploited,
35
+ joined to a call trace that does not exist: tainted calls were matched to
36
+ mapper statements by method name alone, so a controller calling its own
37
+ service's `actualizar` was reported as reaching a mapper statement `actualizar`
38
+ in an unrelated namespace. The correct key was already written in the code and
39
+ unused. A call is now a statement's only when its receiver resolves to that
40
+ mapper; an unresolvable receiver leaves the sink `undecidable`, never
41
+ `reaches`. And the interpolated expression is finally read: an OGNL ternary
42
+ over two string literals is a closed allowlist by construction — precisely the
43
+ mitigation SEC-008's own `fix_hint` recommends — and leaves the sink
44
+ population into a published `bounded_interpolations` list.
45
+ - **The security verdict is a fact about the tree, not about the shell.** Two
46
+ runs of `endpoints` over one unchanged tree returned two different censuses.
47
+ The programmatic-security fallback read a repository-relative path with no
48
+ root, resolving it against the process working directory: run from inside the
49
+ repository it read the file, run from anywhere else it cached a false. The
50
+ same scan could not tell code from prose — it matched `hasRole(` inside
51
+ `@PreAuthorize("hasRole('ADMIN')")`, a declarative gate on another method read
52
+ as runtime enforcement of this one. And a whole-file regex was preempting a
53
+ per-method gate on both surfaces.
54
+ - **One definition of the working set per document.** `git_context.uncommitted_files:
55
+ 1` sat beside `_cache.has_uncommitted_changes: false` in one payload. One
56
+ predicate now answers both, and what it excludes is published
57
+ (`uncommitted_files_not_read`) rather than subtracted in silence.
58
+ - **A declaration that cannot be used says so.** A `sourcecode.config.json` with
59
+ an invented top-level key, a misspelt `dataLabels` and
60
+ `customSecurityAnnotations` as an array of strings ran completely clean —
61
+ `declaration.problems: []`, `declaration_problems: 0`, the two fields the
62
+ schema publishes for exactly this. `ask config` now distinguishes *not
63
+ declared* from *declared and unusable*, and prints the keys the file accepts
64
+ from the registry the loaders read.
65
+ - **`impact` no longer prints the inverse of its own field.** `risk_level: high`
66
+ above "Low-risk isolated change" is gone; `risk_score` stays `null` where none
67
+ could be measured, and the floor the level asserts travels under its own name
68
+ so the row can still be ordered.
69
+ - **A written tail is not a URL, and a comment is not a call.** A client call
70
+ whose head is an interpolation is no longer promoted to `broken_integration` —
71
+ the path matched against is the written tail and the head is unknown — and the
72
+ TypeScript extractor now blanks comments, so a commented-out documentation
73
+ placeholder is not admitted as a live call.
74
+ - **`generate-tests` binds its budget on the clock a user reads.** 56,45 s to
75
+ enforce a 30 000 ms limit and return nothing: the abandoned walk was joined at
76
+ interpreter shutdown. It runs on a daemon thread now, and the default budget
77
+ is derived from the scope instead of being a constant measured against a walk
78
+ that no longer exists.
79
+
80
+ ### Changed
81
+ - `--env-map`, `--code-notes`, `--dependencies` and `--architecture` say that
82
+ `--compact` and `--agent` already enable them, from one sentence in one place.
83
+ - `repo-ir --force` names both guards it bypasses, in both units.
84
+ - `--base-ref` also accepts `--since`; `verify --baseline` also accepts `-b`;
85
+ `baseline capture --dir` and `migrate-check --history-dir` accept each other's
86
+ spelling. Nothing is renamed. `--files` takes the same three shapes on every
87
+ command that has it, through one reader.
88
+ - `docs/USER_GUIDE.md` and `docs/DEFECT-LEDGER.md` ship in the wheel, and the
89
+ surfaces that name them resolve the pointer from what is actually packaged.
90
+ - `enrich` publishes the pipeline that feeds it (`trivy fs --format sarif` →
91
+ `ask enrich . --sarif`) in its own help and in the guide.
92
+ - `untested_sources` declares the population it counts over and is present
93
+ whenever the ranking ran.
94
+
95
+ ### Added
96
+ - `tests/test_cli_grammar.py` — one concept, one spelling, derived from the CLI
97
+ registry, with every exception declared and reasoned.
98
+ - `tests/test_bundled_docs.py` — a document a surface names is a document this
99
+ build carries, asserted against the wheel manifest.
100
+
101
+ Suite: **8 240 passed, 14 skipped.**
102
+
5
103
  ## [5.3.1] — 2026-08-11
6
104
 
7
105
  **Six fixes from one field battery.** 5.3.0 was run over the 14 repositories in
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: sourcecode
3
- Version: 5.3.1
3
+ Version: 5.4.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-5.3.1-blue)
45
+ ![Version](https://img.shields.io/badge/version-5.4.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`**
@@ -126,7 +126,7 @@ brew tap haroundominique/sourcecode && brew install sourcecode
126
126
  # pip / pipx
127
127
  pipx install sourcecode # or: pip install sourcecode
128
128
 
129
- ask version # ask 5.3.1 — and, on a build that has aged,
129
+ ask version # ask 5.4.0 — and, on a build that has aged,
130
130
  # how many releases have probably shipped since
131
131
  ```
132
132
 
@@ -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-5.3.1-blue)
7
+ ![Version](https://img.shields.io/badge/version-5.4.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`**
@@ -88,7 +88,7 @@ brew tap haroundominique/sourcecode && brew install sourcecode
88
88
  # pip / pipx
89
89
  pipx install sourcecode # or: pip install sourcecode
90
90
 
91
- ask version # ask 5.3.1 — and, on a build that has aged,
91
+ ask version # ask 5.4.0 — and, on a build that has aged,
92
92
  # how many releases have probably shipped since
93
93
  ```
94
94
 
@@ -0,0 +1,180 @@
1
+ # Cache model — what a warm gives you, and what invalidates it
2
+
3
+ Field evaluation #3 ran `ask cache warm` (103 s), watched `--compact` come back in 1 s, then
4
+ watched `--agent --full --env-map --depth 20` take 171 s **after that warm**, and most of
5
+ `prepare-context` behave as if no cache existed. Their verdict was not that the cache is slow:
6
+
7
+ > *"El warm no es un warm general — el modelo de invalidación no está documentado y no es
8
+ > predecible."*
9
+
10
+ Two costs, and the second is the one that hurt: nothing told them which of their commands a
11
+ warm would help. This page is the answer, and it is generated from the same table the CLI
12
+ prints — run `ask cache model` for it in the terminal, `ask cache model --json` in a script.
13
+
14
+ ---
15
+
16
+ ## One rule for invalidation
17
+
18
+ **Every layer keys on the exact tree state. Any change to the analysed files invalidates it —
19
+ committed or not, staged or not, tracked or not.** A clean tree keys on the commit, so a repeat
20
+ run with no edits hits. A tree without a git repository is signed by the size and mtime of its
21
+ files and follows the same rule.
22
+
23
+ That was not true before 3.2.2: the snapshot cache keyed on the committed HEAD, so an
24
+ uncommitted edit was served the pre-edit answer (defect C1-9 in the
25
+ [defect ledger](DEFECT-LEDGER.md)). If you are reading this because a stale answer surprised
26
+ you on an older version, that is the bug, and upgrading is the fix.
27
+
28
+ Two things invalidate everything, everywhere:
29
+
30
+ - **An analyzer change.** A content hash of the analyzer's own source is in every key, so a new
31
+ release never serves an answer computed by the old logic.
32
+ - **`ask cache clear`.** `--all` also drops the RIS.
33
+
34
+ `--no-cache` skips the cache for one run without writing over what is stored.
35
+
36
+ ---
37
+
38
+ ## Where it lives
39
+
40
+ | Path | Holds |
41
+ |---|---|
42
+ | `~/.sourcecode/cache/<repo-id>/` | snapshot cache (`core-*`, `view-*`), the RIS, `prepare-context` task answers |
43
+ | `~/.sourcecode/ctx-*.json.gz` | the shared Canonical IR |
44
+ | `~/.sourcecode/parse-cache-v1/` | the per-file parse cache |
45
+
46
+ `SOURCECODE_CACHE_DIR` and `SOURCECODE_CONTEXT_CACHE_DIR` move them. Nothing leaves the machine.
47
+
48
+ The cache is keyed to **the path you analysed**: `cache warm ./service-a` warms `service-a`, not
49
+ the enclosing monorepo, and `cache status` / `cache clear` resolve to that same scope.
50
+
51
+ ---
52
+
53
+ ## The model
54
+
55
+ <!-- BEGIN GENERATED: ask cache model --markdown -->
56
+ | Layer | What it stores | What invalidates it | `cache warm` |
57
+ |---|---|---|---|
58
+ | `snapshot` | the rendered answer of the root command (L1 core analysis + L2 view) | tree state · analyzer fingerprint · analysis flags (--env-map, --depth, --docs, --exclude, …) for the core; presentation flags (--compact, --agent, --full, --format, …) for the view | built for the compact view (`--agent` also builds the agent view) |
59
+ | `ris` | the Repository Intelligence Snapshot — structural index, endpoint index, summaries | tree state (the snapshot records the tree it describes) | rebuilt on every warm |
60
+ | `cir` | the shared Canonical IR — the Java parse every knowledge command reuses | tree state · analyzer fingerprint · schema version | built |
61
+ | `task` | one `prepare-context` task answer, per task and per option set | tree state · task · --symptom / --all / --include-config / --format | never — a warm does not run any task |
62
+ | `parse` | the symbol extraction of one file, keyed by its bytes | the file's own bytes and the extractor's source — content-addressed, so it is never stale and never needs invalidating. Bounded by `ASK_PARSE_CACHE_MAX_MB` (default 512 MB, least-recently-used, enforced on write) and reported in `cache status` (F-AR) | filled for every Java file the warm parses |
63
+
64
+ Measured on BroadleafCommerce (2 000+ Java files, dirty tree), warm machine, 3.2.2, each command in isolation.
65
+
66
+ Measured on release 3.2.2. Figures are that build's on that repository, not a prediction for yours; the nightly performance gate (`docs/perf/REGRESSION-GATE.md`) is what re-measures them.
67
+
68
+ The second anchor is the field one, and it carries its own build for the same reason (C3-97): field evaluation #26: spring-audit on 3 342 Java files took 31 s (Windows, pipx, mixed cache) against 8.8 s on the 2 000-file reference. Where a command was measured on an earlier release than the one you are running, `ask cache model` says so on that row rather than presenting the figure as this build's.
69
+
70
+ | Command | A warm gives it | Measured (nothing cached → after a warm) | Repeat run cached | Layers | Notes |
71
+ |---|---|---|---|---|---|
72
+ | `ask (root)` | the answer | --compact 13.3 s cold → 0.3 s warm (cold re-measured on 3.7.0: was 19.3 s, C3-6); --agent --full --env-map --depth 20 34.7 s → 33.9 s (no gain) | yes | `snapshot`, `ris`, `parse` | `--compact` is what a warm stores by default; `--agent` needs `cache warm --agent`. `--env-map`, `--depth N` and `--exclude` change the *analysis*, so they miss the warmed core and rescan — the 171 s the field measured after a 103 s warm on 4.10.4. Eval #23 timed the same invocation at 72,3 s from a purged cache, and then paid 71,7 s again for `--agent` on the state it had just analysed (C3-103). |
73
+ | `posture` | the shared work | 10.1 s → 1.6 s | no | `cir`, `parse` | Resolves the conditional bean graph on every run, over the shared CIR a warm builds — the parse it used to repeat for itself. `--diff` compares two profile sets over that one IR, so the second side costs the resolution only. |
74
+ | `risk` | the shared work | not measured on the battery yet — the composition is bounded by the `spring-audit` + `impact-chain` costs listed here, not by new analysis | no | `cir`, `parse` | Composes what the audit, impact-chain and the posture already answer, so it pays each of their costs once over the shared CIR a warm builds — one parse for the whole composition, and the reachability query is cached per symbol within the run. |
75
+ | `enrich` | the shared work | not measured on the battery yet — bounded by the `risk` composition, plus reading one JSON file | no | `cir`, `parse` | Runs the same composition as `risk` over the repository, then joins a SARIF log to it. Reading the log is negligible; everything a warm helps with is the repository side, so what it buys is what it buys `risk`. |
76
+ | `audit-report` | the shared work | not measured on the battery yet — bounded by `risk` + `posture`, or by `posture` when `--from-risk` is supplied | no | `cir`, `parse` | Packages `risk` and `posture` evidence. A warm helps the repository side; `--from-risk risk.json` skips risk recomputation entirely and only builds the posture/report projection. |
77
+ | `migrate-recipe` | the shared work | not measured on the battery yet — bounded by `migrate-check` on the same repository (openmrs-core ~2 s) | no | `parse` | Runs the same scan as `migrate-check` and projects its findings into an OpenRewrite recipe, so it buys exactly what a warm buys `migrate-check`: the parse, not the rule pass. |
78
+ | `data-exposure` | the shared work | not measured on the battery yet — one `impact-chain` traversal per declared seed type over a CIR the warm already paid for | no | `cir`, `parse` | Walks the same call reach as `impact-chain` once per declared type and reads the endpoint security surface, both over the shared CIR a warm builds. Cost scales with the number of declared types, not with the size of the label. |
79
+ | `endpoints` | the shared work | 3.3 s → 1.4 s (re-measured on 3.7.0; was 2.8 s → 2.9 s) | no | `ris`, `parse` | Recomputes the endpoint surface on every run, over a parse a warm has already paid for. Until 3.7.0 the extractor parsed every file itself instead of reading the shared parse cache, and a warm measurably bought it nothing (C3-6). |
80
+ | `spring-audit` | the shared work | 8.8 s → 3.7 s | no | `ris`, `parse` | Recomputes every run, but over a parse a warm has already paid for. |
81
+ | `migrate-check` | nothing | 4.8 s → 4.8 s | no | `cir` | Computes its own inventory and shares nothing a warm builds. Only `--blast-radius` reuses the shared CIR. |
82
+ | `impact-chain` | the shared work | 9.9 s → 1.7 s | no | `cir`, `parse` | The CIR is the expensive half — this is where a warm pays most. |
83
+ | `impact` | the shared work | 4.9 s → 2.8 s | no | `parse` | — |
84
+ | `pr-impact` | the shared work | not timed | no | `parse` | Diff-dependent: the answer itself is never stored. What it costs follows the diff, not the repository: 12,5 s on an ordinary one and 11,8 s on a diff of security configuration, measured at field scale. |
85
+ | `verify` | nothing | not timed | no | — | Runs the contracts against a fresh reading. |
86
+ | `verify-edit` | the shared work | 14.6 s → 9.6 s → 5.6 s on repeat | yes | `parse` | Built for the edit loop: the parse cache is what keeps an unchanged file out of the next run. Its own second run is faster again. At field size that loop is not short yet: eval #23 measured 76,6 s on a tree with no edits, because the HEAD side is still built in a throwaway worktree instead of reusing the shared CIR (C3-102). |
87
+ | `review-pr` | nothing | 1.1 s → 2.3 s (slower) | no | `cir` | Diff-dependent, and it reuses the CIR only if one exists. On a small diff, loading the warmed CIR costs more than the work it saves. |
88
+ | `plan` | the shared work | 9.3 s → 3.8 s | no | `parse` | — |
89
+ | `compare` | the shared work | not timed | no | `parse` | — |
90
+ | `delta` | nothing | not timed | no | — | Analyses two states — two checkouts, or two refs materialised into temporary trees; neither is the tree the cache describes. |
91
+ | `contract-diff` | nothing | not timed | no | — | Analyses two states (checkouts or refs); neither is the tree the cache describes. |
92
+ | `fix-bug` | nothing | not timed | yes | `task` | Shorthand for `prepare-context fix-bug`; caches its own answer, which a warm never runs. |
93
+ | `rename-class` | nothing | not timed | no | — | — |
94
+ | `prepare-context` | the answer | onboard 6.5 s → 0.3 s with a warm — but a second run with NO warm recomputes (10.2 s → 9.4 s at 5 486 files; C1-40) · refactor 7.7 s → 7.7 s (0.3 s on repeat) · generate-tests 12.4 s → 11.0 s (0.3 s on repeat) | yes | `task`, `ris`, `cir`, `parse` | Per task: `onboard` and `explain` are served from the RIS a warm rebuilds; `refactor`, `fix-bug` and `generate-tests` cache their own answer, but a warm does not run them, so their first call pays full price; `delta` and `review-pr` are diff-dependent and never cached. |
95
+ | `onboard` | the answer | with a warm: 6.5 s → 0.3 s (2 000 files) · 10.2 s → 0.7 s (5 486 files). WITHOUT a warm, a second identical run: 10.2 s → 9.4 s (5 486 files) — no answer hit | no | `task`, `ris` | Shorthand for `prepare-context onboard`. A warm stores its answer; the command does NOT store its own, so a second run without a warm pays full price. C1-40: the field read `repeat cached` here, ran it twice with no warm, and measured 56 s then 23,5 s — this row said it would be a hit. |
96
+ | `explain` | the shared work | 9.8 s → 1.6 s | no | `cir` | Serves from the shared CIR a warm builds. |
97
+ | `export` | the shared work | 8.8 s → 3.7 s | no | `parse` | — |
98
+ | `repo-ir` | the shared work | 5.1 s → 2.9 s | no | `parse` | Carried as *did not finish* from 4.10.4 until eval #23 ran it at field size in 9,8 s — a run that did not finish once is not a command that cannot finish (C3-100, and the same correction `modernize` needed). |
99
+ | `validation` | the shared work | 11.6 s → 6.4 s | no | `parse` | — |
100
+ | `modernize` | the shared work | 5.2 s → 3.0 s | no | `parse` | Blocked in the session that recorded C3-53 and measured since: a run that did not finish once is not a command that cannot finish. |
101
+ | `chunk-file` | nothing | not timed | no | — | Reads one file; nothing to cache. |
102
+ | `cold-start` | the answer | 0.2 s either way | yes | `ris` | Reads the RIS a warm rebuilds — that is all it does. Without one it answers `no_ris` instead of a snapshot. |
103
+ | `timeline` | nothing | not timed | no | — | Each sample is a fresh materialisation of a different commit, so nothing is shared between samples: two commits are two trees, and a cache keyed on a tree state can only ever serve one of them. The per-sample cost is measured and published in the payload. |
104
+ | `trend` | nothing | not timed | no | — | Reads stored baseline artifacts from disk; analyses no source, so no cache layer applies. Same command as `baseline trend`. |
105
+ | `baseline` | the shared work | capture 8.7 s → 3.6 s | no | `parse` | `capture`/`diff`/`trend` over architectural metrics. The field figure is `capture`, the subcommand that analyses; `trend` reads stored artifacts and has its own row. |
106
+ | `retrieve` | the shared work | not timed | no | `cir`, `parse` | Every query builds or reuses the shared CIR a warm builds. |
107
+ | `archetype` | the shared work | 9.3 s → 5.6 s | no | `parse` | — |
108
+ | `activate` | nothing | not timed | no | — | Not an analysis. |
109
+ | `auth` | nothing | not timed | no | — | Not an analysis. |
110
+ | `cache` | nothing | not timed | no | — | Operates on the caches themselves. |
111
+ | `config` | nothing | not timed | no | — | Not an analysis. |
112
+ | `mcp` | the shared work | not timed | yes | `snapshot`, `ris`, `cir`, `parse` | Serves the same commands over MCP, with the same layers. |
113
+ | `schema` | nothing | not timed | no | — | Prints registries; reads no repository. |
114
+ | `telemetry` | nothing | not timed | no | — | Not an analysis. |
115
+ | `version` | nothing | not timed | no | — | Not an analysis. |
116
+ <!-- END GENERATED -->
117
+
118
+ ---
119
+
120
+ ## What this costs in CI
121
+
122
+ A pipeline with no persisted cache directory pays the cold price **every run** — the cache is on
123
+ disk, not in the repository, so a fresh container starts cold whatever you did yesterday.
124
+ Measured on BroadleafCommerce (2 000+ Java files, dirty tree, warm machine):
125
+
126
+ | Run | Nothing cached | After `cache warm` | Repeat |
127
+ |---|---|---|---|
128
+ | `ask --compact` | 17.7 s | **0.3 s** | 0.3 s |
129
+ | `ask --agent --full --env-map --depth 20` | 34.7 s | 33.9 s | 0.3 s |
130
+ | `endpoints` | 2.8 s | 2.9 s | 2.8 s |
131
+ | `spring-audit` | 8.8 s | 3.7 s | 3.6 s |
132
+ | `posture` | 10.1 s | **1.6 s** | 1.6 s |
133
+ | `migrate-check` | 4.8 s | 4.8 s | 4.8 s |
134
+ | `impact-chain` | 9.9 s | **1.7 s** | 1.7 s |
135
+ | `explain` | 9.8 s | **1.6 s** | 1.6 s |
136
+ | `prepare-context onboard` | 6.5 s | **0.3 s** | 0.3 s |
137
+ | `prepare-context refactor` | 7.7 s | 7.7 s | **0.3 s** |
138
+ | `prepare-context generate-tests` | 12.4 s | 11.0 s | **0.3 s** |
139
+
140
+ `cache warm` itself took **18 s** on that repository, and it reports its own elapsed time when it
141
+ finishes, precisely so the figure is in front of whoever writes the pipeline. On the 3 342-file
142
+ monolith of field evaluation #3 the same warm took 103 s and a cold `--agent --full --env-map
143
+ --depth 20` took 171 s.
144
+
145
+ Read the table twice. A warm is worth most to `--compact`, `impact-chain`, `explain`, `posture`
146
+ and `prepare-context onboard`; it is worth **nothing** to `endpoints` and `migrate-check`, and the
147
+ `prepare-context` tasks that are not `onboard`/`explain` only get fast on their *own* second run,
148
+ which a warm cannot trigger for them. If your pipeline runs `endpoints` and `migrate-check`, a
149
+ warm is 18 s you will not get back.
150
+
151
+ Three ways to spend less:
152
+
153
+ 1. **Persist `~/.sourcecode` between jobs** (cache the directory in your CI). Then only the files
154
+ that changed are re-derived.
155
+ 2. **Warm the view your pipeline consumes**, not the default one — `cache warm --agent` if the
156
+ pipeline reads `--agent`.
157
+ 3. **Ask for the command you need**, not for `--full`. `--full` and a raised `--depth` change the
158
+ analysis, so they are a different, colder question than `--compact`.
159
+
160
+ ---
161
+
162
+ ## Reading the freshness of an answer
163
+
164
+ Every root-command payload carries `_cache`:
165
+
166
+ ```json
167
+ "_cache": {
168
+ "cache_source": "L2_view",
169
+ "git_head_at_generation": "45649e0",
170
+ "current_git_head": "45649e0",
171
+ "is_stale": false,
172
+ "has_uncommitted_changes": true,
173
+ "generated_at": "2026-07-29T04:57:39Z",
174
+ "data_scope": "COMPACT"
175
+ }
176
+ ```
177
+
178
+ `cache_source` is `fresh` when the run computed the answer, and `L1_core` / `L2_view` when it was
179
+ served. `ask cache status` reports what is stored for a repository, and `ask cache freshness`
180
+ reports how far the RIS is from the current HEAD.
@@ -0,0 +1,115 @@
1
+ # ASK Engine — Commercial Offer
2
+
3
+ The single, coherent Free/Pro offer, defined by **customer value** (not technical
4
+ difficulty). Companion to [`PRODUCT_TIERS.md`](PRODUCT_TIERS.md) (the mechanical split)
5
+ and [`MODERNIZATION.md`](MODERNIZATION.md) (the flagship product narrative). CLI command:
6
+ `sourcecode`.
7
+
8
+ ## The one-sentence offer
9
+
10
+ > **ASK Engine answers the expensive questions about a large Java codebase —
11
+ > deterministically, with the source to prove it. Free on normal repos; Pro when the
12
+ > work gets enterprise-scale or automated.**
13
+
14
+ The gating axis is **size + automation**, never capability. Nothing is crippled on Free;
15
+ you pay exactly when the tool is replacing the most engineering time — a monolith above
16
+ **500 Java source files**, or CI/CD automation. **€19/mo · €190/yr, per developer.**
17
+
18
+ ---
19
+
20
+ ## The offer by capability
21
+
22
+ Each capability framed as a customer job. "Free part / Pro part" is the same size axis:
23
+ full on repos ≤ 500 Java files; Pro on enterprise-scale monoliths (and CI automation).
24
+
25
+ ### 1. Impact — "what breaks if I change this?"
26
+ *Commands: `impact`, `impact-chain`, `review-pr`, `pr-impact`, `fix-bug`.*
27
+ - **Problem:** before touching a monolith, know the blast radius — callers, endpoints,
28
+ transactional and security surface — without guessing.
29
+ - **Buyer:** enterprise developer, tech lead.
30
+ - **Why pay:** on a codebase too large to hold in your head (or an LLM's context), a
31
+ precise, source-backed change-risk answer prevents expensive mistakes. This is the moat
32
+ — determinism where LLMs hallucinate and grep can't follow the logic.
33
+ - **Free:** full power on repos ≤ 500 Java files.
34
+ - **Pro:** enterprise-scale monoliths + CI automation (`review-pr --format github-comment`).
35
+
36
+ ### 2. System Map — "what is this system, and what does it talk to?"
37
+ *Commands: `onboard`, `export` (`--c4`/`--module-graph`/`--integrations`), `endpoints`, `spring-audit`, `explain`.*
38
+ - **Problem:** understand an unfamiliar monolith — module structure, endpoints, external
39
+ integrations — fast.
40
+ - **Buyer:** architect, newly-onboarded engineer.
41
+ - **Why pay:** an accurate, current map of a system nobody fully understands; onboarding
42
+ in days, not months.
43
+ - **Free:** full on ≤ 500 Java files.
44
+ - **Pro:** enterprise-scale + rich/CI-consumable exports.
45
+
46
+ ### 3. Modernization — "are we ready to upgrade, and what blocks us?" ← flagship
47
+ *Commands: `migrate-check` (readiness), `validation`; see [`MODERNIZATION.md`](MODERNIZATION.md).*
48
+ - **Problem:** Boot 2→3, javax→jakarta, Hibernate 5→6, JDK and dependency readiness — a
49
+ budgeted, deadline-driven project full of unknowns.
50
+ - **Buyer:** platform/architecture lead with an allocated upgrade budget.
51
+ - **Why pay:** turn a months-long unknown into a measured plan; this is the capability
52
+ tied most directly to a funded project — the clearest willingness-to-pay.
53
+ - **Free:** the **readiness assessment** at any size (see freemium decision below).
54
+ - **Pro:** the **full remediation detail + effort plan** on enterprise-scale monoliths.
55
+
56
+ ### 4. Agent Platform — "give my AI agents ground truth."
57
+ *Commands: `mcp`, `repo-ir`, `cold-start`, `prepare-context`.*
58
+ - **Problem:** AI coding agents re-parse the repo every session and hallucinate structure.
59
+ - **Buyer:** teams using AI coding agents (Claude Code, Cursor, Copilot).
60
+ - **Why pay:** deterministic, cached, source-backed context — and CI automation on every PR.
61
+ - **Free:** local `mcp serve`, `cold-start`, and 30 `prepare-context delta` runs/repo.
62
+ - **Pro:** delta automation beyond the free quota (the CI/CD axis) + `generate-tests` at scale.
63
+
64
+ ---
65
+
66
+ ## Decision: `migrate-check` is FREEMIUM
67
+
68
+ **Question:** should `migrate-check` be fully Free, fully Pro, or freemium?
69
+
70
+ **Decision: FREEMIUM** — the assessment is Free at any size; the full at-scale detail is Pro.
71
+
72
+ **Justification (customer value, not technique):**
73
+ - `migrate-check` is the **buy-trigger**: it maps to a budgeted upgrade project. The
74
+ *assessment* (a readiness score, the dimension breakdown, the headline blocker) is what
75
+ creates the *"we have a problem, let's fund this"* moment. **Gating the assessment fully
76
+ to Pro hides the hook and kills conversion** — the buyer never discovers the value on
77
+ their real monolith.
78
+ - Fully Free, however, gives away the high-value deliverable — a complete, actionable
79
+ remediation plan on a 5,000-file monolith — for nothing.
80
+ - **Freemium resolves both:** the diagnosis is free everywhere (maximizes discovery); the
81
+ detailed, at-scale, actionable plan is the paid deliverable. This mirrors the existing
82
+ capped-preview model (`fix-bug` top-5, `modernize` structural-only on large repos), so it
83
+ introduces **no new gating axis** — just the same size axis applied to `migrate-check`.
84
+
85
+ **The exact split:**
86
+
87
+ | Signal | Free (any size) | Pro (repos > 500 Java files) |
88
+ |--------|-----------------|------------------------------|
89
+ | `readiness_score` + per-dimension scores (jakarta/boot3/jdk/hibernate) | ✅ | ✅ |
90
+ | `headline_blocker`, `blocking_count`, `applicable_dimensions` | ✅ | ✅ |
91
+ | summary counts (`total_findings`, `by_severity`) | ✅ | ✅ |
92
+ | **full `findings` detail** (per-file, per-rule, code context) | preview (top-N) on large repos | ✅ full |
93
+ | **`effort_breakdown` / estimated effort plan** | — on large repos | ✅ |
94
+ | `hygiene_findings`, `non_blocking` detail | — on large repos | ✅ |
95
+
96
+ On repos ≤ 500 Java files everything stays free (the model's promise). On enterprise
97
+ monoliths, a Free user gets the **score + a top-N findings preview + an upgrade prompt** —
98
+ enough to see the value and justify the budget.
99
+
100
+ **Implementation note.** The paywall is currently OFF (`_PRO_UNLOCK_ALL`), so this gate is
101
+ dormant. The capping is specified as a concrete step in
102
+ [`RC1-CHECKLIST.md`](RC1-CHECKLIST.md) / [`RELEASE-CHECKLIST.md`](RELEASE-CHECKLIST.md), to
103
+ land **together with paywall reactivation** (where it is exercised and tested end-to-end).
104
+ It is byte-neutral under the current unlock: with everyone floored to Pro, `migrate-check`
105
+ output is unchanged, so the reference-repo oracles do not move.
106
+
107
+ ---
108
+
109
+ ## Pricing
110
+
111
+ **€19/mo · €190/yr, per developer.** Self-serve, no metering, no sales motion. Sits at the
112
+ floor of the closest comparable (CodeScene $20–30/dev/mo) and matches dev-tool norms
113
+ (Cursor/Copilot $10–20/mo). ASK Engine is a focused CLI, so pricing at — not above — the
114
+ comp floor maximizes adoption. Enterprise (multi-repo, SSO, dashboards) is a future,
115
+ separately-sold SKU — not advertised until it exists.
@@ -0,0 +1,202 @@
1
+ # First Customer Validation (Increment #3.1)
2
+
3
+ Prepares ASK Engine to be **shown to real users for the first time** — developers,
4
+ architects, CTOs — and to run **validation interviews**. This is about the *communication*
5
+ of the product, not the engine. Nothing here changes analysis behavior.
6
+
7
+ Contents:
8
+ 1. First-two-minutes audit (what a new user actually understands)
9
+ 2. README-as-landing-page review + high-impact / low-cost copy proposals (ready to paste)
10
+ 3. End-to-end journey (README → install → first command → first value → Pro) with frictions
11
+ 4. The 5-minute demo → [`DEMO-5MIN.md`](DEMO-5MIN.md)
12
+ 5. User-interview question bank (validate, don't sell)
13
+
14
+ The offer being validated: [`COMMERCIAL-OFFER.md`](COMMERCIAL-OFFER.md) ·
15
+ [`MODERNIZATION.md`](MODERNIZATION.md) · [`PRODUCT_TIERS.md`](PRODUCT_TIERS.md).
16
+
17
+ ---
18
+
19
+ ## 1. First-two-minutes audit
20
+
21
+ Assumes a developer who has never seen ASK Engine and reads only the current repository
22
+ (README first). Observations only — objective, no fixes applied here.
23
+
24
+ ### What they understand in the first 30 seconds
25
+ Reading the title + tagline + first paragraph (`README.md:1–20`):
26
+ - It is a tool called **ASK Engine**; the CLI is `sourcecode`.
27
+ - It gives **AI coding agents** persistent structural context and a fast repeated-analysis
28
+ cache; the headline benefit framed is **speed** (re-parse avoidance, ~17x on Keycloak).
29
+ - It targets **large Java or TypeScript monoliths**.
30
+
31
+ ### What they understand in the first 2 minutes
32
+ Scrolling to the cache table, token table, install, and Quickstart (`README.md:24–131`):
33
+ - There is a **persistent content-hash cache** with measured speedups and bounded token output.
34
+ - The CLI does much more than caching: `impact`, `migrate-check`, `spring-audit`,
35
+ `impact-chain`, `endpoints`, `validation`, `onboard`, `review-pr`, `fix-bug` all appear in
36
+ the Quickstart.
37
+ - It runs **locally / offline** (stated later, `README.md:283`).
38
+
39
+ ### What they do NOT understand
40
+ - **What the flagship is.** Modernization (`migrate-check`) is item #5 in the Quickstart —
41
+ no emphasis — yet it is the buy-trigger in the offer. The reader can't tell the headline
42
+ job from the long-tail command list.
43
+ - **That Impact is the differentiator.** "What breaks if I change this?" — the moat vs
44
+ grep/LLMs — is one line among a dozen commands, not positioned as the reason to care.
45
+ - **Who it's for.** The tagline says "Java **or TypeScript** monolith", but the product
46
+ monetizes **Java/Spring** and several capabilities are Java/Spring-only. A TypeScript dev
47
+ is invited in, then hits Java-only walls.
48
+ - **Free vs Pro at a glance.** The split lives at `README.md:264` (Pricing) — below a very
49
+ long command reference. A buyer scanning "what do I get, why would I pay" must scroll past
50
+ everything first. (Prior audit gap **D3 / F3**.)
51
+ - **Differentiation.** Nowhere near the top does the README say *why this beats grep, an
52
+ LLM, or SonarQube/OpenRewrite* — the three things a buyer will compare it to.
53
+
54
+ ### Doubts they still have before installing
55
+ - **Does my code leave the machine?** (Answer — no egress, offline — is true and good, but
56
+ appears late; a security-conscious buyer wants it up top.)
57
+ - **Do I need an account / license / key to try it?** (Answer — no, fully local, Pro
58
+ currently unlocked — not stated upfront.)
59
+ - **Will it work on *my* repo?** Non-Spring Java? Non-Java? (Honest limitations exist but are
60
+ at the very bottom, `README.md:238–261`.)
61
+
62
+ ### What would stop them trying it
63
+ - **No Java repo handy** — nothing to point it at. (Mitigation: the demo names two public
64
+ repos; the README's first value example should too.)
65
+ - **No single "try it in 30 seconds" line at the very top** — the first runnable command is
66
+ after the install section.
67
+ - Low friction otherwise: `pip install sourcecode` / `brew install`, then `ask .`.
68
+
69
+ ---
70
+
71
+ ## 2. README as a landing page
72
+
73
+ Evaluated as the page that has to sell in one scroll.
74
+
75
+ | Landing criterion | Current state | Verdict |
76
+ |---|---|---|
77
+ | Problem is clear in 1 screen | Problem stated is *agent re-parse latency* only | ⚠ narrow — the expensive-questions problem (impact / modernization) is missing up top |
78
+ | Differentiation vs grep / LLM / static analysis | Not stated near the top | ✗ absent early |
79
+ | Real examples | Strong — measured cache tables, real repos (Keycloak, Broadleaf) | ✓ |
80
+ | Call to action | Install + Quickstart present | ✓ but value CTA ("check your upgrade readiness free") missing |
81
+ | Time-to-first-value | `ask .` is fast; but first *impressive* command isn't foregrounded | ⚠ |
82
+ | Free vs Pro visible without scrolling | No — at `:264` | ✗ (D3/F3) |
83
+
84
+ ### High-impact / low-cost proposals (copy ready to paste — NOT applied this increment)
85
+
86
+ Each is pure copy near the top; no engine or gating change. Ordered by impact.
87
+
88
+ **P-1 — Reframe the tagline + one-line problem (highest impact).** Replace the
89
+ agent-only framing (`README.md:3`) with the expensive-questions framing that names the two
90
+ buy-jobs, keeping the agent story as one of them:
91
+
92
+ > **Deterministic answers to the expensive questions about a large Java codebase —
93
+ > _what breaks if I change this_ and _are we ready to upgrade_ — with the source to prove
94
+ > every answer.**
95
+ > Built for enterprise Java/Spring monoliths. Runs locally, offline, no account. Also
96
+ > serves fast, cached ground-truth to AI coding agents.
97
+
98
+ **P-2 — Add a "What you get (Free vs Pro)" box right after the tagline** (fixes D3/F3).
99
+ Four rows — Impact, System Map, Modernization, Agent context — each with the one-line job
100
+ and "Free on normal repos · Pro at enterprise scale". Lifts the offer above the fold; links
101
+ to `COMMERCIAL-OFFER.md`.
102
+
103
+ **P-3 — Add a top "Try it in 30 seconds" block** naming a public repo so a reader with no
104
+ Java repo handy can still see value:
105
+ > ```bash
106
+ > pip install sourcecode
107
+ > git clone https://github.com/spring-projects/spring-petclinic && cd spring-petclinic
108
+ > ask migrate-check . # upgrade readiness, free, source-backed
109
+ > ask impact OwnerController . # what breaks if I change this?
110
+ > ```
111
+
112
+ **P-4 — One "vs grep / LLM / static analysis" line** near the top: *"grep finds text, an
113
+ LLM guesses, ASK Engine proves — every finding carries the source line, and the blast-radius
114
+ graph follows Spring DI that grep and LLMs miss."*
115
+
116
+ **P-5 — Fix the audience contradiction:** the tagline should say **Java/Spring**; move the
117
+ "other languages get repo-shape only" nuance into the capabilities section so a TypeScript
118
+ reader isn't over-promised.
119
+
120
+ These are proposals for the next copy pass. Applying them is a one-file, reversible edit.
121
+
122
+ ---
123
+
124
+ ## 3. End-to-end journey & frictions
125
+
126
+ The path a first user walks, with the friction at each hop.
127
+
128
+ | Hop | Reference | Friction |
129
+ |---|---|---|
130
+ | **README top** | `README.md:1–20` | Value prop = agent cache only; buy-jobs (impact, modernization) not foregrounded (**F1/F3/D3**). |
131
+ | **Install** | `README.md:62–84` | Clean — `pip install sourcecode` / `brew`. `ask version` confirms. Low friction. |
132
+ | **First command** | `README.md:88–131` | Quickstart is a 12-command wall; no "start here" ordering. A new user doesn't know which command to run first. |
133
+ | **First useful result** | live | `ask .` / `--compact` returns in ~0.3s warm. Good. But the *impressive* first result (blast radius, readiness score) isn't the one signposted first. |
134
+ | **Discover Free vs Pro** | `README.md:264` | Only reachable after the full command reference. Buyer scanning for "why pay" scrolls a long way (**D3**). |
135
+ | **Pro invite / activation** | `license.py`, `PRODUCT_TIERS.md` | Pro currently unlocked for everyone (early-adoption banner honest). When gated, prompt now shows Get-a-license + activate (G1 resolved). No `SOURCECODE_PURCHASE_URL` set yet (points to docs). **F2** — no in-tool pointer to pricing from `--help`/welcome. |
136
+
137
+ **Net:** install and time-to-first-result are strong; the weakness is entirely
138
+ **positioning / ordering of the value story**, not the tool. All frictions are copy-level
139
+ (F1/F2/F3/D3), already tracked in `RC1-CHECKLIST.md` §4 and `pro-experience-audit.md`.
140
+
141
+ ---
142
+
143
+ ## 4. The 5-minute demo
144
+
145
+ See [`DEMO-5MIN.md`](DEMO-5MIN.md) — a reproducible script over two public repos
146
+ (BroadleafCommerce, OpenMRS) showing only what impresses a buyer: precise blast radius,
147
+ modernization readiness with real blockers, and the cache speed story. No internal
148
+ architecture shown. All numbers in that script were captured from a real run on 2026-07-05.
149
+
150
+ ---
151
+
152
+ ## 5. User-interview question bank
153
+
154
+ For validation interviews. **Goal: validate hypotheses, not sell.** Open questions, let the
155
+ user talk, don't lead. Group by whichever hat the interviewee wears.
156
+
157
+ ### Warm-up (any interviewee)
158
+ - Walk me through the last time you had to make a change in a large, unfamiliar codebase.
159
+ What did you do first?
160
+ - When you join a new service/monolith, how long until you trust yourself to change it?
161
+
162
+ ### Core hypothesis probes (the four questions, asked without naming the product)
163
+ - **What problem were you trying to solve?** — last time you needed to know the blast radius
164
+ of a change, or plan a framework upgrade. What triggered it?
165
+ - **What did you expect to find / what did you reach for?** — grep, IDE call hierarchy, an
166
+ LLM, a static-analysis tool, asking a senior? What did that get you, and where did it fall
167
+ short?
168
+ - **What result would surprise you?** — if a tool told you "changing this class touches 54
169
+ endpoints across 2 modules" in ten seconds, would you believe it? What would make you
170
+ trust it?
171
+ - **What would you pay to avoid?** — describe a change or upgrade that went wrong (missed
172
+ caller, a `@Transactional` bypass, a botched Boot/Jakarta migration). What did it cost —
173
+ hours, an incident, a delayed release?
174
+
175
+ ### Modernization segment (platform / architecture lead)
176
+ - How do you *currently* estimate a Boot 2→3 / Jakarta / JDK / Hibernate upgrade? How
177
+ confident is that estimate?
178
+ - What blocks you from starting — unknown scope, unknown effort, fear of what breaks?
179
+ - If you had a per-dimension readiness score with the source line behind every blocker,
180
+ what would you do with it? Who signs off on the budget?
181
+
182
+ ### Impact segment (developer / tech lead)
183
+ - Before a risky change, how do you find everything it affects today? How often does
184
+ something get missed?
185
+ - How much do you trust an LLM's answer to "what calls this?" on your monolith? Have you
186
+ been burned?
187
+ - Spring DI: does your tooling follow interface→impl injection, or do you check by hand?
188
+
189
+ ### AI-agent segment (teams using Claude Code / Cursor / Copilot)
190
+ - How do your agents get repo context today? How often do they hallucinate structure?
191
+ - Would deterministic, cached, source-backed context change how you run agents in CI?
192
+
193
+ ### Pricing / packaging reactions (last, low-pressure)
194
+ - €19/dev/mo, free below 500 Java files and unlimited on normal repos — does that framing
195
+ make sense? Where would you expect to hit the paywall?
196
+ - Would you rather pay per developer, per repo, or per organization? Why?
197
+ - What single capability, if it worked perfectly, would justify the subscription on its own?
198
+
199
+ ### Anti-goals (do not do in interviews)
200
+ - Don't demo before asking what they do today — you'll bias the answers.
201
+ - Don't defend the tool when they describe a gap — write the gap down.
202
+ - Don't ask "would you buy this?" — ask what they've *already paid for or lost*.