sourcecode 3.6.0__tar.gz → 3.8.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 (200) hide show
  1. {sourcecode-3.6.0 → sourcecode-3.8.0}/CHANGELOG.md +452 -0
  2. {sourcecode-3.6.0 → sourcecode-3.8.0}/PKG-INFO +32 -3
  3. {sourcecode-3.6.0 → sourcecode-3.8.0}/README.md +31 -2
  4. {sourcecode-3.6.0 → sourcecode-3.8.0}/pyproject.toml +1 -1
  5. {sourcecode-3.6.0 → sourcecode-3.8.0}/src/sourcecode/__init__.py +1 -1
  6. {sourcecode-3.6.0 → sourcecode-3.8.0}/src/sourcecode/archetype.py +43 -16
  7. {sourcecode-3.6.0 → sourcecode-3.8.0}/src/sourcecode/cache_model.py +10 -7
  8. {sourcecode-3.6.0 → sourcecode-3.8.0}/src/sourcecode/change_plan.py +5 -1
  9. {sourcecode-3.6.0 → sourcecode-3.8.0}/src/sourcecode/cli.py +665 -197
  10. {sourcecode-3.6.0 → sourcecode-3.8.0}/src/sourcecode/compare.py +5 -3
  11. sourcecode-3.8.0/src/sourcecode/contract_init.py +419 -0
  12. sourcecode-3.8.0/src/sourcecode/defect_identity.py +142 -0
  13. {sourcecode-3.6.0 → sourcecode-3.8.0}/src/sourcecode/degradation.py +52 -0
  14. {sourcecode-3.6.0 → sourcecode-3.8.0}/src/sourcecode/detectors/java.py +15 -31
  15. sourcecode-3.8.0/src/sourcecode/environment_resolution.py +361 -0
  16. {sourcecode-3.6.0 → sourcecode-3.8.0}/src/sourcecode/explain.py +11 -0
  17. sourcecode-3.8.0/src/sourcecode/git_checkout.py +149 -0
  18. {sourcecode-3.6.0 → sourcecode-3.8.0}/src/sourcecode/migrate_check.py +52 -2
  19. sourcecode-3.8.0/src/sourcecode/non_coverage.py +198 -0
  20. {sourcecode-3.6.0 → sourcecode-3.8.0}/src/sourcecode/output_budget.py +7 -2
  21. sourcecode-3.8.0/src/sourcecode/pipe_contract.py +208 -0
  22. {sourcecode-3.6.0 → sourcecode-3.8.0}/src/sourcecode/posture.py +144 -2
  23. {sourcecode-3.6.0 → sourcecode-3.8.0}/src/sourcecode/pr_comment_renderer.py +13 -0
  24. {sourcecode-3.6.0 → sourcecode-3.8.0}/src/sourcecode/prepare_context.py +110 -3
  25. {sourcecode-3.6.0 → sourcecode-3.8.0}/src/sourcecode/repository_ir.py +61 -4
  26. {sourcecode-3.6.0 → sourcecode-3.8.0}/src/sourcecode/retrieval/result.py +24 -9
  27. {sourcecode-3.6.0 → sourcecode-3.8.0}/src/sourcecode/retrieval/steps.py +3 -0
  28. {sourcecode-3.6.0 → sourcecode-3.8.0}/src/sourcecode/retrieval/steps_endpoint.py +5 -5
  29. {sourcecode-3.6.0 → sourcecode-3.8.0}/src/sourcecode/retrieval/steps_graph.py +5 -5
  30. {sourcecode-3.6.0 → sourcecode-3.8.0}/src/sourcecode/retrieval/steps_impact.py +19 -7
  31. {sourcecode-3.6.0 → sourcecode-3.8.0}/src/sourcecode/retrieval/steps_intf.py +4 -4
  32. {sourcecode-3.6.0 → sourcecode-3.8.0}/src/sourcecode/retrieval/steps_struct.py +5 -5
  33. {sourcecode-3.6.0 → sourcecode-3.8.0}/src/sourcecode/retrieval/steps_txsec.py +5 -5
  34. {sourcecode-3.6.0 → sourcecode-3.8.0}/src/sourcecode/serializer.py +132 -66
  35. {sourcecode-3.6.0 → sourcecode-3.8.0}/src/sourcecode/spring_findings.py +139 -0
  36. {sourcecode-3.6.0 → sourcecode-3.8.0}/src/sourcecode/spring_impact.py +18 -1
  37. {sourcecode-3.6.0 → sourcecode-3.8.0}/src/sourcecode/spring_profiles.py +193 -1
  38. {sourcecode-3.6.0 → sourcecode-3.8.0}/src/sourcecode/spring_tx_analyzer.py +10 -0
  39. sourcecode-3.8.0/src/sourcecode/target_admission.py +168 -0
  40. sourcecode-3.8.0/src/sourcecode/test_gap_ranking.py +363 -0
  41. {sourcecode-3.6.0 → sourcecode-3.8.0}/src/sourcecode/token_estimate.py +36 -0
  42. {sourcecode-3.6.0 → sourcecode-3.8.0}/src/sourcecode/verify_edit.py +32 -9
  43. {sourcecode-3.6.0 → sourcecode-3.8.0}/.github/workflows/build-windows.yml +0 -0
  44. {sourcecode-3.6.0 → sourcecode-3.8.0}/.gitignore +0 -0
  45. {sourcecode-3.6.0 → sourcecode-3.8.0}/.ruff.toml +0 -0
  46. {sourcecode-3.6.0 → sourcecode-3.8.0}/CONTRIBUTING.md +0 -0
  47. {sourcecode-3.6.0 → sourcecode-3.8.0}/LICENSE +0 -0
  48. {sourcecode-3.6.0 → sourcecode-3.8.0}/SECURITY.md +0 -0
  49. {sourcecode-3.6.0 → sourcecode-3.8.0}/raw +0 -0
  50. {sourcecode-3.6.0 → sourcecode-3.8.0}/scripts/compare_integration_engines.py +0 -0
  51. {sourcecode-3.6.0 → sourcecode-3.8.0}/scripts/customer_smoke_test.sh +0 -0
  52. {sourcecode-3.6.0 → sourcecode-3.8.0}/scripts/generate_jdk_exports.py +0 -0
  53. {sourcecode-3.6.0 → sourcecode-3.8.0}/scripts/perf_harness.py +0 -0
  54. {sourcecode-3.6.0 → sourcecode-3.8.0}/src/sourcecode/adaptive_scanner.py +0 -0
  55. {sourcecode-3.6.0 → sourcecode-3.8.0}/src/sourcecode/architectural_baseline.py +0 -0
  56. {sourcecode-3.6.0 → sourcecode-3.8.0}/src/sourcecode/architectural_delta.py +0 -0
  57. {sourcecode-3.6.0 → sourcecode-3.8.0}/src/sourcecode/architecture_analyzer.py +0 -0
  58. {sourcecode-3.6.0 → sourcecode-3.8.0}/src/sourcecode/architecture_summary.py +0 -0
  59. {sourcecode-3.6.0 → sourcecode-3.8.0}/src/sourcecode/ast_extractor.py +0 -0
  60. {sourcecode-3.6.0 → sourcecode-3.8.0}/src/sourcecode/cache.py +0 -0
  61. {sourcecode-3.6.0 → sourcecode-3.8.0}/src/sourcecode/call_surface.py +0 -0
  62. {sourcecode-3.6.0 → sourcecode-3.8.0}/src/sourcecode/caller_metrics.py +0 -0
  63. {sourcecode-3.6.0 → sourcecode-3.8.0}/src/sourcecode/caller_reach.py +0 -0
  64. {sourcecode-3.6.0 → sourcecode-3.8.0}/src/sourcecode/canonical_ir.py +0 -0
  65. {sourcecode-3.6.0 → sourcecode-3.8.0}/src/sourcecode/chain_rules.py +0 -0
  66. {sourcecode-3.6.0 → sourcecode-3.8.0}/src/sourcecode/cir_graphs.py +0 -0
  67. {sourcecode-3.6.0 → sourcecode-3.8.0}/src/sourcecode/classifier.py +0 -0
  68. {sourcecode-3.6.0 → sourcecode-3.8.0}/src/sourcecode/code_notes_analyzer.py +0 -0
  69. {sourcecode-3.6.0 → sourcecode-3.8.0}/src/sourcecode/confidence_analyzer.py +0 -0
  70. {sourcecode-3.6.0 → sourcecode-3.8.0}/src/sourcecode/constraint_diff.py +0 -0
  71. {sourcecode-3.6.0 → sourcecode-3.8.0}/src/sourcecode/context_cache.py +0 -0
  72. {sourcecode-3.6.0 → sourcecode-3.8.0}/src/sourcecode/context_graph.py +0 -0
  73. {sourcecode-3.6.0 → sourcecode-3.8.0}/src/sourcecode/context_scorer.py +0 -0
  74. {sourcecode-3.6.0 → sourcecode-3.8.0}/src/sourcecode/context_summarizer.py +0 -0
  75. {sourcecode-3.6.0 → sourcecode-3.8.0}/src/sourcecode/contract_diff.py +0 -0
  76. {sourcecode-3.6.0 → sourcecode-3.8.0}/src/sourcecode/contract_model.py +0 -0
  77. {sourcecode-3.6.0 → sourcecode-3.8.0}/src/sourcecode/contract_pipeline.py +0 -0
  78. {sourcecode-3.6.0 → sourcecode-3.8.0}/src/sourcecode/coverage_parser.py +0 -0
  79. {sourcecode-3.6.0 → sourcecode-3.8.0}/src/sourcecode/dependency_analyzer.py +0 -0
  80. {sourcecode-3.6.0 → sourcecode-3.8.0}/src/sourcecode/deployment_prefix.py +0 -0
  81. {sourcecode-3.6.0 → sourcecode-3.8.0}/src/sourcecode/detectors/__init__.py +0 -0
  82. {sourcecode-3.6.0 → sourcecode-3.8.0}/src/sourcecode/detectors/base.py +0 -0
  83. {sourcecode-3.6.0 → sourcecode-3.8.0}/src/sourcecode/detectors/csproj_parser.py +0 -0
  84. {sourcecode-3.6.0 → sourcecode-3.8.0}/src/sourcecode/detectors/dart.py +0 -0
  85. {sourcecode-3.6.0 → sourcecode-3.8.0}/src/sourcecode/detectors/dotnet.py +0 -0
  86. {sourcecode-3.6.0 → sourcecode-3.8.0}/src/sourcecode/detectors/elixir.py +0 -0
  87. {sourcecode-3.6.0 → sourcecode-3.8.0}/src/sourcecode/detectors/go.py +0 -0
  88. {sourcecode-3.6.0 → sourcecode-3.8.0}/src/sourcecode/detectors/heuristic.py +0 -0
  89. {sourcecode-3.6.0 → sourcecode-3.8.0}/src/sourcecode/detectors/hybrid.py +0 -0
  90. {sourcecode-3.6.0 → sourcecode-3.8.0}/src/sourcecode/detectors/jvm_ext.py +0 -0
  91. {sourcecode-3.6.0 → sourcecode-3.8.0}/src/sourcecode/detectors/nodejs.py +0 -0
  92. {sourcecode-3.6.0 → sourcecode-3.8.0}/src/sourcecode/detectors/parsers.py +0 -0
  93. {sourcecode-3.6.0 → sourcecode-3.8.0}/src/sourcecode/detectors/php.py +0 -0
  94. {sourcecode-3.6.0 → sourcecode-3.8.0}/src/sourcecode/detectors/project.py +0 -0
  95. {sourcecode-3.6.0 → sourcecode-3.8.0}/src/sourcecode/detectors/python.py +0 -0
  96. {sourcecode-3.6.0 → sourcecode-3.8.0}/src/sourcecode/detectors/ruby.py +0 -0
  97. {sourcecode-3.6.0 → sourcecode-3.8.0}/src/sourcecode/detectors/rust.py +0 -0
  98. {sourcecode-3.6.0 → sourcecode-3.8.0}/src/sourcecode/detectors/systems.py +0 -0
  99. {sourcecode-3.6.0 → sourcecode-3.8.0}/src/sourcecode/detectors/terraform.py +0 -0
  100. {sourcecode-3.6.0 → sourcecode-3.8.0}/src/sourcecode/detectors/tooling.py +0 -0
  101. {sourcecode-3.6.0 → sourcecode-3.8.0}/src/sourcecode/doc_analyzer.py +0 -0
  102. {sourcecode-3.6.0 → sourcecode-3.8.0}/src/sourcecode/dynamic_argument_surface.py +0 -0
  103. {sourcecode-3.6.0 → sourcecode-3.8.0}/src/sourcecode/endpoint_literals.py +0 -0
  104. {sourcecode-3.6.0 → sourcecode-3.8.0}/src/sourcecode/endpoint_metrics.py +0 -0
  105. {sourcecode-3.6.0 → sourcecode-3.8.0}/src/sourcecode/entrypoint_classifier.py +0 -0
  106. {sourcecode-3.6.0 → sourcecode-3.8.0}/src/sourcecode/env_analyzer.py +0 -0
  107. {sourcecode-3.6.0 → sourcecode-3.8.0}/src/sourcecode/envelope.py +0 -0
  108. {sourcecode-3.6.0 → sourcecode-3.8.0}/src/sourcecode/error_schema.py +0 -0
  109. {sourcecode-3.6.0 → sourcecode-3.8.0}/src/sourcecode/evidence_provider.py +0 -0
  110. {sourcecode-3.6.0 → sourcecode-3.8.0}/src/sourcecode/facts/__init__.py +0 -0
  111. {sourcecode-3.6.0 → sourcecode-3.8.0}/src/sourcecode/facts/registry.json +0 -0
  112. {sourcecode-3.6.0 → sourcecode-3.8.0}/src/sourcecode/file_chunker.py +0 -0
  113. {sourcecode-3.6.0 → sourcecode-3.8.0}/src/sourcecode/file_classifier.py +0 -0
  114. {sourcecode-3.6.0 → sourcecode-3.8.0}/src/sourcecode/filter_surface.py +0 -0
  115. {sourcecode-3.6.0 → sourcecode-3.8.0}/src/sourcecode/format_contract.py +0 -0
  116. {sourcecode-3.6.0 → sourcecode-3.8.0}/src/sourcecode/fqn_utils.py +0 -0
  117. {sourcecode-3.6.0 → sourcecode-3.8.0}/src/sourcecode/git_analyzer.py +0 -0
  118. {sourcecode-3.6.0 → sourcecode-3.8.0}/src/sourcecode/graph_analyzer.py +0 -0
  119. {sourcecode-3.6.0 → sourcecode-3.8.0}/src/sourcecode/graph_evidence.py +0 -0
  120. {sourcecode-3.6.0 → sourcecode-3.8.0}/src/sourcecode/hibernate_strat.py +0 -0
  121. {sourcecode-3.6.0 → sourcecode-3.8.0}/src/sourcecode/integration_coordinates.py +0 -0
  122. {sourcecode-3.6.0 → sourcecode-3.8.0}/src/sourcecode/jdk_exports.py +0 -0
  123. {sourcecode-3.6.0 → sourcecode-3.8.0}/src/sourcecode/license.py +0 -0
  124. {sourcecode-3.6.0 → sourcecode-3.8.0}/src/sourcecode/mcp/__init__.py +0 -0
  125. {sourcecode-3.6.0 → sourcecode-3.8.0}/src/sourcecode/mcp/onboarding/__init__.py +0 -0
  126. {sourcecode-3.6.0 → sourcecode-3.8.0}/src/sourcecode/mcp/onboarding/applier.py +0 -0
  127. {sourcecode-3.6.0 → sourcecode-3.8.0}/src/sourcecode/mcp/onboarding/backup.py +0 -0
  128. {sourcecode-3.6.0 → sourcecode-3.8.0}/src/sourcecode/mcp/onboarding/detector.py +0 -0
  129. {sourcecode-3.6.0 → sourcecode-3.8.0}/src/sourcecode/mcp/onboarding/planner.py +0 -0
  130. {sourcecode-3.6.0 → sourcecode-3.8.0}/src/sourcecode/mcp/orchestrator.py +0 -0
  131. {sourcecode-3.6.0 → sourcecode-3.8.0}/src/sourcecode/mcp/registry.py +0 -0
  132. {sourcecode-3.6.0 → sourcecode-3.8.0}/src/sourcecode/mcp/runner.py +0 -0
  133. {sourcecode-3.6.0 → sourcecode-3.8.0}/src/sourcecode/mcp/server.py +0 -0
  134. {sourcecode-3.6.0 → sourcecode-3.8.0}/src/sourcecode/mcp_nudge.py +0 -0
  135. {sourcecode-3.6.0 → sourcecode-3.8.0}/src/sourcecode/metrics_analyzer.py +0 -0
  136. {sourcecode-3.6.0 → sourcecode-3.8.0}/src/sourcecode/migration_blast.py +0 -0
  137. {sourcecode-3.6.0 → sourcecode-3.8.0}/src/sourcecode/openapi_surface.py +0 -0
  138. {sourcecode-3.6.0 → sourcecode-3.8.0}/src/sourcecode/parse_cache.py +0 -0
  139. {sourcecode-3.6.0 → sourcecode-3.8.0}/src/sourcecode/path_admission.py +0 -0
  140. {sourcecode-3.6.0 → sourcecode-3.8.0}/src/sourcecode/path_filters.py +0 -0
  141. {sourcecode-3.6.0 → sourcecode-3.8.0}/src/sourcecode/perf.py +0 -0
  142. {sourcecode-3.6.0 → sourcecode-3.8.0}/src/sourcecode/pr_impact.py +0 -0
  143. {sourcecode-3.6.0 → sourcecode-3.8.0}/src/sourcecode/progress.py +0 -0
  144. {sourcecode-3.6.0 → sourcecode-3.8.0}/src/sourcecode/ranking_engine.py +0 -0
  145. {sourcecode-3.6.0 → sourcecode-3.8.0}/src/sourcecode/readiness_timeline.py +0 -0
  146. {sourcecode-3.6.0 → sourcecode-3.8.0}/src/sourcecode/reconciliation.py +0 -0
  147. {sourcecode-3.6.0 → sourcecode-3.8.0}/src/sourcecode/redactor.py +0 -0
  148. {sourcecode-3.6.0 → sourcecode-3.8.0}/src/sourcecode/reference_facts.py +0 -0
  149. {sourcecode-3.6.0 → sourcecode-3.8.0}/src/sourcecode/relevance_scorer.py +0 -0
  150. {sourcecode-3.6.0 → sourcecode-3.8.0}/src/sourcecode/rename_refactor.py +0 -0
  151. {sourcecode-3.6.0 → sourcecode-3.8.0}/src/sourcecode/repo_classifier.py +0 -0
  152. {sourcecode-3.6.0 → sourcecode-3.8.0}/src/sourcecode/retrieval/__init__.py +0 -0
  153. {sourcecode-3.6.0 → sourcecode-3.8.0}/src/sourcecode/retrieval/context.py +0 -0
  154. {sourcecode-3.6.0 → sourcecode-3.8.0}/src/sourcecode/retrieval/errors.py +0 -0
  155. {sourcecode-3.6.0 → sourcecode-3.8.0}/src/sourcecode/retrieval/executor.py +0 -0
  156. {sourcecode-3.6.0 → sourcecode-3.8.0}/src/sourcecode/retrieval/planner.py +0 -0
  157. {sourcecode-3.6.0 → sourcecode-3.8.0}/src/sourcecode/retrieval/query.py +0 -0
  158. {sourcecode-3.6.0 → sourcecode-3.8.0}/src/sourcecode/retrieval/request.py +0 -0
  159. {sourcecode-3.6.0 → sourcecode-3.8.0}/src/sourcecode/retrieval/resolution.py +0 -0
  160. {sourcecode-3.6.0 → sourcecode-3.8.0}/src/sourcecode/retrieval/retriever.py +0 -0
  161. {sourcecode-3.6.0 → sourcecode-3.8.0}/src/sourcecode/retrieval/runtime.py +0 -0
  162. {sourcecode-3.6.0 → sourcecode-3.8.0}/src/sourcecode/ris.py +0 -0
  163. {sourcecode-3.6.0 → sourcecode-3.8.0}/src/sourcecode/runtime_classifier.py +0 -0
  164. {sourcecode-3.6.0 → sourcecode-3.8.0}/src/sourcecode/scanner.py +0 -0
  165. {sourcecode-3.6.0 → sourcecode-3.8.0}/src/sourcecode/schema.py +0 -0
  166. {sourcecode-3.6.0 → sourcecode-3.8.0}/src/sourcecode/schemas/envelope-v1.schema.json +0 -0
  167. {sourcecode-3.6.0 → sourcecode-3.8.0}/src/sourcecode/security_config.py +0 -0
  168. {sourcecode-3.6.0 → sourcecode-3.8.0}/src/sourcecode/security_posture.py +0 -0
  169. {sourcecode-3.6.0 → sourcecode-3.8.0}/src/sourcecode/semantic_analyzer.py +0 -0
  170. {sourcecode-3.6.0 → sourcecode-3.8.0}/src/sourcecode/semantic_impact_engine.py +0 -0
  171. {sourcecode-3.6.0 → sourcecode-3.8.0}/src/sourcecode/semantic_integration_engine.py +0 -0
  172. {sourcecode-3.6.0 → sourcecode-3.8.0}/src/sourcecode/semantic_services.py +0 -0
  173. {sourcecode-3.6.0 → sourcecode-3.8.0}/src/sourcecode/spring_event_topology.py +0 -0
  174. {sourcecode-3.6.0 → sourcecode-3.8.0}/src/sourcecode/spring_model.py +0 -0
  175. {sourcecode-3.6.0 → sourcecode-3.8.0}/src/sourcecode/spring_properties.py +0 -0
  176. {sourcecode-3.6.0 → sourcecode-3.8.0}/src/sourcecode/spring_security_audit.py +0 -0
  177. {sourcecode-3.6.0 → sourcecode-3.8.0}/src/sourcecode/spring_semantic.py +0 -0
  178. {sourcecode-3.6.0 → sourcecode-3.8.0}/src/sourcecode/summarizer.py +0 -0
  179. {sourcecode-3.6.0 → sourcecode-3.8.0}/src/sourcecode/telemetry/__init__.py +0 -0
  180. {sourcecode-3.6.0 → sourcecode-3.8.0}/src/sourcecode/telemetry/config.py +0 -0
  181. {sourcecode-3.6.0 → sourcecode-3.8.0}/src/sourcecode/telemetry/consent.py +0 -0
  182. {sourcecode-3.6.0 → sourcecode-3.8.0}/src/sourcecode/telemetry/events.py +0 -0
  183. {sourcecode-3.6.0 → sourcecode-3.8.0}/src/sourcecode/telemetry/filters.py +0 -0
  184. {sourcecode-3.6.0 → sourcecode-3.8.0}/src/sourcecode/telemetry/transport.py +0 -0
  185. {sourcecode-3.6.0 → sourcecode-3.8.0}/src/sourcecode/test_sources.py +0 -0
  186. {sourcecode-3.6.0 → sourcecode-3.8.0}/src/sourcecode/tree_utils.py +0 -0
  187. {sourcecode-3.6.0 → sourcecode-3.8.0}/src/sourcecode/type_usage_surface.py +0 -0
  188. {sourcecode-3.6.0 → sourcecode-3.8.0}/src/sourcecode/validation_inference.py +0 -0
  189. {sourcecode-3.6.0 → sourcecode-3.8.0}/src/sourcecode/validation_surface.py +0 -0
  190. {sourcecode-3.6.0 → sourcecode-3.8.0}/src/sourcecode/verify_repo.py +0 -0
  191. {sourcecode-3.6.0 → sourcecode-3.8.0}/src/sourcecode/verify_rules.py +0 -0
  192. {sourcecode-3.6.0 → sourcecode-3.8.0}/src/sourcecode/version_check.py +0 -0
  193. {sourcecode-3.6.0 → sourcecode-3.8.0}/src/sourcecode/workspace.py +0 -0
  194. {sourcecode-3.6.0 → sourcecode-3.8.0}/supabase/functions/README.md +0 -0
  195. {sourcecode-3.6.0 → sourcecode-3.8.0}/supabase/functions/get-license/index.ts +0 -0
  196. {sourcecode-3.6.0 → sourcecode-3.8.0}/supabase/functions/lemonsqueezy-webhook/index.ts +0 -0
  197. {sourcecode-3.6.0 → sourcecode-3.8.0}/supabase/functions/telemetry/index.ts +0 -0
  198. {sourcecode-3.6.0 → sourcecode-3.8.0}/supabase/sql/license_event_ordering.sql +0 -0
  199. {sourcecode-3.6.0 → sourcecode-3.8.0}/supabase/sql/licensing_schema.sql +0 -0
  200. {sourcecode-3.6.0 → sourcecode-3.8.0}/supabase/sql/telemetry_events.sql +0 -0
