sourcecode 2.6.5__tar.gz → 2.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 (176) hide show
  1. {sourcecode-2.6.5 → sourcecode-2.7.0}/CHANGELOG.md +204 -0
  2. {sourcecode-2.6.5 → sourcecode-2.7.0}/PKG-INFO +1 -1
  3. {sourcecode-2.6.5 → sourcecode-2.7.0}/pyproject.toml +1 -1
  4. {sourcecode-2.6.5 → sourcecode-2.7.0}/src/sourcecode/__init__.py +1 -1
  5. {sourcecode-2.6.5 → sourcecode-2.7.0}/src/sourcecode/archetype.py +11 -0
  6. {sourcecode-2.6.5 → sourcecode-2.7.0}/src/sourcecode/caller_metrics.py +19 -0
  7. {sourcecode-2.6.5 → sourcecode-2.7.0}/src/sourcecode/cli.py +281 -63
  8. sourcecode-2.7.0/src/sourcecode/deployment_prefix.py +229 -0
  9. {sourcecode-2.6.5 → sourcecode-2.7.0}/src/sourcecode/explain.py +32 -0
  10. {sourcecode-2.6.5 → sourcecode-2.7.0}/src/sourcecode/file_classifier.py +6 -2
  11. {sourcecode-2.6.5 → sourcecode-2.7.0}/src/sourcecode/hibernate_strat.py +11 -4
  12. {sourcecode-2.6.5 → sourcecode-2.7.0}/src/sourcecode/mcp/onboarding/applier.py +29 -15
  13. {sourcecode-2.6.5 → sourcecode-2.7.0}/src/sourcecode/mcp/onboarding/detector.py +38 -0
  14. {sourcecode-2.6.5 → sourcecode-2.7.0}/src/sourcecode/mcp/onboarding/planner.py +2 -2
  15. {sourcecode-2.6.5 → sourcecode-2.7.0}/src/sourcecode/mcp/server.py +45 -6
  16. {sourcecode-2.6.5 → sourcecode-2.7.0}/src/sourcecode/mcp_nudge.py +3 -2
  17. {sourcecode-2.6.5 → sourcecode-2.7.0}/src/sourcecode/migrate_check.py +13 -0
  18. {sourcecode-2.6.5 → sourcecode-2.7.0}/src/sourcecode/pr_impact.py +135 -16
  19. sourcecode-2.7.0/src/sourcecode/readiness_timeline.py +178 -0
  20. {sourcecode-2.6.5 → sourcecode-2.7.0}/src/sourcecode/repository_ir.py +285 -13
  21. {sourcecode-2.6.5 → sourcecode-2.7.0}/src/sourcecode/retrieval/steps_endpoint.py +32 -8
  22. {sourcecode-2.6.5 → sourcecode-2.7.0}/src/sourcecode/retrieval/steps_graph.py +9 -1
  23. {sourcecode-2.6.5 → sourcecode-2.7.0}/src/sourcecode/retrieval/steps_intf.py +32 -6
  24. {sourcecode-2.6.5 → sourcecode-2.7.0}/src/sourcecode/retrieval/steps_txsec.py +114 -6
  25. {sourcecode-2.6.5 → sourcecode-2.7.0}/src/sourcecode/security_posture.py +41 -8
  26. {sourcecode-2.6.5 → sourcecode-2.7.0}/src/sourcecode/serializer.py +52 -6
  27. {sourcecode-2.6.5 → sourcecode-2.7.0}/src/sourcecode/spring_findings.py +44 -0
  28. sourcecode-2.7.0/src/sourcecode/spring_profiles.py +208 -0
  29. {sourcecode-2.6.5 → sourcecode-2.7.0}/src/sourcecode/telemetry/__init__.py +2 -0
  30. {sourcecode-2.6.5 → sourcecode-2.7.0}/src/sourcecode/telemetry/consent.py +2 -1
  31. {sourcecode-2.6.5 → sourcecode-2.7.0}/src/sourcecode/telemetry/events.py +3 -0
  32. {sourcecode-2.6.5 → sourcecode-2.7.0}/src/sourcecode/telemetry/filters.py +20 -1
  33. sourcecode-2.7.0/src/sourcecode/token_estimate.py +213 -0
  34. {sourcecode-2.6.5 → sourcecode-2.7.0}/src/sourcecode/validation_inference.py +58 -6
  35. {sourcecode-2.6.5 → sourcecode-2.7.0}/src/sourcecode/validation_surface.py +91 -0
  36. {sourcecode-2.6.5 → sourcecode-2.7.0}/.github/workflows/build-windows.yml +0 -0
  37. {sourcecode-2.6.5 → sourcecode-2.7.0}/.gitignore +0 -0
  38. {sourcecode-2.6.5 → sourcecode-2.7.0}/.ruff.toml +0 -0
  39. {sourcecode-2.6.5 → sourcecode-2.7.0}/CONTRIBUTING.md +0 -0
  40. {sourcecode-2.6.5 → sourcecode-2.7.0}/LICENSE +0 -0
  41. {sourcecode-2.6.5 → sourcecode-2.7.0}/README.md +0 -0
  42. {sourcecode-2.6.5 → sourcecode-2.7.0}/SECURITY.md +0 -0
  43. {sourcecode-2.6.5 → sourcecode-2.7.0}/raw +0 -0
  44. {sourcecode-2.6.5 → sourcecode-2.7.0}/scripts/compare_integration_engines.py +0 -0
  45. {sourcecode-2.6.5 → sourcecode-2.7.0}/scripts/customer_smoke_test.sh +0 -0
  46. {sourcecode-2.6.5 → sourcecode-2.7.0}/scripts/generate_jdk_exports.py +0 -0
  47. {sourcecode-2.6.5 → sourcecode-2.7.0}/scripts/perf_harness.py +0 -0
  48. {sourcecode-2.6.5 → sourcecode-2.7.0}/src/sourcecode/adaptive_scanner.py +0 -0
  49. {sourcecode-2.6.5 → sourcecode-2.7.0}/src/sourcecode/architectural_baseline.py +0 -0
  50. {sourcecode-2.6.5 → sourcecode-2.7.0}/src/sourcecode/architectural_delta.py +0 -0
  51. {sourcecode-2.6.5 → sourcecode-2.7.0}/src/sourcecode/architecture_analyzer.py +0 -0
  52. {sourcecode-2.6.5 → sourcecode-2.7.0}/src/sourcecode/architecture_summary.py +0 -0
  53. {sourcecode-2.6.5 → sourcecode-2.7.0}/src/sourcecode/ast_extractor.py +0 -0
  54. {sourcecode-2.6.5 → sourcecode-2.7.0}/src/sourcecode/cache.py +0 -0
  55. {sourcecode-2.6.5 → sourcecode-2.7.0}/src/sourcecode/call_surface.py +0 -0
  56. {sourcecode-2.6.5 → sourcecode-2.7.0}/src/sourcecode/canonical_ir.py +0 -0
  57. {sourcecode-2.6.5 → sourcecode-2.7.0}/src/sourcecode/change_plan.py +0 -0
  58. {sourcecode-2.6.5 → sourcecode-2.7.0}/src/sourcecode/cir_graphs.py +0 -0
  59. {sourcecode-2.6.5 → sourcecode-2.7.0}/src/sourcecode/classifier.py +0 -0
  60. {sourcecode-2.6.5 → sourcecode-2.7.0}/src/sourcecode/code_notes_analyzer.py +0 -0
  61. {sourcecode-2.6.5 → sourcecode-2.7.0}/src/sourcecode/compare.py +0 -0
  62. {sourcecode-2.6.5 → sourcecode-2.7.0}/src/sourcecode/confidence_analyzer.py +0 -0
  63. {sourcecode-2.6.5 → sourcecode-2.7.0}/src/sourcecode/constraint_diff.py +0 -0
  64. {sourcecode-2.6.5 → sourcecode-2.7.0}/src/sourcecode/context_cache.py +0 -0
  65. {sourcecode-2.6.5 → sourcecode-2.7.0}/src/sourcecode/context_graph.py +0 -0
  66. {sourcecode-2.6.5 → sourcecode-2.7.0}/src/sourcecode/context_scorer.py +0 -0
  67. {sourcecode-2.6.5 → sourcecode-2.7.0}/src/sourcecode/context_summarizer.py +0 -0
  68. {sourcecode-2.6.5 → sourcecode-2.7.0}/src/sourcecode/contract_diff.py +0 -0
  69. {sourcecode-2.6.5 → sourcecode-2.7.0}/src/sourcecode/contract_model.py +0 -0
  70. {sourcecode-2.6.5 → sourcecode-2.7.0}/src/sourcecode/contract_pipeline.py +0 -0
  71. {sourcecode-2.6.5 → sourcecode-2.7.0}/src/sourcecode/coverage_parser.py +0 -0
  72. {sourcecode-2.6.5 → sourcecode-2.7.0}/src/sourcecode/dependency_analyzer.py +0 -0
  73. {sourcecode-2.6.5 → sourcecode-2.7.0}/src/sourcecode/detectors/__init__.py +0 -0
  74. {sourcecode-2.6.5 → sourcecode-2.7.0}/src/sourcecode/detectors/base.py +0 -0
  75. {sourcecode-2.6.5 → sourcecode-2.7.0}/src/sourcecode/detectors/csproj_parser.py +0 -0
  76. {sourcecode-2.6.5 → sourcecode-2.7.0}/src/sourcecode/detectors/dart.py +0 -0
  77. {sourcecode-2.6.5 → sourcecode-2.7.0}/src/sourcecode/detectors/dotnet.py +0 -0
  78. {sourcecode-2.6.5 → sourcecode-2.7.0}/src/sourcecode/detectors/elixir.py +0 -0
  79. {sourcecode-2.6.5 → sourcecode-2.7.0}/src/sourcecode/detectors/go.py +0 -0
  80. {sourcecode-2.6.5 → sourcecode-2.7.0}/src/sourcecode/detectors/heuristic.py +0 -0
  81. {sourcecode-2.6.5 → sourcecode-2.7.0}/src/sourcecode/detectors/hybrid.py +0 -0
  82. {sourcecode-2.6.5 → sourcecode-2.7.0}/src/sourcecode/detectors/java.py +0 -0
  83. {sourcecode-2.6.5 → sourcecode-2.7.0}/src/sourcecode/detectors/jvm_ext.py +0 -0
  84. {sourcecode-2.6.5 → sourcecode-2.7.0}/src/sourcecode/detectors/nodejs.py +0 -0
  85. {sourcecode-2.6.5 → sourcecode-2.7.0}/src/sourcecode/detectors/parsers.py +0 -0
  86. {sourcecode-2.6.5 → sourcecode-2.7.0}/src/sourcecode/detectors/php.py +0 -0
  87. {sourcecode-2.6.5 → sourcecode-2.7.0}/src/sourcecode/detectors/project.py +0 -0
  88. {sourcecode-2.6.5 → sourcecode-2.7.0}/src/sourcecode/detectors/python.py +0 -0
  89. {sourcecode-2.6.5 → sourcecode-2.7.0}/src/sourcecode/detectors/ruby.py +0 -0
  90. {sourcecode-2.6.5 → sourcecode-2.7.0}/src/sourcecode/detectors/rust.py +0 -0
  91. {sourcecode-2.6.5 → sourcecode-2.7.0}/src/sourcecode/detectors/systems.py +0 -0
  92. {sourcecode-2.6.5 → sourcecode-2.7.0}/src/sourcecode/detectors/terraform.py +0 -0
  93. {sourcecode-2.6.5 → sourcecode-2.7.0}/src/sourcecode/detectors/tooling.py +0 -0
  94. {sourcecode-2.6.5 → sourcecode-2.7.0}/src/sourcecode/doc_analyzer.py +0 -0
  95. {sourcecode-2.6.5 → sourcecode-2.7.0}/src/sourcecode/dynamic_argument_surface.py +0 -0
  96. {sourcecode-2.6.5 → sourcecode-2.7.0}/src/sourcecode/endpoint_literals.py +0 -0
  97. {sourcecode-2.6.5 → sourcecode-2.7.0}/src/sourcecode/endpoint_metrics.py +0 -0
  98. {sourcecode-2.6.5 → sourcecode-2.7.0}/src/sourcecode/entrypoint_classifier.py +0 -0
  99. {sourcecode-2.6.5 → sourcecode-2.7.0}/src/sourcecode/env_analyzer.py +0 -0
  100. {sourcecode-2.6.5 → sourcecode-2.7.0}/src/sourcecode/error_schema.py +0 -0
  101. {sourcecode-2.6.5 → sourcecode-2.7.0}/src/sourcecode/evidence_provider.py +0 -0
  102. {sourcecode-2.6.5 → sourcecode-2.7.0}/src/sourcecode/file_chunker.py +0 -0
  103. {sourcecode-2.6.5 → sourcecode-2.7.0}/src/sourcecode/filter_surface.py +0 -0
  104. {sourcecode-2.6.5 → sourcecode-2.7.0}/src/sourcecode/format_contract.py +0 -0
  105. {sourcecode-2.6.5 → sourcecode-2.7.0}/src/sourcecode/fqn_utils.py +0 -0
  106. {sourcecode-2.6.5 → sourcecode-2.7.0}/src/sourcecode/git_analyzer.py +0 -0
  107. {sourcecode-2.6.5 → sourcecode-2.7.0}/src/sourcecode/graph_analyzer.py +0 -0
  108. {sourcecode-2.6.5 → sourcecode-2.7.0}/src/sourcecode/graph_evidence.py +0 -0
  109. {sourcecode-2.6.5 → sourcecode-2.7.0}/src/sourcecode/jdk_exports.py +0 -0
  110. {sourcecode-2.6.5 → sourcecode-2.7.0}/src/sourcecode/license.py +0 -0
  111. {sourcecode-2.6.5 → sourcecode-2.7.0}/src/sourcecode/mcp/__init__.py +0 -0
  112. {sourcecode-2.6.5 → sourcecode-2.7.0}/src/sourcecode/mcp/onboarding/__init__.py +0 -0
  113. {sourcecode-2.6.5 → sourcecode-2.7.0}/src/sourcecode/mcp/onboarding/backup.py +0 -0
  114. {sourcecode-2.6.5 → sourcecode-2.7.0}/src/sourcecode/mcp/orchestrator.py +0 -0
  115. {sourcecode-2.6.5 → sourcecode-2.7.0}/src/sourcecode/mcp/registry.py +0 -0
  116. {sourcecode-2.6.5 → sourcecode-2.7.0}/src/sourcecode/mcp/runner.py +0 -0
  117. {sourcecode-2.6.5 → sourcecode-2.7.0}/src/sourcecode/metrics_analyzer.py +0 -0
  118. {sourcecode-2.6.5 → sourcecode-2.7.0}/src/sourcecode/openapi_surface.py +0 -0
  119. {sourcecode-2.6.5 → sourcecode-2.7.0}/src/sourcecode/output_budget.py +0 -0
  120. {sourcecode-2.6.5 → sourcecode-2.7.0}/src/sourcecode/parse_cache.py +0 -0
  121. {sourcecode-2.6.5 → sourcecode-2.7.0}/src/sourcecode/path_filters.py +0 -0
  122. {sourcecode-2.6.5 → sourcecode-2.7.0}/src/sourcecode/perf.py +0 -0
  123. {sourcecode-2.6.5 → sourcecode-2.7.0}/src/sourcecode/pr_comment_renderer.py +0 -0
  124. {sourcecode-2.6.5 → sourcecode-2.7.0}/src/sourcecode/prepare_context.py +0 -0
  125. {sourcecode-2.6.5 → sourcecode-2.7.0}/src/sourcecode/progress.py +0 -0
  126. {sourcecode-2.6.5 → sourcecode-2.7.0}/src/sourcecode/ranking_engine.py +0 -0
  127. {sourcecode-2.6.5 → sourcecode-2.7.0}/src/sourcecode/reconciliation.py +0 -0
  128. {sourcecode-2.6.5 → sourcecode-2.7.0}/src/sourcecode/redactor.py +0 -0
  129. {sourcecode-2.6.5 → sourcecode-2.7.0}/src/sourcecode/relevance_scorer.py +0 -0
  130. {sourcecode-2.6.5 → sourcecode-2.7.0}/src/sourcecode/rename_refactor.py +0 -0
  131. {sourcecode-2.6.5 → sourcecode-2.7.0}/src/sourcecode/repo_classifier.py +0 -0
  132. {sourcecode-2.6.5 → sourcecode-2.7.0}/src/sourcecode/retrieval/__init__.py +0 -0
  133. {sourcecode-2.6.5 → sourcecode-2.7.0}/src/sourcecode/retrieval/context.py +0 -0
  134. {sourcecode-2.6.5 → sourcecode-2.7.0}/src/sourcecode/retrieval/errors.py +0 -0
  135. {sourcecode-2.6.5 → sourcecode-2.7.0}/src/sourcecode/retrieval/executor.py +0 -0
  136. {sourcecode-2.6.5 → sourcecode-2.7.0}/src/sourcecode/retrieval/planner.py +0 -0
  137. {sourcecode-2.6.5 → sourcecode-2.7.0}/src/sourcecode/retrieval/query.py +0 -0
  138. {sourcecode-2.6.5 → sourcecode-2.7.0}/src/sourcecode/retrieval/request.py +0 -0
  139. {sourcecode-2.6.5 → sourcecode-2.7.0}/src/sourcecode/retrieval/resolution.py +0 -0
  140. {sourcecode-2.6.5 → sourcecode-2.7.0}/src/sourcecode/retrieval/result.py +0 -0
  141. {sourcecode-2.6.5 → sourcecode-2.7.0}/src/sourcecode/retrieval/retriever.py +0 -0
  142. {sourcecode-2.6.5 → sourcecode-2.7.0}/src/sourcecode/retrieval/runtime.py +0 -0
  143. {sourcecode-2.6.5 → sourcecode-2.7.0}/src/sourcecode/retrieval/steps.py +0 -0
  144. {sourcecode-2.6.5 → sourcecode-2.7.0}/src/sourcecode/retrieval/steps_impact.py +0 -0
  145. {sourcecode-2.6.5 → sourcecode-2.7.0}/src/sourcecode/retrieval/steps_struct.py +0 -0
  146. {sourcecode-2.6.5 → sourcecode-2.7.0}/src/sourcecode/ris.py +0 -0
  147. {sourcecode-2.6.5 → sourcecode-2.7.0}/src/sourcecode/runtime_classifier.py +0 -0
  148. {sourcecode-2.6.5 → sourcecode-2.7.0}/src/sourcecode/scanner.py +0 -0
  149. {sourcecode-2.6.5 → sourcecode-2.7.0}/src/sourcecode/schema.py +0 -0
  150. {sourcecode-2.6.5 → sourcecode-2.7.0}/src/sourcecode/security_config.py +0 -0
  151. {sourcecode-2.6.5 → sourcecode-2.7.0}/src/sourcecode/semantic_analyzer.py +0 -0
  152. {sourcecode-2.6.5 → sourcecode-2.7.0}/src/sourcecode/semantic_impact_engine.py +0 -0
  153. {sourcecode-2.6.5 → sourcecode-2.7.0}/src/sourcecode/semantic_integration_engine.py +0 -0
  154. {sourcecode-2.6.5 → sourcecode-2.7.0}/src/sourcecode/semantic_services.py +0 -0
  155. {sourcecode-2.6.5 → sourcecode-2.7.0}/src/sourcecode/spring_event_topology.py +0 -0
  156. {sourcecode-2.6.5 → sourcecode-2.7.0}/src/sourcecode/spring_impact.py +0 -0
  157. {sourcecode-2.6.5 → sourcecode-2.7.0}/src/sourcecode/spring_model.py +0 -0
  158. {sourcecode-2.6.5 → sourcecode-2.7.0}/src/sourcecode/spring_security_audit.py +0 -0
  159. {sourcecode-2.6.5 → sourcecode-2.7.0}/src/sourcecode/spring_semantic.py +0 -0
  160. {sourcecode-2.6.5 → sourcecode-2.7.0}/src/sourcecode/spring_tx_analyzer.py +0 -0
  161. {sourcecode-2.6.5 → sourcecode-2.7.0}/src/sourcecode/summarizer.py +0 -0
  162. {sourcecode-2.6.5 → sourcecode-2.7.0}/src/sourcecode/telemetry/config.py +0 -0
  163. {sourcecode-2.6.5 → sourcecode-2.7.0}/src/sourcecode/telemetry/transport.py +0 -0
  164. {sourcecode-2.6.5 → sourcecode-2.7.0}/src/sourcecode/tree_utils.py +0 -0
  165. {sourcecode-2.6.5 → sourcecode-2.7.0}/src/sourcecode/type_usage_surface.py +0 -0
  166. {sourcecode-2.6.5 → sourcecode-2.7.0}/src/sourcecode/verify_edit.py +0 -0
  167. {sourcecode-2.6.5 → sourcecode-2.7.0}/src/sourcecode/verify_rules.py +0 -0
  168. {sourcecode-2.6.5 → sourcecode-2.7.0}/src/sourcecode/version_check.py +0 -0
  169. {sourcecode-2.6.5 → sourcecode-2.7.0}/src/sourcecode/workspace.py +0 -0
  170. {sourcecode-2.6.5 → sourcecode-2.7.0}/supabase/functions/README.md +0 -0
  171. {sourcecode-2.6.5 → sourcecode-2.7.0}/supabase/functions/get-license/index.ts +0 -0
  172. {sourcecode-2.6.5 → sourcecode-2.7.0}/supabase/functions/lemonsqueezy-webhook/index.ts +0 -0
  173. {sourcecode-2.6.5 → sourcecode-2.7.0}/supabase/functions/telemetry/index.ts +0 -0
  174. {sourcecode-2.6.5 → sourcecode-2.7.0}/supabase/sql/license_event_ordering.sql +0 -0
  175. {sourcecode-2.6.5 → sourcecode-2.7.0}/supabase/sql/licensing_schema.sql +0 -0
  176. {sourcecode-2.6.5 → sourcecode-2.7.0}/supabase/sql/telemetry_events.sql +0 -0
