sourcecode 3.5.0__tar.gz → 3.7.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 (194) hide show
  1. {sourcecode-3.5.0 → sourcecode-3.7.0}/CHANGELOG.md +305 -0
  2. {sourcecode-3.5.0 → sourcecode-3.7.0}/PKG-INFO +1 -1
  3. {sourcecode-3.5.0 → sourcecode-3.7.0}/pyproject.toml +1 -1
  4. {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/__init__.py +1 -1
  5. {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/change_plan.py +5 -1
  6. {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/cli.py +461 -112
  7. {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/compare.py +75 -8
  8. {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/explain.py +11 -0
  9. {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/hibernate_strat.py +60 -7
  10. {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/migrate_check.py +244 -19
  11. {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/output_budget.py +35 -2
  12. sourcecode-3.7.0/src/sourcecode/pipe_contract.py +208 -0
  13. {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/repository_ir.py +114 -15
  14. {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/serializer.py +174 -69
  15. {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/spring_findings.py +124 -0
  16. {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/spring_impact.py +18 -1
  17. {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/spring_security_audit.py +6 -0
  18. {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/spring_tx_analyzer.py +6 -0
  19. sourcecode-3.7.0/src/sourcecode/target_admission.py +168 -0
  20. {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/verify_edit.py +32 -9
  21. {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/verify_repo.py +22 -4
  22. {sourcecode-3.5.0 → sourcecode-3.7.0}/.github/workflows/build-windows.yml +0 -0
  23. {sourcecode-3.5.0 → sourcecode-3.7.0}/.gitignore +0 -0
  24. {sourcecode-3.5.0 → sourcecode-3.7.0}/.ruff.toml +0 -0
  25. {sourcecode-3.5.0 → sourcecode-3.7.0}/CONTRIBUTING.md +0 -0
  26. {sourcecode-3.5.0 → sourcecode-3.7.0}/LICENSE +0 -0
  27. {sourcecode-3.5.0 → sourcecode-3.7.0}/README.md +0 -0
  28. {sourcecode-3.5.0 → sourcecode-3.7.0}/SECURITY.md +0 -0
  29. {sourcecode-3.5.0 → sourcecode-3.7.0}/raw +0 -0
  30. {sourcecode-3.5.0 → sourcecode-3.7.0}/scripts/compare_integration_engines.py +0 -0
  31. {sourcecode-3.5.0 → sourcecode-3.7.0}/scripts/customer_smoke_test.sh +0 -0
  32. {sourcecode-3.5.0 → sourcecode-3.7.0}/scripts/generate_jdk_exports.py +0 -0
  33. {sourcecode-3.5.0 → sourcecode-3.7.0}/scripts/perf_harness.py +0 -0
  34. {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/adaptive_scanner.py +0 -0
  35. {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/archetype.py +0 -0
  36. {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/architectural_baseline.py +0 -0
  37. {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/architectural_delta.py +0 -0
  38. {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/architecture_analyzer.py +0 -0
  39. {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/architecture_summary.py +0 -0
  40. {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/ast_extractor.py +0 -0
  41. {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/cache.py +0 -0
  42. {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/cache_model.py +0 -0
  43. {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/call_surface.py +0 -0
  44. {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/caller_metrics.py +0 -0
  45. {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/caller_reach.py +0 -0
  46. {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/canonical_ir.py +0 -0
  47. {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/chain_rules.py +0 -0
  48. {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/cir_graphs.py +0 -0
  49. {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/classifier.py +0 -0
  50. {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/code_notes_analyzer.py +0 -0
  51. {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/confidence_analyzer.py +0 -0
  52. {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/constraint_diff.py +0 -0
  53. {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/context_cache.py +0 -0
  54. {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/context_graph.py +0 -0
  55. {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/context_scorer.py +0 -0
  56. {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/context_summarizer.py +0 -0
  57. {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/contract_diff.py +0 -0
  58. {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/contract_model.py +0 -0
  59. {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/contract_pipeline.py +0 -0
  60. {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/coverage_parser.py +0 -0
  61. {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/degradation.py +0 -0
  62. {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/dependency_analyzer.py +0 -0
  63. {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/deployment_prefix.py +0 -0
  64. {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/detectors/__init__.py +0 -0
  65. {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/detectors/base.py +0 -0
  66. {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/detectors/csproj_parser.py +0 -0
  67. {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/detectors/dart.py +0 -0
  68. {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/detectors/dotnet.py +0 -0
  69. {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/detectors/elixir.py +0 -0
  70. {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/detectors/go.py +0 -0
  71. {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/detectors/heuristic.py +0 -0
  72. {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/detectors/hybrid.py +0 -0
  73. {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/detectors/java.py +0 -0
  74. {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/detectors/jvm_ext.py +0 -0
  75. {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/detectors/nodejs.py +0 -0
  76. {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/detectors/parsers.py +0 -0
  77. {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/detectors/php.py +0 -0
  78. {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/detectors/project.py +0 -0
  79. {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/detectors/python.py +0 -0
  80. {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/detectors/ruby.py +0 -0
  81. {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/detectors/rust.py +0 -0
  82. {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/detectors/systems.py +0 -0
  83. {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/detectors/terraform.py +0 -0
  84. {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/detectors/tooling.py +0 -0
  85. {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/doc_analyzer.py +0 -0
  86. {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/dynamic_argument_surface.py +0 -0
  87. {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/endpoint_literals.py +0 -0
  88. {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/endpoint_metrics.py +0 -0
  89. {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/entrypoint_classifier.py +0 -0
  90. {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/env_analyzer.py +0 -0
  91. {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/envelope.py +0 -0
  92. {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/error_schema.py +0 -0
  93. {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/evidence_provider.py +0 -0
  94. {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/facts/__init__.py +0 -0
  95. {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/facts/registry.json +0 -0
  96. {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/file_chunker.py +0 -0
  97. {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/file_classifier.py +0 -0
  98. {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/filter_surface.py +0 -0
  99. {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/format_contract.py +0 -0
  100. {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/fqn_utils.py +0 -0
  101. {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/git_analyzer.py +0 -0
  102. {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/graph_analyzer.py +0 -0
  103. {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/graph_evidence.py +0 -0
  104. {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/integration_coordinates.py +0 -0
  105. {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/jdk_exports.py +0 -0
  106. {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/license.py +0 -0
  107. {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/mcp/__init__.py +0 -0
  108. {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/mcp/onboarding/__init__.py +0 -0
  109. {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/mcp/onboarding/applier.py +0 -0
  110. {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/mcp/onboarding/backup.py +0 -0
  111. {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/mcp/onboarding/detector.py +0 -0
  112. {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/mcp/onboarding/planner.py +0 -0
  113. {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/mcp/orchestrator.py +0 -0
  114. {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/mcp/registry.py +0 -0
  115. {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/mcp/runner.py +0 -0
  116. {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/mcp/server.py +0 -0
  117. {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/mcp_nudge.py +0 -0
  118. {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/metrics_analyzer.py +0 -0
  119. {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/migration_blast.py +0 -0
  120. {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/openapi_surface.py +0 -0
  121. {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/parse_cache.py +0 -0
  122. {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/path_admission.py +0 -0
  123. {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/path_filters.py +0 -0
  124. {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/perf.py +0 -0
  125. {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/posture.py +0 -0
  126. {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/pr_comment_renderer.py +0 -0
  127. {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/pr_impact.py +0 -0
  128. {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/prepare_context.py +0 -0
  129. {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/progress.py +0 -0
  130. {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/ranking_engine.py +0 -0
  131. {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/readiness_timeline.py +0 -0
  132. {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/reconciliation.py +0 -0
  133. {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/redactor.py +0 -0
  134. {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/reference_facts.py +0 -0
  135. {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/relevance_scorer.py +0 -0
  136. {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/rename_refactor.py +0 -0
  137. {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/repo_classifier.py +0 -0
  138. {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/retrieval/__init__.py +0 -0
  139. {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/retrieval/context.py +0 -0
  140. {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/retrieval/errors.py +0 -0
  141. {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/retrieval/executor.py +0 -0
  142. {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/retrieval/planner.py +0 -0
  143. {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/retrieval/query.py +0 -0
  144. {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/retrieval/request.py +0 -0
  145. {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/retrieval/resolution.py +0 -0
  146. {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/retrieval/result.py +0 -0
  147. {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/retrieval/retriever.py +0 -0
  148. {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/retrieval/runtime.py +0 -0
  149. {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/retrieval/steps.py +0 -0
  150. {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/retrieval/steps_endpoint.py +0 -0
  151. {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/retrieval/steps_graph.py +0 -0
  152. {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/retrieval/steps_impact.py +0 -0
  153. {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/retrieval/steps_intf.py +0 -0
  154. {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/retrieval/steps_struct.py +0 -0
  155. {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/retrieval/steps_txsec.py +0 -0
  156. {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/ris.py +0 -0
  157. {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/runtime_classifier.py +0 -0
  158. {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/scanner.py +0 -0
  159. {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/schema.py +0 -0
  160. {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/schemas/envelope-v1.schema.json +0 -0
  161. {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/security_config.py +0 -0
  162. {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/security_posture.py +0 -0
  163. {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/semantic_analyzer.py +0 -0
  164. {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/semantic_impact_engine.py +0 -0
  165. {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/semantic_integration_engine.py +0 -0
  166. {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/semantic_services.py +0 -0
  167. {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/spring_event_topology.py +0 -0
  168. {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/spring_model.py +0 -0
  169. {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/spring_profiles.py +0 -0
  170. {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/spring_properties.py +0 -0
  171. {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/spring_semantic.py +0 -0
  172. {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/summarizer.py +0 -0
  173. {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/telemetry/__init__.py +0 -0
  174. {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/telemetry/config.py +0 -0
  175. {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/telemetry/consent.py +0 -0
  176. {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/telemetry/events.py +0 -0
  177. {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/telemetry/filters.py +0 -0
  178. {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/telemetry/transport.py +0 -0
  179. {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/test_sources.py +0 -0
  180. {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/token_estimate.py +0 -0
  181. {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/tree_utils.py +0 -0
  182. {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/type_usage_surface.py +0 -0
  183. {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/validation_inference.py +0 -0
  184. {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/validation_surface.py +0 -0
  185. {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/verify_rules.py +0 -0
  186. {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/version_check.py +0 -0
  187. {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/workspace.py +0 -0
  188. {sourcecode-3.5.0 → sourcecode-3.7.0}/supabase/functions/README.md +0 -0
  189. {sourcecode-3.5.0 → sourcecode-3.7.0}/supabase/functions/get-license/index.ts +0 -0
  190. {sourcecode-3.5.0 → sourcecode-3.7.0}/supabase/functions/lemonsqueezy-webhook/index.ts +0 -0
  191. {sourcecode-3.5.0 → sourcecode-3.7.0}/supabase/functions/telemetry/index.ts +0 -0
  192. {sourcecode-3.5.0 → sourcecode-3.7.0}/supabase/sql/license_event_ordering.sql +0 -0
  193. {sourcecode-3.5.0 → sourcecode-3.7.0}/supabase/sql/licensing_schema.sql +0 -0
  194. {sourcecode-3.5.0 → sourcecode-3.7.0}/supabase/sql/telemetry_events.sql +0 -0
@@ -1,5 +1,310 @@
1
1
  # Changelog
2
2
 
3
+ ## [3.7.0] — 2026-08-01
4
+
5
+ **The exit-code contract and the C3 surface block.** Seven rows closed: the two the field named
6
+ as blocking for CI (exit codes over correct answers), the fourth and fifth appearance of a
7
+ curated list beside real data, and three surfaces that published a promise the payload did not
8
+ keep.
9
+
10
+ Minor and not patch, because a pipeline can see the difference: `plan` exits 1 where it exited 0
11
+ over a target it never resolved (C3-29), `ask <cmd> | head` exits 0 where a correct run used to
12
+ exit non-zero (C3-28), `--output FILE` carries the whole answer where it was silently trimmed
13
+ (C3-17), `--agent` publishes sections it used to omit (C3-10), and a path-shaped target that was
14
+ refused as ambiguous now resolves (C3-35).
15
+
16
+ ### Fixed
17
+
18
+ - **A broken output pipe is no longer a failed run** (C3-28, **exit code changes for
19
+ `ask <cmd> | head`**). `ask repo-ir . --force | head -c 100` returned the correct bytes and
20
+ exit 1; under `set -e` that stops a pipeline with no error anywhere to explain it — the field
21
+ named it one of two blockers for CI. One authority now says what a closed stream means
22
+ (`pipe_contract.py`, installed at the entry point): **a broken output stream changes nothing
23
+ except where the remaining bytes go.** The descriptor is redirected to the null device on the
24
+ first broken write and the command finishes and exits on its own terms.
25
+ - **It does not overwrite the command's own verdict.** `ask impact <ambiguous target> | head`
26
+ still exits 1, because a consumer that stopped reading has no opinion about whether the
27
+ analysis resolved its target.
28
+ - Redirecting before the shutdown flush is what keeps Python from printing
29
+ `Exception ignored in: <_io.TextIOWrapper …>` and exiting 120 — the same defect wearing a
30
+ different number.
31
+ - **The wrapper covers `.buffer`, which is the whole fix**: payloads are written as bytes
32
+ through `sys.stdout.buffer` at the single emit seam, so a text-only wrapper sits beside the
33
+ one write this exists for. Measured: with the text wrapper alone, nothing changed.
34
+ - Only visible above a pipe buffer, which is why it looked intermittent: `endpoints` on a
35
+ small repository exits 0 either way, `repo-ir` on the same repository did not.
36
+
37
+ - **An unresolved target has one exit code across every command** (C3-29, **`plan` now exits 1
38
+ where it exited 0**). `plan <unknown> <repo>` ran to completion, emitted a plan-shaped payload
39
+ of zeros with `resolution: "not_found"` and exited **0**, while `impact` on the same input
40
+ exited 1 — so a gate could not tell "nothing to review" from "I never found what you asked
41
+ about". One authority (`target_admission.py`), four commands rebound (`impact`,
42
+ `impact-chain`, `plan`, `explain`), and the two other copies of the same literal set
43
+ (`compare`, `change_plan`) now read it instead of restating it.
44
+ - **Ambiguity is the same fact, and it was not in the field report.** A target matching
45
+ several classes returns `ambiguous_path`, empty results and a message asking for the full
46
+ FQN — the command declined to answer — and `impact` exited **0** on it. Measured on a
47
+ purpose-built two-class fixture, since no battery repository carries the shape.
48
+ - Unresolved is **1, not 2**: 2 is reserved by the `verify` family for a run that could not
49
+ look, and this run looked. Partial and expanded resolutions stay 0 — they are answers about
50
+ the target the caller named.
51
+ - `plan`'s `Note:` on stderr is gone with it: the payload already carries the statement, and
52
+ a successful-looking run should not be narrating on stderr (the `plan` half of C3-34).
53
+
54
+ - **`--help` reaches inside command groups** (C4-7). `ask cache model` — what a warm buys each
55
+ command, per layer, including the commands it buys nothing for — appeared in no help text at
56
+ all: the root catalogue was generated (C4-1/C4-2) but the Cache and Auth blocks under it were
57
+ three lines somebody typed by hand. The blocks are now built from the registered groups, so a
58
+ subcommand is listed the moment it is registered; a group too large to name in full (`retrieve`,
59
+ 29 parked intents) publishes its **exact count** and a pointer, never silence. The battery
60
+ fails if a subcommand of a listed group is missing, or if a collapsed group's count drifts.
61
+
62
+ - **A successful run says nothing on stderr — measured over the commands, not over a list**
63
+ (C3-34, the `repo-ir` half). `ask repo-ir . --force` wrote an 82-byte size advisory on a run
64
+ that exited 0 with the IR on stdout, which PowerShell 5.1 raises as a `NativeCommandError`.
65
+ The advisory is terminal-gated now, like every other notice, and so is the `--exclude`
66
+ directory warning and the output-budget trim warning found beside it.
67
+ - **The list was the defect.** `tests/test_stderr_purity_matrix.py` enumerated 13 commands by
68
+ hand for the fourth time in three releases; the rows are now **discovered from the CLI**,
69
+ with every command either driven or carrying a written reason it cannot be. Nine more
70
+ commands are driven as a result, `cache` subcommands included.
71
+ - The `repo-ir` row builds a repository large enough for the advisory to actually fire and
72
+ **asserts it fired**, because a row that never reaches the branch proves nothing.
73
+
74
+ - **`--output FILE` is no longer trimmed to an agent's context window** (C3-17). The payload
75
+ budget exists because a context window is finite — it is a constraint on **stdout**. Written
76
+ to a file it cut the answer anyway, dropped `key_dependencies` entirely, and the note
77
+ explaining the cut advised `--output`, the flag already in use. Two of six call sites had the
78
+ rule and four did not (`prepare-context`, `modernize`, the cached-view rebuild, and `impact`
79
+ in part), so it now lives in one seam (`cli._apply_budget`) and a battery fails if a seventh
80
+ call site decides for itself.
81
+ - **The cache had the same defect one layer down**, found while field-checking the seam:
82
+ `prepare-context` stored the document *after* trimming, so the first stdout run poisoned the
83
+ cache and every later `--output FILE` hit received a stdout-sized answer. The cache stores
84
+ the analysis now and the budget is applied per run — measured on alfresco-community-repo:
85
+ stdout 5 files, cache hit to a file 26.
86
+ - **`--full` says what it does.** It raises the caps (boundaries and DTO mappers in full,
87
+ `file_relevance` to 40); it never removed them — under `--agent --full` the file list stayed
88
+ capped at 40 of 710 while the flag's help promised "remove truncation limits".
89
+
90
+ - **`--agent` cannot publish less than `--compact`** (C3-10). `--compact` documents
91
+ `security_surface` "when custom security annotations detected" and closes with "use `--agent`
92
+ for maximum signal", while `--agent` was assembled from its own hand-written list of sections:
93
+ measured on BroadleafCommerce it omitted `deployment` and `language_version` outright, and
94
+ nothing stopped the security surface going the same way. Both views now read one authority
95
+ (`serializer.JAVA_SPRING_SECTIONS`), and the battery fails on any section `--compact` publishes
96
+ that `--agent` does not.
97
+
98
+ - **A path that names one file resolves to that file** (C3-35). Every resolver reduced a
99
+ path-shaped target to its basename before anything looked at it, so
100
+ `ask impact src/main/java/com/a/Service.java` answered `ambiguous_path` and offered
101
+ `com.a.Service` **and** `com.b.Service` — being more specific made the answer worse. A path is
102
+ matched against the `source_file` each symbol came from, strongest tier first (exact, then
103
+ module-relative, then parent-relative), and nested types collapse to the type the file is about
104
+ (on eureka, `DiscoveryClient.java` declares its outer class and five inner ones). One authority
105
+ in `target_admission`, because three graphs answer target questions — the repo IR, and the CIR
106
+ that `explain` and `impact-chain` read, both of which used to answer `not_found` for a path.
107
+ Parity checked on eureka: by path and by name give byte-identical `stats`.
108
+
109
+ - **`verify-edit` stops paying for a diff it has already proved empty** (C3-32). It computed the
110
+ change set and then built the HEAD CIR *and* the working CIR unconditionally — on a clean tree
111
+ the second is the first by construction. Measured on a clean ofbiz-framework: **5.9 s -> 1.7 s**
112
+ warm. The shortcut is taken only when git actually answered: a failed `git diff` also returns an
113
+ empty list, and reading that as "nothing changed" would trade dead cost for a false green.
114
+
115
+ - **`spring-audit --compact`** (C3-31). The one analysis command with no summary mode: 1.99 MB for
116
+ 14 findings in the field, *"a context overflow against an LLM with no filter in between"*. The
117
+ weight is not the findings — on BroadleafCommerce `security_posture.endpoints` is 113 KB of a
118
+ 178 KB report, and the counts it supports are published beside it. `--compact` caps that list and
119
+ `findings` to their top 5, ordered by what asks something of the reader (`probably_exposed`
120
+ first; most severe first), and recomputes nothing: **178 KB -> 25 KB with every count
121
+ identical**. A flag changes how much is emitted, never the shape (C2-10) — each list stays a list
122
+ and the totals live in a `*_cap` sibling that exists only when the cap bit.
123
+
124
+
125
+ ### Documentation
126
+
127
+ - **Field evaluation #6 of 3.5.0 recorded** (`.planning/FIELD-EVAL-6-2026-08-01.md`, defect
128
+ ledger, development roadmap). Full 27-command catalogue, repository left byte-identical,
129
+ scored 8/10. Every reported defect was re-measured on 3.6.0 before it was written down: two
130
+ do not reproduce (one closed here as C3-15, one by the 3.5.0 admission authority) and the
131
+ re-measurement found two the evaluation did not report.
132
+ - **New rows**: C1-18 (profile population differs per command, and the narrower one is what an
133
+ agent reads) · C3-28/C3-29 (**exit codes that lie over correct answers** — a broken pipe
134
+ exits non-zero on a successful run, `plan` exits 0 on a target it did not resolve while
135
+ `impact` exits 1) · C3-30 (`verify --init`) · C3-31…C3-34 · C4-7 (`cache model` in no help
136
+ panel) · P-4 (`baseline` history nobody automated) · CL-7 (non-coverage: no dataflow, no
137
+ secrets outside Java/YAML, filter order not reconstructed) · CL-8 (`posture --diff` answers
138
+ conditionally because the profile is decided outside the repository).
139
+ - **The executive roadmap gains what the product does *not* do**, published beside the
140
+ capabilities, and the evaluation table is current through eval #6.
141
+
142
+ ## [3.6.0] — 2026-08-01
143
+
144
+ **The P0 block and the C1/C2 backlog.** Nine rows closed, three closed by measurement alone
145
+ (C1-17, C2-11, and C2-12 as stated did not reproduce). `migrate-check` stops billing work a
146
+ declared dependency already did, stops billing a Hibernate rewrite to another vendor's provider,
147
+ and stops assuming a single destination — `--target-jdk 11 --keep-boot` takes MIG-001 from 85 to 0
148
+ on openmrs-core.
149
+
150
+ Two patterns from 3.5.0 repeat, and both are worth carrying forward. **The reported symptom keeps
151
+ being narrower than the defect**: C1-10 was one rule and was also an evidence rule admitting JPA as
152
+ proof of Hibernate; C2-1 was a `why` trail and was also the ranking key underneath it. **And a
153
+ curated list beside real data keeps being the cause** — C2-3's trim schedule named sections the
154
+ payload does not have while the weight sat in two it never mentions, the third appearance of the
155
+ C4-1 shape in two releases.
156
+
157
+ **Minor, not patch**: blocking counts move (C1-10), reach-derived counts become nullable (C1-13),
158
+ `compare`'s ranking can move (C2-1), `migrate-check.findings` keeps one type across `--compact`
159
+ (C2-10), and two commands that wrote their confirmation to stderr now write it to stdout (C3-18).
160
+
161
+ ### Added
162
+
163
+ - **`migrate-check --target-jdk N` and `--keep-boot`** (C1-15, P0 gate 2). Asked about a JDK move,
164
+ the answer was `headline_blocker: boot3_migration` with fix hints sending a developer to migrate
165
+ 481 `javax.persistence` imports they never planned to touch; nothing could say "JDK 11, keep Boot
166
+ 2.7". The route is filtered over the `migration_target` vocabulary every rule already carried.
167
+ Measured on openmrs-core with `--target-jdk 11 --keep-boot`: **MIG-001 85 → 0**, blocking 114 → 0,
168
+ headline `hibernate_rewrite` → `none_applicable`. Narrowing is not silencing — `metadata.route`
169
+ publishes the target and every excluded axis, and a `limitations` entry states what was left out
170
+ and that it is unresolved, not fixed. **The default is unchanged**: no flags means every axis at
171
+ once.
172
+
173
+ - **`spring-audit` findings carry `first_line`** (C2-4), from the `SourceSpan` index the IR already
174
+ records. `null` where the symbol has no recorded span, never 0.
175
+
176
+ ### Changed
177
+
178
+ - **`migrate-check` reconciles findings with the build it already read** (C1-10, P0 gate 1,
179
+ **blocking counts move**). `MIG-021` fired as blocking while `javax.xml.bind:jaxb-api:2.3.1` sat
180
+ in the same `pom.xml`. A rule now declares the coordinates that satisfy it; a satisfied finding
181
+ gets `mitigated_by` and `code_context: "dependency_satisfied"`, leaving `blocking_count` exactly
182
+ as test scope does, and its hint stops saying "add this dependency". `satisfied_by` is empty for
183
+ every rule whose remedy is a source change.
184
+ - **The Hibernate axis now needs Hibernate evidence.** It billed 45.6 days to a repository whose
185
+ declared provider was EclipseLink because a bare `javax.persistence` import counted as proof —
186
+ that proves JPA, not Hibernate. A declared competing provider refutes the inference, and only
187
+ the inference: a repository carrying both coordinates keeps direct evidence. An inference from
188
+ a JPA import alone now reports `medium`, not `high`.
189
+ - Battery: `blocking_count` identical on all six repositories.
190
+
191
+ - **A capped blast radius answers `unknown`, not `0`** (C1-13, **reach-derived counts become
192
+ nullable**). A hub capped at `depth=1` reported `endpoints_affected_count: 0` for a walk that
193
+ never looked. Under the cap a reach-derived zero becomes `null`, named in
194
+ `stats.unknown_under_cap`. A **non-zero** count under the cap stays a number — it is a floor — and
195
+ an **uncapped** run keeps its measured zero.
196
+
197
+ - **`compare` ranks on measurements, not on rendered rows** (C1-13/C2-1, **ranking may move**).
198
+ Three of the seven cost fields were `len()` of a display list, so the ordering was computed over
199
+ however many rows the renderer had decided to show. Capped magnitudes are declared in
200
+ `cost_floor_fields` beside `cost`, never inside it.
201
+
202
+ - **`impact.endpoints_affected[]` gains `controller_class` and `handler_symbol`** (C2-12), the names
203
+ `impact-chain` already uses. Grouping by controller needed a different key per command on payloads
204
+ one run produces. Original keys kept as aliases.
205
+
206
+ - **`effort_breakdown.affected_files` is now `blocking_affected_files`** (C1-14, alias kept). It
207
+ named a different population from `summary.affected_files` — 264 against 265 on openmrs-core — and
208
+ the shared name was the whole of the contradiction. Both carry a `_basis`.
209
+
210
+ ### Fixed
211
+
212
+ - **The payload budget cuts where the bytes are** (C2-3). `_TRIM_SCHEDULE` is a hand-written list of
213
+ key names: on a 1 222-file `review-pr` diff it trimmed 1 733 KB → 1 732 KB against a 97 KB budget,
214
+ walking to `execution_paths` while every byte sat in `changed_files` and `runtime_changes`, which
215
+ it does not mention. Once the schedule is exhausted the remaining cut is chosen by measuring which
216
+ list is largest. Measured on that payload shape: **566 KB → 71 KB**.
217
+
218
+ - **`ask verify` no longer passes with zero contracts declared** (C3-15, **behaviour change for
219
+ pipelines**). It returned `pass` + exit 0 on a repository that declared nothing — a green light
220
+ for having verified nothing. `evaluate_repo` returns before it even builds the CIR when no
221
+ contracts exist, so no code was read and no contract was checked: the same standing as a
222
+ repository that could not be analysed, and now reported the same way — **`unverified`, exit 2**,
223
+ with the reason stated. Exit 2 and not 1 because the published contract reserves 1 for
224
+ violations found and 2 for a run that could not verify. Asserted under every `--fail-on` choice:
225
+ `never` suppresses violations from blocking, it does not turn a run that verified nothing into a
226
+ verified one. This is C3-22 in different clothes — there a typo in `$DIR` made the gate
227
+ permanently green, here a repository that never adopted contracts did.
228
+
229
+ - **A command that writes its answer to a file now confirms on stdout, not stderr** (C3-18,
230
+ **behaviour change for scripts reading stderr**). `repo-ir`, `modernize`, `export` and
231
+ `cold-start` wrote the "written to" confirmation to stderr while the payload went to the file
232
+ and stdout stayed empty, so `ask repo-ir -o ir.json > log.txt` captured **nothing** and
233
+ PowerShell 5.1 raised `NativeCommandError` over a run that succeeded. Measured on
234
+ spring-petclinic before the fix: stdout 0 bytes, stderr 155. C3-26 set this rule in 3.5.0 for
235
+ `cache warm`/`cache clear`; these four were missed because the stderr battery listed its
236
+ commands **by hand**. The `--output` rows are now discovered from the CLI.
237
+
238
+ - **Usage errors emit the JSON envelope for a pipeline** (C3-4). The interception was patched onto
239
+ `click.UsageError.show`, which Typer never calls when `rich_markup_mode` is set — it is, for the
240
+ help panels — so **no usage error had been emitting an envelope at all** and `ask <cmd>
241
+ --badflag` answered automation with a rich text box. Split by audience: a pipeline gets the
242
+ envelope, a person at a terminal keeps the `Usage:` line and the pointer to `--help`.
243
+
244
+ - **A flag no longer changes the type of a key** (C2-10, **breaking for `--compact` consumers**).
245
+ `migrate-check.findings` was a bare array in full output and a
246
+ `{total, shown, omitted, items}` object under `--compact` — the same key, two types. A consumer
247
+ iterating `findings` broke silently on a flag it did not pass: nothing errored, the loop simply
248
+ ran over the four keys of a summary object instead of over the findings.
249
+ - `findings` is a **list in both modes**. The counts moved to a `findings_cap` sibling that
250
+ exists **only when a cap actually bit**, and it carries the I-8 `display_list` statement of
251
+ what the cut changed and what stayed exact.
252
+ - **Five collections had it, not one**: top-level `findings`, `hibernate.rewrite_targets`,
253
+ `hibernate.findings`, `hibernate.critical_call_chains`, `hibernate.golden_sql_hotspots`, and
254
+ `blast_radius.files`.
255
+ - **Half of C2-13 falls out of the same fix.** `migrate-check.findings` is now the bare array
256
+ `spring-audit.findings` always was — one word, one type, one parser, measured across all
257
+ three payloads. The `schema_version` fragmentation is the half that stays open.
258
+ - Enforced rather than documented: `tests/test_flag_shape_stability.py` walks both payloads key
259
+ by key and fails on any type that moves. The same walk covers the root command's `--compact`
260
+ and `--agent`, which were **measured clean** while fixing this and are locked so they stay
261
+ clean.
262
+
263
+ - **A misplaced global flag is told where that flag lives** (C3-4). `ask spring-audit --full`
264
+ answered "No such option: --full" about a flag the tool does have — it is declared on the root
265
+ command. The flag is looked up on the root command, so every global flag typed after every
266
+ subcommand is covered and no flag name is written into the check; a genuinely unknown flag earns
267
+ no hint, asserted.
268
+
269
+ - **`repo-ir` states the output cost before it is paid** (C3-18). The advisory ran after the IR was
270
+ built, serialized and written — the whole bill settled. It now runs off the file count before the
271
+ build starts, as a **band** (10.8–27.9 KB per Java file) rather than a point: the per-file cost
272
+ spreads 2.6× across sampled repositories with how densely the code cross-references, and
273
+ publishing a midpoint as one figure is the C1-12 defect. The band is asserted to bracket what
274
+ those repositories actually produced.
275
+
276
+ - **A capped `file_relevance` list says what was cut, measured** (C3-20). The hint published the
277
+ *budget* as the number of files shown — on spring-petclinic, "Showing top 40/176" beside a list
278
+ of **25** — fired even when nothing had been cut, and advised `--full` while `--full` was active.
279
+ Two constraints trim the list (a visibility threshold and a per-category cap of half the budget)
280
+ and the sentence knew about neither. Now: nothing unless a cap really bit, the figure is what was
281
+ shown against the population it samples, a flag is named only when it would change the answer,
282
+ and the I-8 `display_list` block sits beside it.
283
+
284
+ - **`--no-cache` on a subcommand says what it does** (C3-5). Six commands claimed "always reads
285
+ fresh source (no snapshot cache)" while `ask cache model` records them reading `ris`, `cir` and
286
+ `parse`. One string now, stating the reason it is a no-op: since C1-9 every layer keys on the
287
+ exact tree state and the parse layer is content-addressed, so there is no staleness to bypass.
288
+ The flag stays accepted so scripts do not break, and is real on `ask --no-cache` (root).
289
+
290
+ - **`--output <file>` now returns the whole answer, which is what its own note promised**
291
+ (C2-2, first M8 increment). Measured on `org.broadleafcommerce.common.money.Money`: the file
292
+ held **30 of 134** caller classes and **50 of 1 302** indirect callers — the same sample stdout
293
+ gets — while the payload told the reader *"use `--output` for the full list"*.
294
+ - **The recorded cause was wrong, and fixing what was recorded would not have worked.** The
295
+ file carried no `_budget_note` at all: the caps were applied at *construction*, inside
296
+ `compute_blast_radius`, before any output flag was consulted. No option could have returned
297
+ the full list.
298
+ - A cap is now a **rendering** parameter (`list_limit`) and never a measurement one — every
299
+ `stats.*_count` is taken over the full population either way (ADR-0008 R5-R8). `--output`
300
+ renders unbounded; stdout keeps the sample and names the total; and the note only claims a
301
+ cap that actually bit, with the I-8 `display_list` effect block beside it.
302
+ - The output budget is skipped for a file as well. `--agent` and `--compact` already did this;
303
+ `impact` was the one that did not.
304
+ - Same rule for `impact-chain`, with one qualification: an **explicit `--limit` still wins**.
305
+ A default is not a request; a typed flag is (`_flag_was_given`, off Click's parameter source).
306
+ - The USER_GUIDE now states the rule where a reader meets it, beside the `impact` output.
307
+
3
308
  ## [3.5.0] — 2026-07-31
4
309
 
5
310
  **M7.7 "Robustness floor" — the axis field evaluation #5 scored 4/10.** Ten pieces, and the
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: sourcecode
3
- Version: 3.5.0
3
+ Version: 3.7.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
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "sourcecode"
7
- version = "3.5.0"
7
+ version = "3.7.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.5.0"
7
+ __version__ = "3.7.0"
@@ -88,7 +88,11 @@ def build_change_plan(
88
88
  resolution = blast.get("resolution", "not_found")
89
89
 
90
90
  # Unresolvable target → return a plan-shaped resolution notice (never crash).
91
- if resolution in ("not_found", "ambiguous_path") or not blast.get("matched_fqns"):
91
+ # The set of resolutions that means "never found it" is one fact, and the CLI
92
+ # reads the same one to decide the exit code (C3-29).
93
+ from sourcecode.target_admission import is_unresolved
94
+
95
+ if is_unresolved(resolution) or not blast.get("matched_fqns"):
92
96
  return {
93
97
  "schema": CHANGE_PLAN_SCHEMA,
94
98
  "target": target,