@@ -1,5 +1,457 @@
1
1
  # Changelog
2
2
 
3
+ ## [Unreleased]
4
+
5
+ ## [3.8.0] — 2026-08-02
6
+
7
+ ### Added
8
+
9
+ - **The security surface publishes what it does not answer** (CL-2, CL-7, and the framing half
10
+ of CL-5). A report that lists what it found and says nothing about what it never looks at
11
+ invites silence to be read as absence — and the audit that raised this found a credential
12
+ versioned in three deployment descriptors *by hand*, because nothing here reads outside Java
13
+ and Spring configuration.
14
+ - One authority, `sourcecode/non_coverage.py`, read by three surfaces: the `non_coverage`
15
+ block in the `spring-audit` payload, the command's own `--help`, and the README section —
16
+ all rendered from the same table, because a curated list beside a generated one is how
17
+ `endpoints` went missing from every help list.
18
+ - Four rows for the security surface: no dataflow or taint (NC-001), no secrets outside Java
19
+ and Spring configuration (NC-002), filter-chain order not reconstructed (NC-003), no CVE
20
+ matching (NC-004). Each states why it is out of scope rather than unimplemented, and what
21
+ does answer it. Two more state the migration boundary (NC-005, OpenRewrite takes the
22
+ recipes this publishes) and the environment boundary (NC-006, answered as far as a
23
+ repository can by `posture --resolve-environments`).
24
+ - The evaluator's argument for publishing it is commercial, not ethical: *"un producto que
25
+ publica sus límites no se compara por amplitud; se compara por profundidad, que es donde
26
+ gana."*
27
+
28
+ ### Changed
29
+
30
+ - **Two claims corrected with measured figures.** `--compact` is documented as the smallest
31
+ answer, **not the cheapest run** — 13.3 s cold on BroadleafCommerce against `spring-audit`
32
+ 3.6 s and `posture` 1.9 s, 0.3 s warm — with the reason to warm before a session stated where
33
+ the claim is made (CL-3). And the product is positioned as the **diagnosis layer** until an
34
+ executor ships, in the field's own numbers (7/10 as a report generator, 5.5/10 as a
35
+ development tool) rather than argued with (CL-5).
36
+
37
+ - **`ask trend` is a top-level command, and capture is automatable** (P-4). The *series* is the
38
+ asset — a repository that captured a baseline at each release has a history nobody can
39
+ reconstruct afterwards, and one that did not never will — so reading it is no longer two words
40
+ deep, and [`docs/baseline-ci.yml`](docs/baseline-ci.yml) captures one per tag and publishes the
41
+ trend as a build artifact. `ask baseline trend` is the same command.
42
+ - The read-only half was a **documentation** gap and is closed where the auditor meets it:
43
+ `--dir` already existed, and the default now says *why* it is inside the repository (the
44
+ history travels with the code, not with a vendor) and that an audit which must leave the tree
45
+ untouched writes elsewhere. README and the user guide say the same.
46
+ - ⚠Adding the command surfaced the **C4-1 shape a sixth time**: `ask trend` was registered,
47
+ working and documented, and the CLI answered *"'trend' does not exist"* — because the
48
+ dispatcher matched against a **hand-written set of subcommand names**. It is derived from the
49
+ registry now, and the battery asserts every registered command is dispatchable.
50
+
51
+ - **`ask posture --resolve-environments` — which profile set actually runs, and the worst one
52
+ that could** (CL-8 / M9.5). `posture --diff` was called the strongest thing this product does
53
+ and it stopped at the repository boundary: which profile set runs is decided by the
54
+ deployment, so the answer was conditional and a field evaluator closed the last hops by hand
55
+ with `grep` (build profile → the property the build filters → a placeholder present in no
56
+ config file → no `context-param` in any descriptor → therefore nothing decides it).
57
+ - Those hops are now mechanical. Every artefact that can set `spring.profiles.active` is read
58
+ — config files, Maven/Gradle properties, `web.xml` context parameters, `Dockerfile` `ENV`
59
+ and `-D` arguments, Compose and Kubernetes manifests, launch scripts — each publishing what
60
+ it says with `file:line`. The verdict is `decided_in_repository`, `artefacts_disagree` (two
61
+ deployments, never a contradiction to resolve by picking one), or **`NOT DECIDED IN THIS
62
+ REPOSITORY`**.
63
+ - Every admissible profile set is then resolved over one parse and ranked by what it leaves
64
+ open, so the payload names the worst case and, where the repository does decide, how far the
65
+ shipped set is from it: *"one environment variable away from dev"*.
66
+ - **`open_by_rule` and `access_not_decided` are counted separately.** A readable rule that
67
+ permits a request unauthenticated is not the same fact as no readable rule matching it, and
68
+ folding them together would publish the confident security falsehood this command exists to
69
+ prevent. The reading says which is which.
70
+ - A value found in the repository is published as a default, never a guarantee:
71
+ `SPRING_PROFILES_ACTIVE` in the process environment outranks every artefact, and this
72
+ analysis cannot see the process environment.
73
+
74
+ - **`ask verify --init` derives the contracts a repository already satisfies** (C3-30). The gate
75
+ had no way to acquire what it gates on: nobody hand-writes contracts for a 3 300-file
76
+ monolith, so the honest gate (zero contracts is `unverified`, closed as C3-15) stayed empty —
77
+ and the gate is the recurring half of the value story, where an audit is bought once.
78
+ - Three shapes, each written with the measurement behind it: a path prefix whose endpoints all
79
+ carry the same policy today (`require_endpoint_security`), an audit pattern that fires
80
+ nowhere (`forbid_finding`), and an injection edge between two annotated populations that
81
+ does not occur, both populations large enough that the absence is a pattern rather than an
82
+ accident (`forbidden_edge`).
83
+ - **Every rule is executed before it is written.** The derived set runs through the same engine
84
+ `verify` runs, and anything that fails on the tree it came from is dropped and reported —
85
+ `verify --init` followed by `verify` passes by construction, asserted as a round trip in the
86
+ battery, together with the proof that the populated gate goes red when the invariant breaks.
87
+ - Violations that exist today are deliberately not proposed: that is debt for
88
+ `--capture-baseline`, a different claim from an invariant, and the payload says so per
89
+ rejected candidate.
90
+ - `--dry-run` prints without writing; an existing contracts file is never replaced without
91
+ `--force`.
92
+
93
+ - **`delta` and `contract-diff` take git refs** (C3-33). Both compared two *checkouts* while
94
+ `review-pr` in the same CLI already took `--since`, so comparing two commits meant
95
+ orchestrating worktrees first. In the evaluation that recorded this, that cost coverage rather
96
+ than convenience: the evaluator ran the full catalogue against a client monolith under a
97
+ promise to leave the environment byte-identical and **omitted both commands** rather than
98
+ create worktrees in someone else's repository.
99
+ - `ask delta --base-ref origin/main --head-ref HEAD [--repo <path>]`, same for
100
+ `contract-diff`. Two checkouts positionally still work, and the payload publishes a
101
+ `comparison` block saying which basis it used — with both refs and their resolved commits.
102
+ - **Reading a ref writes nothing to the repository.** `git archive` streams the tree into a
103
+ temporary directory that is removed on the way out: no `git worktree add` (which registers
104
+ administrative state under `.git/worktrees` and leaves it behind if the process dies), no
105
+ checkout, no stash, no index read. The battery asserts `git status` and `git worktree list`
106
+ are identical before and after.
107
+ - A ref this repository does not have is refused by name (`git_ref_not_found`, exit 1) and
108
+ never substituted with something nearby.
109
+
110
+ ### Fixed
111
+
112
+ - **`retrieve` stopped publishing scores nothing computed** (C3-19, **`entities[].score` and
113
+ `explanation.score` are nullable**). `retrieve blast-radius` returned eighty dependents each
114
+ carrying `"score": 0.0`, beside an explanation whose own score was 92.43 — and the step that
115
+ orders those entities says in its own docstring that no score is computed. The same default put
116
+ a zero on every entity of every intent, and an `explanation` block with `winner: null,
117
+ score: 0.0` on the intents that return what they found rather than choose a winner: the shape
118
+ the field called *a ranking block that never ran*.
119
+ - Both fields are `None` when nothing wrote them. The order is real and structural, so the
120
+ payload states it: `entities_ranked_by` — *"reach from the target (direct before indirect),
121
+ then identity — a structural order, not a per-entity score"*.
122
+ - `retrieve` remains `[PARKED]`; this is the honesty fix the tier does not excuse.
123
+
124
+ - **`archetype` no longer scores an unmeasured HTTP surface as an absent one** (C3-7). The
125
+ command declares `endpoints` as a missing signal on runs with no root to read — and then
126
+ scored as if the answer were **0**, which is a measured statement. Inside the scorer that zero
127
+ did two things at once: it refuted `api-first` and it fired `worker`'s `event_no_http`
128
+ evidence, so a repository nobody measured came back classified as an event worker with the
129
+ reason published as if it were a finding (I-3/R9, inside a score).
130
+ - The count is nullable now. Unmeasured contributes nothing and says so in its own evidence
131
+ row; `event_no_http` requires the absence of HTTP as a *measured* fact. A measured zero
132
+ behaves exactly as before, which the battery asserts alongside the unmeasured case.
133
+ - Measured while closing it, and recorded rather than acted on: `archetype` on
134
+ BroadleafCommerce takes **9.3 s** (the field reported 22 s) and returns two high-confidence
135
+ dimensions of four, so the tier stays `[EXPERIMENTAL]` — the cost complaint does not
136
+ reproduce at that magnitude, and a command with two high-confidence answers is not a
137
+ candidate for `parked`.
138
+
139
+ - **The summary stopped costing more than the analyses it summarises** (C3-6, C3-21). Measured on
140
+ BroadleafCommerce with nothing warm: `--compact` **19.3 s → 13.3 s**, and with the parse cache
141
+ warm **14.0 s → 7.9 s**; `endpoints` **3.3 s → 1.4 s**. Two duplications inside one process, both
142
+ removed:
143
+ - The **core view was built twice on every cold run** — once for the L1 cache write and once for
144
+ the RIS update — and building it rebuilds the CIR. One repository state has one core view; both
145
+ writers now read it.
146
+ - The **endpoint extractor parsed every file itself** while `build_repo_ir` read the
147
+ content-addressed parse cache for the same bytes. A run that does both paid for the same parse
148
+ twice, and a warm cache measurably bought `endpoints` nothing — a fact this product published
149
+ in its own cache model. Same key, same extractor, same capture signature: the entry either side
150
+ writes is the entry the other reads. The cache-model rows for `endpoints` and the root command
151
+ are re-measured accordingly.
152
+ - The inversion is **narrowed, not gone**: `--compact` is still slower than `spring-audit`
153
+ (3.6 s) or `posture` (1.9 s), because it builds the summary *and* the core view where those
154
+ build one analysis each.
155
+ - **C3-21 does not reproduce on 3.7.0**: the cache hit that cost 2 647 ms now costs 1.6 s for
156
+ `explain` against a 1.6 s cold run, and the snapshot hit for `--compact` is 0.29 s. Recorded as
157
+ measured, not assumed closed.
158
+ - The battery pins the two mechanisms rather than wall-clock figures: a second extraction must
159
+ re-parse nothing, the cached and uncached answers must be identical, and one root run must
160
+ build the core view once.
161
+
162
+ - **A comment can no longer take a whole file out of the graph** (E-1). The declaration joiner
163
+ decided whether a line *starts* a type declaration by scanning raw text, so a comment carrying
164
+ `class` or `interface` followed by an identifier looked like a declaration head with its brace
165
+ on a later line — `/** Implements the interface only for the legacy path. */`, or a trailing
166
+ `// starter class is not an utility class` on an annotation. The join then swallowed the
167
+ annotation and the real declaration into one entry beginning with `@`, which the parser reads
168
+ as a pending annotation and never examines: the file contributed **zero symbols** — no type,
169
+ no endpoint, no transaction boundary — and a file that contributes nothing looks exactly like
170
+ a file with nothing in it, which is why no field report could ever name this.
171
+ - Comments are stripped before the keyword scan (block state carried across lines, string
172
+ literal aware), and the brace that ends a join must also be code, so a commented `{` no
173
+ longer cuts a real multi-line declaration in half.
174
+ - Measured A/B over six repositories: **open-banking-gateway recovers 6 types, three of them
175
+ Spring Boot application classes**; petclinic, eureka, openmrs-core, BroadleafCommerce and
176
+ keycloak are unchanged, and **no repository loses a symbol**.
177
+
178
+ - **`generate-tests` ranks by what depends on the file, not by how the file is named**
179
+ (C3-13, **`untested_sources[]` entries change shape**). Two rules, both name matching, both
180
+ measured on openmrs-core: admission kept only files whose name ends in one of five suffixes
181
+ (`Service.java`, `Controller.java`, `Repository.java`, `Mapper.java`, `RestController.java`),
182
+ reducing **866 production files to 11 candidates**; and coverage was a filename pair, so
183
+ `PersonServiceImpl` was a gap for want of a `PersonServiceImplTest`. What remained was ordered
184
+ by how often the substring `"public "` appears in the first 16 KB — while `blast_radius`,
185
+ transaction boundaries and endpoint exposure were already computed elsewhere in the same
186
+ product and never consulted.
187
+ - **Coverage is now a reach fact**: a type is covered when a test source reaches it — named
188
+ directly, or reached along the call, instantiation and injection edges a blast radius
189
+ already walks, through the interface the container wires it behind, or as a supertype of
190
+ something a test exercises. One forward traversal from every test type: 0.01 s on
191
+ BroadleafCommerce. Reaching is not asserting, so the coverage figure is a floor and the gap
192
+ list is a ceiling, and `notes` says so.
193
+ - **Admission is the population**, not a naming convention: openmrs-core 866 production files
194
+ → **161 untested**, BroadleafCommerce 2 765 → **1 494**, published as `population` beside
195
+ the list.
196
+ - **Order is the measured axes** — endpoints reached, transaction boundaries declared, classes
197
+ that depend on it — reusing `caller_reach`, `spring_impact._collect_endpoints` and
198
+ `spring_semantic.boundaries_declared_within` rather than deriving them again. The weights
199
+ that fold the three into `score` are published with `rank_weights_basis: "assumption, not a
200
+ measurement"`, and the order is reproducible from the axes without accepting them.
201
+ - `untested_sources[]`/`test_gaps[]` rows drop `rank_score`, `public_method_count` and
202
+ `has_framework_annotations` — measurements of the replaced basis — and carry
203
+ `endpoints_reached`, `transaction_boundaries` and `caller_classes` instead. `path`, `score`
204
+ and `reason` are unchanged. The new `test_gap_ranking` block publishes the basis, the
205
+ population and the caps.
206
+ - Cost, measured cold: BroadleafCommerce 11.1 s → **15.3 s**, openmrs-core 5.1 s → 10.2 s. A
207
+ run whose IR cannot be built keeps the filename algorithm and publishes the
208
+ `test_reach_graph` signal with what taking it costs the answer (I-8).
209
+
210
+ - **`generate-tests` publishes its time budget, and a cache no longer defeats it** (C3-1). The
211
+ 30 s cap was reachable only through `SOURCECODE_TESTS_TIMEOUT_MS`, a name in no help text —
212
+ the one knob that turns an empty answer into an answer was invisible to whoever was holding
213
+ the empty answer. `--timeout <seconds>` is now a documented flag (the variable still works;
214
+ the flag wins), and an exhausted budget publishes `analysis_budget` carrying the new
215
+ `time_budget` cap: *"an empty list here means the walk stopped, NOT that the repository has
216
+ nothing"*, with the budget, its source, and how to raise it.
217
+ - Closing it surfaced a sharper defect, measured: **the cache key ignored the budget**, so a
218
+ run that exhausted 2 s answered the re-run at 30 s from cache — the remedy the payload
219
+ names did nothing at all. The budget is now part of the cache identity, and an exhausted
220
+ result is never stored: an unfinished walk is worth re-running.
221
+ - Measured while closing it: the full scan on openmrs-core (3 300 files, cold cache) takes
222
+ **3.35 s** and returns 13 untested sources, so the field's empty payload does not reproduce
223
+ and the default budget is not the constraint it was taken for. The ranking half of C3-13
224
+ stays open — the command still matches file names while `blast_radius`, transactional
225
+ writes and endpoint exposure are already computed.
226
+
227
+ - **`review-pr` no longer counts documentation as a runtime change** (C3-11b). The field
228
+ reported a diff of 227 `.md` files as `runtime_changes: 228` — while every one of those
229
+ entries carried `artifact_type: "documentation"` and `change_effect: "documentation file (no
230
+ runtime impact)"`. The list contradicted its own members. Reproduced on a real git repository
231
+ (12 `.md` files + one touched controller): **13 → 1**. The classifier was never wrong;
232
+ membership was "not noise and not a build manifest", which admits everything else, and the
233
+ admission seam (K2) now asks whether the admitted type can carry runtime behaviour at all.
234
+ - Nothing is dropped: the twelve are reported under `non_runtime_changes` with the same
235
+ evidence and effect statement, and the GitHub comment names them by count so it cannot look
236
+ like it missed part of the diff.
237
+ - The split is asserted **against the effect statements themselves** — a type whose published
238
+ statement disclaims impact must be in the non-runtime set — so it cannot drift from the
239
+ prose it is derived from (C4-1).
240
+
241
+ - **One profile population, whatever surface is asked** (C1-18, **`spring_profiles` changes on
242
+ repositories with resource bundles or resource folders**). Reproduced on a fixture first: the
243
+ same repository in one session answered `["qa","dev"]` in the default view, `["dev","prod",
244
+ "staging"]` in `posture` and `["dev","prod","qa","staging"]` under `--agent`. Three
245
+ populations under one name — and every conditional-security finding is keyed on that set, so
246
+ the default agent surface was answering the profile question with the population that had
247
+ lost the environments.
248
+ - Authority `spring_profiles.profile_population`: four named signals — the
249
+ `application-{profile}` filename, the per-environment overlay directory,
250
+ `spring.config.activate.on-profile` / `spring.profiles` inside config documents, and
251
+ `@Profile` on a bean — unioned once, with `by_signal` published so each name's provenance
252
+ is auditable. The Java stack detector, `posture` and the serializer's profile section all
253
+ read it, asserted per surface.
254
+ - Closing it exposed two false positives in the signals it inherited, both fixed
255
+ structurally rather than by name (VAI): an `application-{x}` file counts only **beside its
256
+ base config** — alfresco-community-repo's `alfresco/messages/application-model_de.properties`
257
+ and 19 siblings were reported as twenty environments, now none — and an overlay directory
258
+ counts only when it **holds a config file** — spring-petclinic's `db/`, `messages/`,
259
+ `static/` and `templates/` were reported as four environments, now `mysql, postgres`, its
260
+ real profiles.
261
+
262
+ - **The token-saving ratio is published, and published as a ceiling** (CL-1). `token_economy`
263
+ emitted `emitted`, `baseline_raw_read` and `saved` — three numbers a reader divides into a
264
+ multiple and then quotes. The multiple travelled without the label the block put on the
265
+ inputs, which is how "up to 55×" ends up in a room. `ratio_upper_bound` is now emitted with
266
+ a `ratio_basis` that states the counterfactual making it a ceiling — every cited file and
267
+ build manifest read **in full and once** — the band we measured for the ceiling itself
268
+ (**3.8×–37.6×** over `--compact` and `--agent` on spring-petclinic, BroadleafCommerce,
269
+ openmrs-core and keycloak; nothing near 55×), and the field's 10×–20× read of the saving an
270
+ agent actually realizes.
271
+ - `realized_saving` is `null` with its reason rather than a number: which files an agent would
272
+ truly have read is not observable from this process, and a `0` there would read as "no
273
+ saving" (I-3).
274
+
275
+ - **`spring-audit` counts defects as well as observations** (C2-5). A rule fires per
276
+ observation; a reader counts repairs. The audit published only the first number and let it
277
+ stand for the second: on openmrs-core `ConceptServiceImpl#checkIfLocked` carried **six
278
+ TX-006 findings, one per call site, for one annotated method with one fix**, and the
279
+ ledger's original witness is a private `@Transactional` method that draws TX-001 *and*
280
+ TX-006 for the same repair. Measured on the fleet: **openmrs-core 38 findings → 29
281
+ defects, BroadleafCommerce 19 → 14**.
282
+ - A defect is `(category, defect_kind, symbol)` — the thing you edit, and what is wrong
283
+ with it. `defect_kind` is **declared by the rule itself** (TX-001 and TX-006 both
284
+ declare `proxy_bypass`) and defaults to the rule's own id, so a rule that declares
285
+ nothing is never merged into another by omission, and there is no rule table maintained
286
+ beside the rules to drift out of date (C4-1).
287
+ - Nothing is filtered. `findings[]` keeps every observation and each one now names its
288
+ `defect_id`; the new `defects[]` rows carry `rule_ids`, `witness_count` and the witness
289
+ ids, so the grouping is auditable in both directions. `summary` publishes
290
+ `total_findings`, `total_defects`, `defects_by_severity` and a `counts_note` stating
291
+ which is which — `by_severity` and `by_category` keep counting observations, because a
292
+ count that changes basis under an unchanged name is the same defect wearing a new suit.
293
+ - A defect takes the **strongest** severity and confidence among its witnesses, and its id
294
+ is keyed on the identity, not the witnesses — acquiring a second witness next run does
295
+ not rename it, so a baseline keeps matching it.
296
+
297
+ - **`migrate-check` lists the blockers; hygiene is counted, not listed** (C2-6, **default
298
+ payload changes**). On openmrs-core the default report carried 310 findings of which **184
299
+ were `java_8_best_practice` advisory hygiene** — findings that block no version and that
300
+ every readiness score already excludes. A reader scanning the array met three advisory
301
+ entries for every two blockers. The emitted list now carries the blockers, ordered
302
+ most-severe first (**310 → 126 listed, 912 KB → 717 KB**), and `--include-hygiene` restores
303
+ the entries.
304
+ - **The floor cuts the list, never a figure.** `summary.by_severity`, `by_rule`,
305
+ `by_migration_target`, `total_findings`, `hygiene_findings`, `blocking_count` and every
306
+ dimension score are byte-identical to the unfloored run and still cover the whole
307
+ population — verified as an equality, not a claim.
308
+ - It is published as a cap, not applied in silence: `findings_floor` (the `severity_floor`
309
+ row of `CAP_EFFECTS`, I-8) states what was removed, what stayed exact, and the flag that
310
+ restores it, so `len(findings)` is never read as the total.
311
+ - The other half of the ledger row — "headline score reads 0/100 while real blockers are
312
+ 481" — was already closed and re-measured here: hygiene is out of the aggregate, and
313
+ openmrs's 0 is `min(jakarta 0, hibernate 0)` with `jdk_modernization` (58) excluded by
314
+ design. The score was honest; the finding list was the noise.
315
+
316
+ ## [3.7.0] — 2026-08-01
317
+
318
+ **The exit-code contract and the C3 surface block.** Seven rows closed: the two the field named
319
+ as blocking for CI (exit codes over correct answers), the fourth and fifth appearance of a
320
+ curated list beside real data, and three surfaces that published a promise the payload did not
321
+ keep.
322
+
323
+ Minor and not patch, because a pipeline can see the difference: `plan` exits 1 where it exited 0
324
+ over a target it never resolved (C3-29), `ask <cmd> | head` exits 0 where a correct run used to
325
+ exit non-zero (C3-28), `--output FILE` carries the whole answer where it was silently trimmed
326
+ (C3-17), `--agent` publishes sections it used to omit (C3-10), and a path-shaped target that was
327
+ refused as ambiguous now resolves (C3-35).
328
+
329
+ ### Fixed
330
+
331
+ - **A broken output pipe is no longer a failed run** (C3-28, **exit code changes for
332
+ `ask <cmd> | head`**). `ask repo-ir . --force | head -c 100` returned the correct bytes and
333
+ exit 1; under `set -e` that stops a pipeline with no error anywhere to explain it — the field
334
+ named it one of two blockers for CI. One authority now says what a closed stream means
335
+ (`pipe_contract.py`, installed at the entry point): **a broken output stream changes nothing
336
+ except where the remaining bytes go.** The descriptor is redirected to the null device on the
337
+ first broken write and the command finishes and exits on its own terms.
338
+ - **It does not overwrite the command's own verdict.** `ask impact <ambiguous target> | head`
339
+ still exits 1, because a consumer that stopped reading has no opinion about whether the
340
+ analysis resolved its target.
341
+ - Redirecting before the shutdown flush is what keeps Python from printing
342
+ `Exception ignored in: <_io.TextIOWrapper …>` and exiting 120 — the same defect wearing a
343
+ different number.
344
+ - **The wrapper covers `.buffer`, which is the whole fix**: payloads are written as bytes
345
+ through `sys.stdout.buffer` at the single emit seam, so a text-only wrapper sits beside the
346
+ one write this exists for. Measured: with the text wrapper alone, nothing changed.
347
+ - Only visible above a pipe buffer, which is why it looked intermittent: `endpoints` on a
348
+ small repository exits 0 either way, `repo-ir` on the same repository did not.
349
+
350
+ - **An unresolved target has one exit code across every command** (C3-29, **`plan` now exits 1
351
+ where it exited 0**). `plan <unknown> <repo>` ran to completion, emitted a plan-shaped payload
352
+ of zeros with `resolution: "not_found"` and exited **0**, while `impact` on the same input
353
+ exited 1 — so a gate could not tell "nothing to review" from "I never found what you asked
354
+ about". One authority (`target_admission.py`), four commands rebound (`impact`,
355
+ `impact-chain`, `plan`, `explain`), and the two other copies of the same literal set
356
+ (`compare`, `change_plan`) now read it instead of restating it.
357
+ - **Ambiguity is the same fact, and it was not in the field report.** A target matching
358
+ several classes returns `ambiguous_path`, empty results and a message asking for the full
359
+ FQN — the command declined to answer — and `impact` exited **0** on it. Measured on a
360
+ purpose-built two-class fixture, since no battery repository carries the shape.
361
+ - Unresolved is **1, not 2**: 2 is reserved by the `verify` family for a run that could not
362
+ look, and this run looked. Partial and expanded resolutions stay 0 — they are answers about
363
+ the target the caller named.
364
+ - `plan`'s `Note:` on stderr is gone with it: the payload already carries the statement, and
365
+ a successful-looking run should not be narrating on stderr (the `plan` half of C3-34).
366
+
367
+ - **`--help` reaches inside command groups** (C4-7). `ask cache model` — what a warm buys each
368
+ command, per layer, including the commands it buys nothing for — appeared in no help text at
369
+ all: the root catalogue was generated (C4-1/C4-2) but the Cache and Auth blocks under it were
370
+ three lines somebody typed by hand. The blocks are now built from the registered groups, so a
371
+ subcommand is listed the moment it is registered; a group too large to name in full (`retrieve`,
372
+ 29 parked intents) publishes its **exact count** and a pointer, never silence. The battery
373
+ fails if a subcommand of a listed group is missing, or if a collapsed group's count drifts.
374
+
375
+ - **A successful run says nothing on stderr — measured over the commands, not over a list**
376
+ (C3-34, the `repo-ir` half). `ask repo-ir . --force` wrote an 82-byte size advisory on a run
377
+ that exited 0 with the IR on stdout, which PowerShell 5.1 raises as a `NativeCommandError`.
378
+ The advisory is terminal-gated now, like every other notice, and so is the `--exclude`
379
+ directory warning and the output-budget trim warning found beside it.
380
+ - **The list was the defect.** `tests/test_stderr_purity_matrix.py` enumerated 13 commands by
381
+ hand for the fourth time in three releases; the rows are now **discovered from the CLI**,
382
+ with every command either driven or carrying a written reason it cannot be. Nine more
383
+ commands are driven as a result, `cache` subcommands included.
384
+ - The `repo-ir` row builds a repository large enough for the advisory to actually fire and
385
+ **asserts it fired**, because a row that never reaches the branch proves nothing.
386
+
387
+ - **`--output FILE` is no longer trimmed to an agent's context window** (C3-17). The payload
388
+ budget exists because a context window is finite — it is a constraint on **stdout**. Written
389
+ to a file it cut the answer anyway, dropped `key_dependencies` entirely, and the note
390
+ explaining the cut advised `--output`, the flag already in use. Two of six call sites had the
391
+ rule and four did not (`prepare-context`, `modernize`, the cached-view rebuild, and `impact`
392
+ in part), so it now lives in one seam (`cli._apply_budget`) and a battery fails if a seventh
393
+ call site decides for itself.
394
+ - **The cache had the same defect one layer down**, found while field-checking the seam:
395
+ `prepare-context` stored the document *after* trimming, so the first stdout run poisoned the
396
+ cache and every later `--output FILE` hit received a stdout-sized answer. The cache stores
397
+ the analysis now and the budget is applied per run — measured on alfresco-community-repo:
398
+ stdout 5 files, cache hit to a file 26.
399
+ - **`--full` says what it does.** It raises the caps (boundaries and DTO mappers in full,
400
+ `file_relevance` to 40); it never removed them — under `--agent --full` the file list stayed
401
+ capped at 40 of 710 while the flag's help promised "remove truncation limits".
402
+
403
+ - **`--agent` cannot publish less than `--compact`** (C3-10). `--compact` documents
404
+ `security_surface` "when custom security annotations detected" and closes with "use `--agent`
405
+ for maximum signal", while `--agent` was assembled from its own hand-written list of sections:
406
+ measured on BroadleafCommerce it omitted `deployment` and `language_version` outright, and
407
+ nothing stopped the security surface going the same way. Both views now read one authority
408
+ (`serializer.JAVA_SPRING_SECTIONS`), and the battery fails on any section `--compact` publishes
409
+ that `--agent` does not.
410
+
411
+ - **A path that names one file resolves to that file** (C3-35). Every resolver reduced a
412
+ path-shaped target to its basename before anything looked at it, so
413
+ `ask impact src/main/java/com/a/Service.java` answered `ambiguous_path` and offered
414
+ `com.a.Service` **and** `com.b.Service` — being more specific made the answer worse. A path is
415
+ matched against the `source_file` each symbol came from, strongest tier first (exact, then
416
+ module-relative, then parent-relative), and nested types collapse to the type the file is about
417
+ (on eureka, `DiscoveryClient.java` declares its outer class and five inner ones). One authority
418
+ in `target_admission`, because three graphs answer target questions — the repo IR, and the CIR
419
+ that `explain` and `impact-chain` read, both of which used to answer `not_found` for a path.
420
+ Parity checked on eureka: by path and by name give byte-identical `stats`.
421
+
422
+ - **`verify-edit` stops paying for a diff it has already proved empty** (C3-32). It computed the
423
+ change set and then built the HEAD CIR *and* the working CIR unconditionally — on a clean tree
424
+ the second is the first by construction. Measured on a clean ofbiz-framework: **5.9 s -> 1.7 s**
425
+ warm. The shortcut is taken only when git actually answered: a failed `git diff` also returns an
426
+ empty list, and reading that as "nothing changed" would trade dead cost for a false green.
427
+
428
+ - **`spring-audit --compact`** (C3-31). The one analysis command with no summary mode: 1.99 MB for
429
+ 14 findings in the field, *"a context overflow against an LLM with no filter in between"*. The
430
+ weight is not the findings — on BroadleafCommerce `security_posture.endpoints` is 113 KB of a
431
+ 178 KB report, and the counts it supports are published beside it. `--compact` caps that list and
432
+ `findings` to their top 5, ordered by what asks something of the reader (`probably_exposed`
433
+ first; most severe first), and recomputes nothing: **178 KB -> 25 KB with every count
434
+ identical**. A flag changes how much is emitted, never the shape (C2-10) — each list stays a list
435
+ and the totals live in a `*_cap` sibling that exists only when the cap bit.
436
+
437
+
438
+ ### Documentation
439
+
440
+ - **Field evaluation #6 of 3.5.0 recorded** (`.planning/FIELD-EVAL-6-2026-08-01.md`, defect
441
+ ledger, development roadmap). Full 27-command catalogue, repository left byte-identical,
442
+ scored 8/10. Every reported defect was re-measured on 3.6.0 before it was written down: two
443
+ do not reproduce (one closed here as C3-15, one by the 3.5.0 admission authority) and the
444
+ re-measurement found two the evaluation did not report.
445
+ - **New rows**: C1-18 (profile population differs per command, and the narrower one is what an
446
+ agent reads) · C3-28/C3-29 (**exit codes that lie over correct answers** — a broken pipe
447
+ exits non-zero on a successful run, `plan` exits 0 on a target it did not resolve while
448
+ `impact` exits 1) · C3-30 (`verify --init`) · C3-31…C3-34 · C4-7 (`cache model` in no help
449
+ panel) · P-4 (`baseline` history nobody automated) · CL-7 (non-coverage: no dataflow, no
450
+ secrets outside Java/YAML, filter order not reconstructed) · CL-8 (`posture --diff` answers
451
+ conditionally because the profile is decided outside the repository).
452
+ - **The executive roadmap gains what the product does *not* do**, published beside the
453
+ capabilities, and the evaluation table is current through eval #6.
454
+
3
455
  ## [3.6.0] — 2026-08-01