@@ -1,5 +1,209 @@
1
1
  # Changelog
2
2
 
3
+ ## [2.7.0] — 2026-07-26
4
+
5
+ **The analyzer reads facts it had been walking past, and stops spending the context budget
6
+ it exists to save.** Driven by an external audit of 2.6.10 and validated by a field battery
7
+ across eleven real repositories plus an A/B against the previous release.
8
+
9
+ ### Added
10
+
11
+ - **Deployment prefix.** Neither `server.servlet.context-path` nor `spring.mvc.servlet.path`
12
+ was read anywhere, so an app deployed under `/app-server/api` was inventoried as `/v1/x` —
13
+ every URL wrong by the same constant, which is what makes the error invisible. Endpoints
14
+ now carry `effective_path` alongside the mapping-relative `path`, plus a
15
+ `deployment_prefix` block with per-source provenance. A value carrying a placeholder, or
16
+ declared only under a profile, is recorded but never imposed on every route.
17
+ - **Two unread profile signals.** Profile names came from one signal — the
18
+ `application-{profile}.yml` filename convention. Multi-document activation
19
+ (`spring.config.activate.on-profile`) and `@Profile` on beans are read now, and
20
+ `profile_conditional_beans` says WHICH beans each profile switches — routinely the
21
+ security filter chain.
22
+ - **A repo's own authorization gate on the endpoint surface.** Custom-gate detection fed
23
+ only the `spring-audit` posture block; every other surface reported `policy: none_detected`
24
+ for each endpoint of a repo whose authorization runs entirely through its own annotation.
25
+ Such endpoints now carry `policy: custom_gate_inferred` with the annotation as evidence,
26
+ and the model becomes `custom_annotation_based`. Coverage and specificity alone were
27
+ measured to be insufficient for a per-endpoint claim — they select caching and
28
+ documentation annotations — so the claim additionally requires an in-repo `@interface`
29
+ declaration. Structural, no name matching.
30
+ - **`explain --limit`** (default 50), capping the list sections with the truncation and the
31
+ exact total stated in `warnings`. `--limit 0` restores the full lists.
32
+
33
+ ### Fixed
34
+
35
+ - **Cross-file `String` constants were not folded.** `@RequestMapping(Routes.BASE)` resolved
36
+ to nothing and "nothing" was emitted as the empty path, collapsing every handler of a
37
+ controller onto `GET /`. A repo-wide constant table is built from the pass the assembler
38
+ already runs; a name declared twice with different values is dropped, not guessed; what
39
+ still cannot be resolved is published as `path_resolution: "unresolved"` with the
40
+ expression, instead of a fabricated `/`. On keycloak this recovers three real endpoints
41
+ (`AuthZen.EVALUATION_PATH`, `AdapterConstants.K_LOGOUT`) with no route newly unresolved.
42
+ - **Types whose name sits on the line after the keyword** (`public class\n Name {`) were
43
+ not extracted.
44
+ - **Hibernate rewrite snippets quoted literal-blanked source**, emitting
45
+ `em.createNamedQuery("")` — dropping the query name, the one datum that makes the target
46
+ actionable.
47
+ - **Confidence described the lookup, not the answer.** `retrieve endpoint-security` graded
48
+ "high" whenever the reference resolved, so an endpoint with no policy and no finding came
49
+ back maximally confident about nothing. It is high only when evidence attaches, and an
50
+ explicit `evidence_absent` observation says which case it is.
51
+ - **Archetype counted signal diversity by cardinality**, which one dominant signal satisfies
52
+ trivially. "High" now also requires the top signal to supply at most 80% of the label's
53
+ score.
54
+ - **Cycle counts read as one command contradicting another** (`modernize` 15 tangles vs
55
+ `subsystem-coupling` 0 import cycles). Both are right and measure different graphs; a
56
+ shared reconciliation note now travels with both numbers.
57
+ - **`auth status` reported `pro: false`** while every Pro command ran under the
58
+ early-adoption unlock. It now reports the gating in force (`pro_gating`, `pro_effective`,
59
+ `pro_reason`).
60
+ - **`transaction-entrypoints` counted only `@Transactional` declared ON a controller**, so a
61
+ repo with 129 boundaries reported 1 entrypoint. Boundaries reachable from a controller
62
+ within 3 call hops are reported alongside, each labelled with its `entrypoint_basis`.
63
+ Rows that a signature-free FQN made indistinguishable (overloads) collapse with the count
64
+ kept as `occurrences`; rows that differ in any attribute stay separate.
65
+ - **`integration-inventory` said nothing four times**: identity keyed on
66
+ (kind, target-or-client) produced byte-identical rows. Rows collapse with `occurrences`,
67
+ and a null target carries the reason it is null. On Broadleaf: 9 rows → 4.
68
+ - **`cache warm <subdir>` warmed the whole monorepo**, populating a cache for a different
69
+ target than `ask <subdir>` reads. It warms exactly the path given and says so when that
70
+ differs from the git root.
71
+ - **`migrate-check --compact` shipped an empty `headline_blocker`**, forcing the reader back
72
+ into the full report. It names the weakest applicable axis, or says "none" /
73
+ "none_applicable". The guard against asserting a framework blocker without version
74
+ evidence is preserved.
75
+ - **`impact-chain` enumerations were unbounded.** Lists are capped; every total stays exact
76
+ in `metadata` and `truncated_lists`.
77
+ - **The profile signal was gated on the env-var scan**: a repo that declares profiles but
78
+ reads no environment variable published nothing about them — the exact shape the profile
79
+ signals were added for.
80
+
81
+ ### Changed
82
+
83
+ - **`export --c4` omits the code level (C4 level 4) by default.** It enumerates every symbol
84
+ per directory and dominated the export: keycloak 18.6 MB → 2.5 MB, Broadleaf 9.7 MB →
85
+ 1.1 MB. The omission is explicit in the payload (`included: false` with the reason and the
86
+ directory count) and `--c4-code` restores it.
87
+
88
+ ### Notes
89
+
90
+ - Validated before release: full suite (3,869 passed), eleven repositories × eight commands
91
+ with no crash and valid JSON throughout, output identical across `PYTHONHASHSEED` values
92
+ on cold caches, and an A/B against 2.6.10 in which every difference maps to a change listed
93
+ above.
94
+
95
+ ## [2.6.10] — 2026-07-25
96
+
97
+ **Identical runs now produce identical output.** Found by a field battery across twelve
98
+ real repositories.
99
+
100
+ ### Fixed
101
+
102
+ - **Annotation `evidence` had an unstable order** in the agent view's `file_relevance`:
103
+ the list came out of a frozenset, so its order depended on `PYTHONHASHSEED` and changed
104
+ between processes — the same repository analysed twice differed byte-for-byte while
105
+ being identical as data. The values were never wrong; the ordering defeated byte-level
106
+ diffing and reproducible caching. Long-standing, not introduced by a recent release.
107
+
108
+ ## [2.6.9] — 2026-07-25
109
+
110
+ **MCP tool usage is now counted, anonymously.** Which capabilities agents actually reach
111
+ for was invisible: MCP calls run the CLI in-process, so their events were
112
+ indistinguishable from direct CLI use.
113
+
114
+ ### Added
115
+
116
+ - **`mcp_tool_invoked` telemetry event** recording the invoked tool's own name
117
+ (`get_compact_context`, `get_impact_context`, …), whether it succeeded, and the existing
118
+ duration bucket. Counted once per call at the single dispatch point, on every exit path.
119
+
120
+ ### Notes
121
+
122
+ - The tool **arguments are never sent** — they carry repository paths — and neither is any
123
+ part of the result. The name is a fixed identifier from ASK Engine's own tool registry,
124
+ not user input, and the sanitization layer still shape-validates it before transmission.
125
+ - Same opt-out as every other event (`ask telemetry disable`, `SOURCECODE_TELEMETRY=0`,
126
+ `DO_NOT_TRACK=1`); with telemetry off, nothing is recorded. `docs/privacy.md` and the
127
+ first-run notice document the new field.
128
+
129
+ ## [2.6.8] — 2026-07-25
130
+
131
+ **One-click MCP setup now reaches Windsurf and VS Code.** `ask mcp init` / `status` /
132
+ `remove` cover four clients instead of two.
133
+
134
+ ### Added
135
+
136
+ - **Windsurf** (`--target windsurf`) and **VS Code** (`--target vscode`) as MCP onboarding
137
+ targets, detected from their standard per-platform config locations. VS Code keys its
138
+ servers under `servers` (not `mcpServers`) and receives an explicit `"type": "stdio"` on
139
+ the entry; the config shape is now a property of each client, so the other clients' files
140
+ are written exactly as before.
141
+
142
+ ### Fixed
143
+
144
+ - **`mcp status` reported a built-in server as `EXTERNAL`** for configs registered under the
145
+ canonical `ask` entry name: the drift check still looked up the deprecated `sourcecode`
146
+ key, under a hardcoded `mcpServers`. It now reads through the client's own key and accepts
147
+ either entry name.
148
+ - **The "no MCP clients found" hint printed the deprecated manual snippet** (`"sourcecode":
149
+ {"command": "sourcecode", ...}`). It now shows the canonical `ask` entry and notes VS
150
+ Code's different key.
151
+
152
+ ## [2.6.7] — 2026-07-25
153
+
154
+ **The context layer now reports what it saves: `_meta.token_economy`.** Responses used to
155
+ report only what ASK emits. They now also report the measured counterfactual — what reading
156
+ the same files raw would have cost the agent. Additive; no existing output changes.
157
+
158
+ ### Added
159
+
160
+ - **`_meta.token_economy` on the agent-facing responses** (`--compact`, `--agent`, and
161
+ `cold-start`, on both cache-hit and fresh paths; the MCP `get_compact_context` tool inherits
162
+ it). Fields: `emitted` (what this response costs), `baseline_raw_read` (what the agent would
163
+ have spent reading raw the files the response cites, plus the build manifests it derives
164
+ from), `saved`, `files_counted`, plus the declared `basis`, `token_model` and `estimate`
165
+ flag. Example on a small Spring repo: `--compact` emits ~1.1K tokens against a ~4.9K raw-read
166
+ baseline; `--agent` emits ~3.9K against ~16.3K over 22 cited files.
167
+ - **`sourcecode.token_estimate`** — `estimate_tokens()` and `token_economy()`, the single
168
+ source of the token model (previously an inline `size // 4` in `cold-start`).
169
+
170
+ ### Notes
171
+
172
+ - Honest by construction: the token model is `chars/4` — an approximation, declared on every
173
+ block, with no tokenizer dependency. A file counts toward the baseline only when the
174
+ response's own text resolves to a real file inside the repository, so fully-qualified names
175
+ and prose never inflate it; the baseline is the conservative cited-files-plus-manifests set,
176
+ never the whole repository; `saved` is clamped at zero; and the block is a pure function of
177
+ the response and the files on disk. It is an upper-bound estimate of tokens avoided, never a
178
+ monetary or ROI figure.
179
+ - No "hallucinations avoided" counter is emitted. It is not measurable, so it is not claimed;
180
+ what the product does guarantee — every claim carrying its `source_file` and FQN — is
181
+ already visible in the responses themselves.
182
+ - The cached view stored on disk never embeds the block; it is recomputed against the working
183
+ tree on every emission.
184
+
185
+ ## [2.6.6] — 2026-07-24
186
+
187
+ **Migration readiness as a time series: `migrate-check --snapshot` / `--trend`.** The
188
+ quantified, budgetable readiness figures can now be tracked across commits — the
189
+ days-remaining line a migration lead reports to management. Additive; no existing output
190
+ changes.
191
+
192
+ ### Added
193
+
194
+ - **`migrate-check --snapshot`** persists the run's budgetable figures — `readiness_score`,
195
+ `estimated_effort_days`, the per-dimension scores (jakarta / boot3 / hibernate / jdk),
196
+ and `blocking_count` — as a compact `readiness-snapshot-v1` artifact under `--history-dir`
197
+ (default `<repo>/.ask/readiness-history`). `--ref` labels the point (e.g. a sprint or
198
+ version). Capturing the same repo over successive commits builds the series.
199
+ - **`migrate-check --trend`** reads the stored series and reports first→last movement per
200
+ track (score and days-remaining over time), ordered by capture time. Honest by design:
201
+ movement only, never an improving/degrading label; no delta is emitted across a missing
202
+ endpoint (a `None` readiness yields no delta); and the `readiness_score` is flagged
203
+ `comparable: false` when the applicable dimension set changed between endpoints (the score
204
+ is a min over dimensions, so a different set is not strictly comparable). The projection is
205
+ deterministic for a fixed snapshot set.
206
+
3
207
  ## [2.6.5] — 2026-07-24