4
456
 
5
457
  **The P0 block and the C1/C2 backlog.** Nine rows closed, three closed by measurement alone
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: sourcecode
3
- Version: 3.6.0
3
+ Version: 3.8.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
@@ -251,7 +251,7 @@ from it.
251
251
  | `review-pr` / `fix-bug` / `prepare-context` | supported | diff review, symptom triage, task-shaped context | |
252
252
  | `plan` / `compare` / `delta` / `contract-diff` | supported | what to review for a change; candidates by measured cost; outcome of a change; public-contract break | no verdicts, measured cost only |
253
253
  | `validation` | supported | request-body validation coverage and gaps | |
254
- | `baseline capture\|diff\|trend` | supported | versioned architectural metrics over time | trend reporting, not gating |
254
+ | `baseline capture\|diff` · `trend` | supported | versioned architectural metrics over time; `ask trend <dir>` reads the series | trend reporting, not gating. Baselines land in `.ask/baselines` **inside the repository** — the history travels with the code, not with a vendor; an audit that must not write passes `--dir`. Automate it: [baseline-ci.yml](docs/baseline-ci.yml) |
255
255
  | `retrieve` | parked | typed knowledge queries over the model | |
256
256
  | `archetype` | experimental | evidence-based architectural archetype | |
257
257
  | `rename-class` / `chunk-file` | supported | word-boundary Java rename; split a large file for an agent | |
@@ -275,6 +275,34 @@ Honest limits worth knowing before you rely on it:
275
275
  - Architecture classification is tuned for Spring MVC layered apps; SPI/plugin models (e.g. Quarkus extensions) may be misclassified. JAX-RS subresource-locator endpoint recall is ~65%.
276
276
  - Self-invocation `@Transactional` bypass (same-class call skipping the proxy) is not detected.
277
277
 
278
+ ### What the security surface does not answer
279
+
280
+ Published because a product that states its limits is not compared on breadth — it is
281
+ compared on depth. Each row is emitted in the payload too (`non_coverage`), so an agent
282
+ reading JSON sees the same boundary a buyer reads here.
283
+
284
+ | Not covered | Why | What answers it |
285
+ |---|---|---|
286
+ | **Whether request input reaches a sink — no dataflow or taint analysis.** | This engine resolves structure and wiring without compiling. Taint needs value flow through a program, which is a different analysis with a different failure mode: an unsound one produces confident findings that are wrong, and every claim here is meant to be checkable against the line that produced it. | A dataflow scanner (Semgrep, CodeQL). What this product adds on top is reachability: which of that tool's findings sit behind an endpoint that is reachable unauthenticated. |
287
+ | **Secrets outside Java and Spring configuration — a credential in a deployment descriptor, a Helm value, a CI variable file.** | The file population this analyzer reads is the Java source and the Spring configuration convention. A secret elsewhere is not missed by a weak rule; it is outside the set of files anything here opens. | A dedicated secret scanner over the whole tree (gitleaks, trufflehog). |
288
+ | **Filter-chain order and per-filter URL patterns — the presence of a custom filter is structural only.** | Which filter runs first is decided by bean ordering this analyzer does not resolve. Where two active configurations both match a request, the answer published is `undecided` rather than a guess. | `ask posture --profile <set>` states per endpoint what the readable rules decide and what they leave undecided. |
289
+ | **Known vulnerabilities in dependencies — no CVE database, no version advisory matching.** | Enriching a vulnerability feed is a different product with a different update cadence; a stale embedded database is worse than no database, because it reads as a clean bill of health. | A dependency scanner (Trivy, OWASP Dependency-Check). `impact-chain` then answers which of its findings anything actually reaches. |
290
+
291
+ Two more boundaries worth stating in the same voice:
292
+
293
+ | Not covered | Why | What answers it |
294
+ |---|---|---|
295
+ | **Applying a migration — nothing here edits source.** | This is the diagnosis layer: it measures what must change and what each change would reach. Rewriting code is an execution problem with an established executor, and duplicating it would mean maintaining a second, worse one. | OpenRewrite. `migrate-check` publishes the recipe each finding carries (`recipes[]`), which is the input that executor takes. |
296
+ | **What the process environment sets at start-up — the profile set, properties and secrets a container is given.** | Nothing in a repository can observe the environment of a process that has not started. A value read from a file here is the default the repository ships, never a guarantee of what runs. | `ask posture --resolve-environments` reads every artefact in the repository that names the profile set, says when none of them decides it, and ranks the admissible sets by what each leaves open. |
297
+
298
+ **Positioning.** Until an executor ships, this is the **diagnosis layer**: it measures what
299
+ must change, what each change reaches, and what a gate should block — and it removes none of
300
+ it. Field evaluation scored it 7/10 as a report generator and 5.5/10 as a development tool,
301
+ and that gap is the honest description, not a defect to argue with. `migrate-check` publishes
302
+ the OpenRewrite recipe each finding carries so the executor that does apply changes has its
303
+ input.
304
+
305
+
278
306
  ---