4
208
 
5
209
  **Mistyped-subcommand ergonomics: `ask` no longer swallows a typo'd command as a path
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: sourcecode
3
- Version: 2.6.5
3
+ Version: 2.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 = "2.6.5"
7
+ version = "2.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__ = "2.6.5"
7
+ __version__ = "2.7.0"
@@ -604,12 +604,23 @@ class ArchetypeClassifier:
604
604
  # Gini alone labeling a REST API an "engine") — is a single point of view and
605
605
  # must not read as high confidence (field-eval Fase 0).
606
606
  distinct_signals = len({e.signal for e in top.evidence if e.contribution > 0})
607
+ # Diversity by COUNT is satisfiable while one signal carries the
608
+ # verdict: an audited repo was labelled "engine" at high confidence on
609
+ # 1.500 of a 1.504 score — a fan-in Gini alone, with the second signal
610
+ # contributing 0.3%. Counting it as two views is a fiction, so a label
611
+ # whose top signal supplies almost all of its score cannot be "high"
612
+ # however many other signals nominally touch it.
613
+ _contributions = sorted(
614
+ (e.contribution for e in top.evidence if e.contribution > 0), reverse=True
615
+ )
616
+ top_signal_share = (_contributions[0] / top.score) if _contributions else 1.0
607
617
  if (
608
618
  confident_enough
609
619
  and rel_margin >= 0.4
610
620
  and mass_backed
611
621
  and graph_backed
612
622
  and distinct_signals >= 2
623
+ and top_signal_share <= 0.8
613
624
  ):