279
307
 
280
308
  ## Pricing
@@ -348,7 +376,8 @@ Matching endpoints report `policy: "custom"` and drop out of the `no_security_si
348
376
  | Doc | What it covers |
349
377
  |-----|----------------|
350
378
  | [USER_GUIDE.md](docs/USER_GUIDE.md) | Full command reference, flags, output schema, workflows |
351
- | [contracts.md](docs/contracts.md) | Declare invariants in `.ask/contracts.yml`, enforce them in the edit loop and in CI |
379
+ | [contracts.md](docs/contracts.md) | Declare invariants in `.ask/contracts.yml` (or derive them with `ask verify --init`), enforce them in the edit loop and in CI |
380
+ | [baseline-ci.yml](docs/baseline-ci.yml) | Capture an architectural baseline per release, so the series exists when you want to read it |
352
381
  | [posture.md](docs/posture.md) | What a profile set actually wires — down to which endpoints its filter chain permits — and what could not be decided (experimental) |
353
382
  | [migrate-check.md](docs/migrate-check.md) | Migration rule catalogue (MIG-001..043) + Hibernate stratification |
354
383
  | [MODERNIZATION.md](docs/MODERNIZATION.md) | The modernization product: assess → understand → plan → execute |
@@ -213,7 +213,7 @@ from it.
213
213
  | `review-pr` / `fix-bug` / `prepare-context` | supported | diff review, symptom triage, task-shaped context | |
214
214
  | `plan` / `compare` / `delta` / `contract-diff` | supported | what to review for a change; candidates by measured cost; outcome of a change; public-contract break | no verdicts, measured cost only |
215
215
  | `validation` | supported | request-body validation coverage and gaps | |
216
- | `baseline capture\|diff\|trend` | supported | versioned architectural metrics over time | trend reporting, not gating |
216
+ | `baseline capture\|diff` · `trend` | supported | versioned architectural metrics over time; `ask trend <dir>` reads the series | trend reporting, not gating. Baselines land in `.ask/baselines` **inside the repository** — the history travels with the code, not with a vendor; an audit that must not write passes `--dir`. Automate it: [baseline-ci.yml](docs/baseline-ci.yml) |
217
217
  | `retrieve` | parked | typed knowledge queries over the model | |
218
218
  | `archetype` | experimental | evidence-based architectural archetype | |
219
219
  | `rename-class` / `chunk-file` | supported | word-boundary Java rename; split a large file for an agent | |
@@ -237,6 +237,34 @@ Honest limits worth knowing before you rely on it:
237
237
  - Architecture classification is tuned for Spring MVC layered apps; SPI/plugin models (e.g. Quarkus extensions) may be misclassified. JAX-RS subresource-locator endpoint recall is ~65%.
238
238
  - Self-invocation `@Transactional` bypass (same-class call skipping the proxy) is not detected.
239
239
 
240
+ ### What the security surface does not answer
241
+
242
+ Published because a product that states its limits is not compared on breadth — it is
243
+ compared on depth. Each row is emitted in the payload too (`non_coverage`), so an agent
244
+ reading JSON sees the same boundary a buyer reads here.
245
+
246
+ | Not covered | Why | What answers it |
247
+ |---|---|---|
248
+ | **Whether request input reaches a sink — no dataflow or taint analysis.** | This engine resolves structure and wiring without compiling. Taint needs value flow through a program, which is a different analysis with a different failure mode: an unsound one produces confident findings that are wrong, and every claim here is meant to be checkable against the line that produced it. | A dataflow scanner (Semgrep, CodeQL). What this product adds on top is reachability: which of that tool's findings sit behind an endpoint that is reachable unauthenticated. |
249
+ | **Secrets outside Java and Spring configuration — a credential in a deployment descriptor, a Helm value, a CI variable file.** | The file population this analyzer reads is the Java source and the Spring configuration convention. A secret elsewhere is not missed by a weak rule; it is outside the set of files anything here opens. | A dedicated secret scanner over the whole tree (gitleaks, trufflehog). |
250
+ | **Filter-chain order and per-filter URL patterns — the presence of a custom filter is structural only.** | Which filter runs first is decided by bean ordering this analyzer does not resolve. Where two active configurations both match a request, the answer published is `undecided` rather than a guess. | `ask posture --profile <set>` states per endpoint what the readable rules decide and what they leave undecided. |
251
+ | **Known vulnerabilities in dependencies — no CVE database, no version advisory matching.** | Enriching a vulnerability feed is a different product with a different update cadence; a stale embedded database is worse than no database, because it reads as a clean bill of health. | A dependency scanner (Trivy, OWASP Dependency-Check). `impact-chain` then answers which of its findings anything actually reaches. |
252
+
253
+ Two more boundaries worth stating in the same voice:
254
+
255
+ | Not covered | Why | What answers it |
256
+ |---|---|---|
257
+ | **Applying a migration — nothing here edits source.** | This is the diagnosis layer: it measures what must change and what each change would reach. Rewriting code is an execution problem with an established executor, and duplicating it would mean maintaining a second, worse one. | OpenRewrite. `migrate-check` publishes the recipe each finding carries (`recipes[]`), which is the input that executor takes. |
258
+ | **What the process environment sets at start-up — the profile set, properties and secrets a container is given.** | Nothing in a repository can observe the environment of a process that has not started. A value read from a file here is the default the repository ships, never a guarantee of what runs. | `ask posture --resolve-environments` reads every artefact in the repository that names the profile set, says when none of them decides it, and ranks the admissible sets by what each leaves open. |
259
+
260
+ **Positioning.** Until an executor ships, this is the **diagnosis layer**: it measures what
261
+ must change, what each change reaches, and what a gate should block — and it removes none of
262
+ it. Field evaluation scored it 7/10 as a report generator and 5.5/10 as a development tool,
263
+ and that gap is the honest description, not a defect to argue with. `migrate-check` publishes
264
+ the OpenRewrite recipe each finding carries so the executor that does apply changes has its
265
+ input.
266
+
267
+
240
268
  ---
241
269
 
242
270
  ## Pricing
@@ -310,7 +338,8 @@ Matching endpoints report `policy: "custom"` and drop out of the `no_security_si
310
338
  | Doc | What it covers |
311
339
  |-----|----------------|
312
340
  | [USER_GUIDE.md](docs/USER_GUIDE.md) | Full command reference, flags, output schema, workflows |
313
- | [contracts.md](docs/contracts.md) | Declare invariants in `.ask/contracts.yml`, enforce them in the edit loop and in CI |
341
+ | [contracts.md](docs/contracts.md) | Declare invariants in `.ask/contracts.yml` (or derive them with `ask verify --init`), enforce them in the edit loop and in CI |
342
+ | [baseline-ci.yml](docs/baseline-ci.yml) | Capture an architectural baseline per release, so the series exists when you want to read it |
314
343
  | [posture.md](docs/posture.md) | What a profile set actually wires — down to which endpoints its filter chain permits — and what could not be decided (experimental) |
315
344
  | [migrate-check.md](docs/migrate-check.md) | Migration rule catalogue (MIG-001..043) + Hibernate stratification |
316
345
  | [MODERNIZATION.md](docs/MODERNIZATION.md) | The modernization product: assess → understand → plan → execute |
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "sourcecode"
7
- version = "3.6.0"
7
+ version = "3.8.0"
8
8
  description = "Persistent structural context and ultra-fast repeated analysis for AI coding agents"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.9"
@@ -4,4 +4,4 @@ ASK Engine is the product. ``ask`` is the canonical CLI command; ``sourcecode``
4
4
  the legacy compatibility alias and the Python/PyPI package name. See
5
5
  docs/PRODUCT_IDENTITY.md (normative)."""
6
6
 
7
- __version__ = "3.6.0"
7
+ __version__ = "3.8.0"