614
625
  confidence = "high"
615
626
  elif confident_enough and rel_margin >= 0.25 and mass_backed:
@@ -40,3 +40,22 @@ CALLER_METRIC_RECONCILIATION: str = (
40
40
  "references or DI-interface resolution). The top-level impact.direct_callers array "
41
41
  "may be truncated for output size — use stats.direct_caller_count for the true total."
42
42
  )
43
+
44
+
45
+ # Cycle / tangle metrics come from TWO different graphs. Both are correct; they
46
+ # answer different questions, and without saying so the pair reads as one command
47
+ # contradicting another (external audit 2026-07-25: modernize reported 15 cyclic
48
+ # tangles while retrieve subsystem-coupling reported import_cycles: 0).
49
+ CYCLE_METRIC_RECONCILIATION: str = (
50
+ "Cycle metrics differ across commands BY DESIGN. modernize.cross_module_tangles "
51
+ "is computed over the SYMBOL dependency graph, aggregated to subsystem packages: "
52
+ "coupling_type=cyclic means two subsystems reference each other (a 2-cycle "
53
+ "between package groups). The module-graph metrics (import_cycles, cyclic_density, "
54
+ "scc_mass — used by archetype and the subsystem-coupling retrieval intent) are "
55
+ "computed over the MODULE/DIRECTORY graph, are bounded for cost (node/edge caps), "
56
+ "and count strongly-connected components among modules. A repo can therefore "
57
+ "show mutual package-level coupling (tangles > 0) with no module-level SCC "
58
+ "(import_cycles = 0): the coupling exists between package groups inside the same "
59
+ "module. Neither number invalidates the other — read tangles for decomposition "
60
+ "risk and import_cycles for module-graph topology."
61
+ )