sourcecode 1.62.0__tar.gz → 1.64.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 (123) hide show
  1. {sourcecode-1.62.0 → sourcecode-1.64.0}/CHANGELOG.md +90 -0
  2. {sourcecode-1.62.0 → sourcecode-1.64.0}/PKG-INFO +71 -1
  3. {sourcecode-1.62.0 → sourcecode-1.64.0}/README.md +70 -0
  4. {sourcecode-1.62.0 → sourcecode-1.64.0}/pyproject.toml +1 -1
  5. {sourcecode-1.62.0 → sourcecode-1.64.0}/src/sourcecode/__init__.py +1 -1
  6. {sourcecode-1.62.0 → sourcecode-1.64.0}/src/sourcecode/cli.py +6 -3
  7. sourcecode-1.64.0/src/sourcecode/hibernate_strat.py +1161 -0
  8. {sourcecode-1.62.0 → sourcecode-1.64.0}/src/sourcecode/mcp/server.py +5 -1
  9. {sourcecode-1.62.0 → sourcecode-1.64.0}/src/sourcecode/migrate_check.py +99 -1
  10. {sourcecode-1.62.0 → sourcecode-1.64.0}/src/sourcecode/repository_ir.py +70 -0
  11. sourcecode-1.62.0/src/sourcecode/hibernate_strat.py +0 -599
  12. {sourcecode-1.62.0 → sourcecode-1.64.0}/.github/workflows/build-windows.yml +0 -0
  13. {sourcecode-1.62.0 → sourcecode-1.64.0}/.gitignore +0 -0
  14. {sourcecode-1.62.0 → sourcecode-1.64.0}/.ruff.toml +0 -0
  15. {sourcecode-1.62.0 → sourcecode-1.64.0}/CONTRIBUTING.md +0 -0
  16. {sourcecode-1.62.0 → sourcecode-1.64.0}/LICENSE +0 -0
  17. {sourcecode-1.62.0 → sourcecode-1.64.0}/SECURITY.md +0 -0
  18. {sourcecode-1.62.0 → sourcecode-1.64.0}/raw +0 -0
  19. {sourcecode-1.62.0 → sourcecode-1.64.0}/src/sourcecode/adaptive_scanner.py +0 -0
  20. {sourcecode-1.62.0 → sourcecode-1.64.0}/src/sourcecode/architecture_analyzer.py +0 -0
  21. {sourcecode-1.62.0 → sourcecode-1.64.0}/src/sourcecode/architecture_summary.py +0 -0
  22. {sourcecode-1.62.0 → sourcecode-1.64.0}/src/sourcecode/ast_extractor.py +0 -0
  23. {sourcecode-1.62.0 → sourcecode-1.64.0}/src/sourcecode/cache.py +0 -0
  24. {sourcecode-1.62.0 → sourcecode-1.64.0}/src/sourcecode/canonical_ir.py +0 -0
  25. {sourcecode-1.62.0 → sourcecode-1.64.0}/src/sourcecode/cir_graphs.py +0 -0
  26. {sourcecode-1.62.0 → sourcecode-1.64.0}/src/sourcecode/classifier.py +0 -0
  27. {sourcecode-1.62.0 → sourcecode-1.64.0}/src/sourcecode/code_notes_analyzer.py +0 -0
  28. {sourcecode-1.62.0 → sourcecode-1.64.0}/src/sourcecode/confidence_analyzer.py +0 -0
  29. {sourcecode-1.62.0 → sourcecode-1.64.0}/src/sourcecode/context_scorer.py +0 -0
  30. {sourcecode-1.62.0 → sourcecode-1.64.0}/src/sourcecode/context_summarizer.py +0 -0
  31. {sourcecode-1.62.0 → sourcecode-1.64.0}/src/sourcecode/contract_model.py +0 -0
  32. {sourcecode-1.62.0 → sourcecode-1.64.0}/src/sourcecode/contract_pipeline.py +0 -0
  33. {sourcecode-1.62.0 → sourcecode-1.64.0}/src/sourcecode/coverage_parser.py +0 -0
  34. {sourcecode-1.62.0 → sourcecode-1.64.0}/src/sourcecode/dependency_analyzer.py +0 -0
  35. {sourcecode-1.62.0 → sourcecode-1.64.0}/src/sourcecode/detectors/__init__.py +0 -0
  36. {sourcecode-1.62.0 → sourcecode-1.64.0}/src/sourcecode/detectors/base.py +0 -0
  37. {sourcecode-1.62.0 → sourcecode-1.64.0}/src/sourcecode/detectors/csproj_parser.py +0 -0
  38. {sourcecode-1.62.0 → sourcecode-1.64.0}/src/sourcecode/detectors/dart.py +0 -0
  39. {sourcecode-1.62.0 → sourcecode-1.64.0}/src/sourcecode/detectors/dotnet.py +0 -0
  40. {sourcecode-1.62.0 → sourcecode-1.64.0}/src/sourcecode/detectors/elixir.py +0 -0
  41. {sourcecode-1.62.0 → sourcecode-1.64.0}/src/sourcecode/detectors/go.py +0 -0
  42. {sourcecode-1.62.0 → sourcecode-1.64.0}/src/sourcecode/detectors/heuristic.py +0 -0
  43. {sourcecode-1.62.0 → sourcecode-1.64.0}/src/sourcecode/detectors/hybrid.py +0 -0
  44. {sourcecode-1.62.0 → sourcecode-1.64.0}/src/sourcecode/detectors/java.py +0 -0
  45. {sourcecode-1.62.0 → sourcecode-1.64.0}/src/sourcecode/detectors/jvm_ext.py +0 -0
  46. {sourcecode-1.62.0 → sourcecode-1.64.0}/src/sourcecode/detectors/nodejs.py +0 -0
  47. {sourcecode-1.62.0 → sourcecode-1.64.0}/src/sourcecode/detectors/parsers.py +0 -0
  48. {sourcecode-1.62.0 → sourcecode-1.64.0}/src/sourcecode/detectors/php.py +0 -0
  49. {sourcecode-1.62.0 → sourcecode-1.64.0}/src/sourcecode/detectors/project.py +0 -0
  50. {sourcecode-1.62.0 → sourcecode-1.64.0}/src/sourcecode/detectors/python.py +0 -0
  51. {sourcecode-1.62.0 → sourcecode-1.64.0}/src/sourcecode/detectors/ruby.py +0 -0
  52. {sourcecode-1.62.0 → sourcecode-1.64.0}/src/sourcecode/detectors/rust.py +0 -0
  53. {sourcecode-1.62.0 → sourcecode-1.64.0}/src/sourcecode/detectors/systems.py +0 -0
  54. {sourcecode-1.62.0 → sourcecode-1.64.0}/src/sourcecode/detectors/terraform.py +0 -0
  55. {sourcecode-1.62.0 → sourcecode-1.64.0}/src/sourcecode/detectors/tooling.py +0 -0
  56. {sourcecode-1.62.0 → sourcecode-1.64.0}/src/sourcecode/doc_analyzer.py +0 -0
  57. {sourcecode-1.62.0 → sourcecode-1.64.0}/src/sourcecode/entrypoint_classifier.py +0 -0
  58. {sourcecode-1.62.0 → sourcecode-1.64.0}/src/sourcecode/env_analyzer.py +0 -0
  59. {sourcecode-1.62.0 → sourcecode-1.64.0}/src/sourcecode/error_schema.py +0 -0
  60. {sourcecode-1.62.0 → sourcecode-1.64.0}/src/sourcecode/explain.py +0 -0
  61. {sourcecode-1.62.0 → sourcecode-1.64.0}/src/sourcecode/file_chunker.py +0 -0
  62. {sourcecode-1.62.0 → sourcecode-1.64.0}/src/sourcecode/file_classifier.py +0 -0
  63. {sourcecode-1.62.0 → sourcecode-1.64.0}/src/sourcecode/flow_analyzer.py +0 -0
  64. {sourcecode-1.62.0 → sourcecode-1.64.0}/src/sourcecode/format_contract.py +0 -0
  65. {sourcecode-1.62.0 → sourcecode-1.64.0}/src/sourcecode/fqn_utils.py +0 -0
  66. {sourcecode-1.62.0 → sourcecode-1.64.0}/src/sourcecode/git_analyzer.py +0 -0
  67. {sourcecode-1.62.0 → sourcecode-1.64.0}/src/sourcecode/graph_analyzer.py +0 -0
  68. {sourcecode-1.62.0 → sourcecode-1.64.0}/src/sourcecode/integration_detector.py +0 -0
  69. {sourcecode-1.62.0 → sourcecode-1.64.0}/src/sourcecode/license.py +0 -0
  70. {sourcecode-1.62.0 → sourcecode-1.64.0}/src/sourcecode/mcp/__init__.py +0 -0
  71. {sourcecode-1.62.0 → sourcecode-1.64.0}/src/sourcecode/mcp/onboarding/__init__.py +0 -0
  72. {sourcecode-1.62.0 → sourcecode-1.64.0}/src/sourcecode/mcp/onboarding/applier.py +0 -0
  73. {sourcecode-1.62.0 → sourcecode-1.64.0}/src/sourcecode/mcp/onboarding/backup.py +0 -0
  74. {sourcecode-1.62.0 → sourcecode-1.64.0}/src/sourcecode/mcp/onboarding/detector.py +0 -0
  75. {sourcecode-1.62.0 → sourcecode-1.64.0}/src/sourcecode/mcp/onboarding/planner.py +0 -0
  76. {sourcecode-1.62.0 → sourcecode-1.64.0}/src/sourcecode/mcp/orchestrator.py +0 -0
  77. {sourcecode-1.62.0 → sourcecode-1.64.0}/src/sourcecode/mcp/registry.py +0 -0
  78. {sourcecode-1.62.0 → sourcecode-1.64.0}/src/sourcecode/mcp/runner.py +0 -0
  79. {sourcecode-1.62.0 → sourcecode-1.64.0}/src/sourcecode/mcp_nudge.py +0 -0
  80. {sourcecode-1.62.0 → sourcecode-1.64.0}/src/sourcecode/metrics_analyzer.py +0 -0
  81. {sourcecode-1.62.0 → sourcecode-1.64.0}/src/sourcecode/openapi_surface.py +0 -0
  82. {sourcecode-1.62.0 → sourcecode-1.64.0}/src/sourcecode/output_budget.py +0 -0
  83. {sourcecode-1.62.0 → sourcecode-1.64.0}/src/sourcecode/path_filters.py +0 -0
  84. {sourcecode-1.62.0 → sourcecode-1.64.0}/src/sourcecode/pr_comment_renderer.py +0 -0
  85. {sourcecode-1.62.0 → sourcecode-1.64.0}/src/sourcecode/pr_impact.py +0 -0
  86. {sourcecode-1.62.0 → sourcecode-1.64.0}/src/sourcecode/prepare_context.py +0 -0
  87. {sourcecode-1.62.0 → sourcecode-1.64.0}/src/sourcecode/progress.py +0 -0
  88. {sourcecode-1.62.0 → sourcecode-1.64.0}/src/sourcecode/ranking_engine.py +0 -0
  89. {sourcecode-1.62.0 → sourcecode-1.64.0}/src/sourcecode/redactor.py +0 -0
  90. {sourcecode-1.62.0 → sourcecode-1.64.0}/src/sourcecode/relevance_scorer.py +0 -0
  91. {sourcecode-1.62.0 → sourcecode-1.64.0}/src/sourcecode/rename_refactor.py +0 -0
  92. {sourcecode-1.62.0 → sourcecode-1.64.0}/src/sourcecode/repo_classifier.py +0 -0
  93. {sourcecode-1.62.0 → sourcecode-1.64.0}/src/sourcecode/ris.py +0 -0
  94. {sourcecode-1.62.0 → sourcecode-1.64.0}/src/sourcecode/runtime_classifier.py +0 -0
  95. {sourcecode-1.62.0 → sourcecode-1.64.0}/src/sourcecode/scanner.py +0 -0
  96. {sourcecode-1.62.0 → sourcecode-1.64.0}/src/sourcecode/schema.py +0 -0
  97. {sourcecode-1.62.0 → sourcecode-1.64.0}/src/sourcecode/security_config.py +0 -0
  98. {sourcecode-1.62.0 → sourcecode-1.64.0}/src/sourcecode/semantic_analyzer.py +0 -0
  99. {sourcecode-1.62.0 → sourcecode-1.64.0}/src/sourcecode/serializer.py +0 -0
  100. {sourcecode-1.62.0 → sourcecode-1.64.0}/src/sourcecode/spring_event_topology.py +0 -0
  101. {sourcecode-1.62.0 → sourcecode-1.64.0}/src/sourcecode/spring_findings.py +0 -0
  102. {sourcecode-1.62.0 → sourcecode-1.64.0}/src/sourcecode/spring_impact.py +0 -0
  103. {sourcecode-1.62.0 → sourcecode-1.64.0}/src/sourcecode/spring_model.py +0 -0
  104. {sourcecode-1.62.0 → sourcecode-1.64.0}/src/sourcecode/spring_security_audit.py +0 -0
  105. {sourcecode-1.62.0 → sourcecode-1.64.0}/src/sourcecode/spring_semantic.py +0 -0
  106. {sourcecode-1.62.0 → sourcecode-1.64.0}/src/sourcecode/spring_tx_analyzer.py +0 -0
  107. {sourcecode-1.62.0 → sourcecode-1.64.0}/src/sourcecode/summarizer.py +0 -0
  108. {sourcecode-1.62.0 → sourcecode-1.64.0}/src/sourcecode/telemetry/__init__.py +0 -0
  109. {sourcecode-1.62.0 → sourcecode-1.64.0}/src/sourcecode/telemetry/config.py +0 -0
  110. {sourcecode-1.62.0 → sourcecode-1.64.0}/src/sourcecode/telemetry/consent.py +0 -0
  111. {sourcecode-1.62.0 → sourcecode-1.64.0}/src/sourcecode/telemetry/events.py +0 -0
  112. {sourcecode-1.62.0 → sourcecode-1.64.0}/src/sourcecode/telemetry/filters.py +0 -0
  113. {sourcecode-1.62.0 → sourcecode-1.64.0}/src/sourcecode/telemetry/transport.py +0 -0
  114. {sourcecode-1.62.0 → sourcecode-1.64.0}/src/sourcecode/tree_utils.py +0 -0
  115. {sourcecode-1.62.0 → sourcecode-1.64.0}/src/sourcecode/validation_surface.py +0 -0
  116. {sourcecode-1.62.0 → sourcecode-1.64.0}/src/sourcecode/version_check.py +0 -0
  117. {sourcecode-1.62.0 → sourcecode-1.64.0}/src/sourcecode/workspace.py +0 -0
  118. {sourcecode-1.62.0 → sourcecode-1.64.0}/supabase/functions/README.md +0 -0
  119. {sourcecode-1.62.0 → sourcecode-1.64.0}/supabase/functions/get-license/index.ts +0 -0
  120. {sourcecode-1.62.0 → sourcecode-1.64.0}/supabase/functions/lemonsqueezy-webhook/index.ts +0 -0
  121. {sourcecode-1.62.0 → sourcecode-1.64.0}/supabase/functions/telemetry/index.ts +0 -0
  122. {sourcecode-1.62.0 → sourcecode-1.64.0}/supabase/sql/license_event_ordering.sql +0 -0
  123. {sourcecode-1.62.0 → sourcecode-1.64.0}/supabase/sql/telemetry_events.sql +0 -0
@@ -1,5 +1,95 @@
1
1
  # Changelog
2
2
 
3
+ ## [1.64.0] — 2026-06-30
4
+
5
+ ### Fixed — zero false-positive blockers (`migrate-check` / `endpoints`)
6
+
7
+ A Pro audit of a real enterprise repo (Alfresco Content Services Community, 6,549
8
+ classes) surfaced false blockers that would have invalidated a ~2 person-month
9
+ budget decision. A migration blocker is a high-cost claim: if the tool cannot
10
+ **prove** it from resolved AST/dependency signals, it must not be declared. This
11
+ release enforces that — blockers operate on parsed imports / fully-qualified type
12
+ references, never on a substring inside a comment, Javadoc, string literal, or
13
+ classpath resource path. The `hibernate` sub-`schema_version` is now **2.1**.
14
+
15
+ - **Phantom Hibernate eliminated.** Hibernate detection now requires real evidence:
16
+ an `org.hibernate:*` build dependency, a parsed `import org.hibernate.*`, or a
17
+ parsed `import {jakarta,javax}.persistence.*`. Absent all three →
18
+ `hibernate.detected = false`, no `hibernate_rewrite` headline, no phantom effort.
19
+ All scanning runs on source with comments + string/char literals stripped (line
20
+ numbers preserved), so an `org.hibernate.dialect.*` substring in Javadoc or an
21
+ iBatis resource path can no longer trigger a verdict. Over-generic Criteria tokens
22
+ (`Predicate`, `Root<`, `Criterion`, `Conjunction`, `Disjunction`) were dropped —
23
+ they collide with project-owned domain classes. SPI bare-name matches
24
+ (`implements XInterceptor`, `extends XEventListener`) now require an
25
+ `org.hibernate` import in the same file; FQN-anchored SPI matches still count
26
+ on their own. New `hibernate.evidence{}` records the proof + `confidence`.
27
+ - **MIG-004 / jakarta rules respect a JDK allowlist.** `javax.transaction.xa.*`
28
+ (the Java SE `java.transaction.xa` module), `javax.annotation.processing.*`,
29
+ `javax.sql.*`, `javax.xml.parsers/transform/...`, `javax.management.*`,
30
+ `javax.crypto.*`, and the other permanent JDK/JSR `javax` namespaces no longer
31
+ count as jakarta-migration findings. App-level `javax.transaction.Transactional`,
32
+ `javax.annotation.PostConstruct`, etc. are still flagged (true positives kept).
33
+ Matching is by fully-qualified import prefix, not simple name or partial token.
34
+ - **`readiness_score` no longer sinks on an N/A dimension.** A dimension that does
35
+ not apply (e.g. Hibernate on a repo with no Hibernate) is reported as N/A
36
+ (`score: null`), never as 0. New `applicable_dimensions{}` and `readiness_note`
37
+ make the aggregate's derivation explicit — read the per-dimension breakdown +
38
+ `blocking_count`, not the single number.
39
+ - **`endpoints` never implies "no API".** When the Spring-MVC surface is empty but
40
+ another REST framework is present (Alfresco WebScripts via `*.desc.xml` +
41
+ `AbstractWebScript`/`DeclarativeWebScript`, JAX-RS, or mapped Servlets),
42
+ `security_model` becomes `"undetermined"` (not `"unknown"`), a
43
+ `non_spring_rest_surface{}` block is emitted, and a warning states the surface is
44
+ unmodeled — so `total: 0` is never read as "this app exposes no endpoints".
45
+
46
+ ### Tests
47
+
48
+ - New `tests/test_falsepositive_fixes.py` — positive **and** negative fixtures per
49
+ bug (phantom comment-only repo, project-owned `Dialect`/`Criteria`/`Interceptor`
50
+ classes, `javax.transaction.xa`, WebScripts) alongside the true positives that
51
+ must be preserved (real Hibernate, `javax.transaction.Transactional`,
52
+ `@RestController`). Full suite: 2827 passed.
53
+
54
+ ## [1.63.0] — 2026-06-29
55
+
56
+ ### Added — actionable Hibernate rewrite targets (`migrate-check`)
57
+
58
+ The Hibernate stratification went from **diagnostic** (how many files/occurrences
59
+ per layer) to **actionable** (what to rewrite, where, and to what) so a migration
60
+ agent can consume the output directly without re-parsing the repo. The `hibernate`
61
+ section gains a sub-`schema_version` (now **2.0**); all existing keys preserved.
62
+
63
+ - **`hibernate.rewrite_targets[]`** — one machine-readable target per call site:
64
+ `id`, `layer`, `source_file`, `line_start`/`line_end`, `current_pattern`,
65
+ `current_snippet`, `target_api` (the Hibernate-6 destination), `migration_kind`
66
+ (`manual_rewrite` / `assisted` / `mechanical` / `review`), `auto_migratable`,
67
+ `blocking_reason`, `symbol` (enclosing `Class#method`), `module`, `dynamic`.
68
+ Mapping rules: legacy `org.hibernate.Criteria`/`Restrictions`/`Projections` →
69
+ `CriteriaBuilder` (manual); `@Type(type=)` → `@Type(value=)`/`@JdbcTypeCode`
70
+ (mechanical, auto); `@TypeDef`/`@GenericGenerator` → assisted; concatenated HQL →
71
+ assisted + `runtime-resolved string`; `UserType`/`Interceptor`/`EventListener`/SPI
72
+ → its H6 contract (manual). Standard JPA annotations emit **no** targets.
73
+ - **Per-layer migration-kind sub-counts** in `risk_matrix` (`manual_count`,
74
+ `assisted_count`, `mechanical_count`, `review_count`); Criteria adds
75
+ `static_count` vs `dynamic_count`; SPI adds `userType_rewrite_count` vs
76
+ `userType_resolvable_count` — so dynamic/reflexive cost is not blended into static.
77
+ - **Honest effort** — each layer carries `effort_range` `{low, high, confidence}`
78
+ (legacy `estimated_effort` string kept); `hibernate.total_effort_range_days`
79
+ aggregates them; `hibernate.effort_model` exposes the auditable formula and the
80
+ caveat that layers may share files (the total is an upper bound, not deduplicated).
81
+ - **`hibernate_readiness` (0–100)** — 4th readiness dimension alongside
82
+ jakarta/boot3/jdk. It does **not** sink the headline `readiness_score` (Hibernate
83
+ is an orthogonal rewrite axis), but in a rewrite zone `headline_blocker` is set to
84
+ `"hibernate_rewrite"` so a reader of "62/100" is not misled.
85
+ - **`hibernate.golden_sql_hotspots[]`** — classes/methods that concentrate dynamic
86
+ query generation, ranked by reflexive-query volume — where to pin golden-SQL tests.
87
+
88
+ ### Fixed
89
+
90
+ - `get_migration_readiness` MCP test asserted the pre-1.62 report `schema_version`
91
+ `1.3`; the v1.62.0 schema bump to `1.4` made it stale. Corrected to `1.4`.
92
+
3
93
  ## [1.62.0] — 2026-06-29
4
94
 
5
95
  ### Added — Hibernate 5.x → 6.x migration stratification (`migrate-check`)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: sourcecode
3
- Version: 1.62.0
3
+ Version: 1.64.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
@@ -377,6 +377,8 @@ Extracts all Spring MVC (`@GetMapping`, `@PostMapping`, `@RequestMapping`, etc.)
377
377
 
378
378
  **Functional / WebFlux routing (honest limitation).** Routes registered via the functional DSL — `route().GET("/path", handler)` / `RouterFunction` / `CustomEndpoint`, common in reactive Spring apps — are **not** modeled (their real paths depend on `nest()`/group-version prefixes that can't be resolved statically). Rather than emit partial paths that would mislead, the output reports a `functional_routing` block (`files`, `route_registrations`, `modeled: false`) plus a warning. When the annotation surface is empty but functional routes exist, the warning explicitly tells you not to read it as "no endpoints". Annotation-based (MVC/JAX-RS) repos are unaffected.
379
379
 
380
+ **Non-Spring REST frameworks (never "no API").** When the Spring-MVC surface is empty but the repo exposes REST another way — Alfresco WebScripts (`*.desc.xml` descriptors + classes extending `AbstractWebScript`/`DeclarativeWebScript`), JAX-RS, or mapped Servlets — `security_model` is reported as `"undetermined"` (never `"unknown"`, which downstream reads as "no security"), a `non_spring_rest_surface` block names the detected frameworks, and a warning states the surface is unmodeled. `total: 0` therefore can never be read as "this application exposes no API".
381
+
380
382
  **Custom security annotations.** Enterprise repos often guard endpoints with a bespoke annotation instead of `@PreAuthorize`/`@Secured`. Drop a `sourcecode.config.json` at the repo root to teach the scanner about it — otherwise those endpoints report `policy: "none_detected"`:
381
383
 
382
384
  ```json
@@ -657,6 +659,74 @@ Detects migration blockers across Java source files, Spring XML config files, an
657
659
 
658
660
  Each finding includes `severity`, `title`, `source_file`, `first_line`, `explanation`, `fix_hint`, `migration_target`, and `openrewrite_recipe` (when an automated recipe exists).
659
661
 
662
+ #### Hibernate 5.x → 6.x stratification (the `hibernate` output section)
663
+
664
+ A Hibernate major upgrade is **not** a single dependency bump for systems that use
665
+ dynamic persistence. `migrate-check` stratifies Hibernate exposure into four
666
+ independent migration domains — never one aggregated score — and emits **actionable,
667
+ machine-readable rewrite targets** so a migration agent can consume the output
668
+ directly instead of re-parsing the repo. Sub-`schema_version`: `2.1`.
669
+
670
+ > **Evidence-gated (no false blockers).** Hibernate detection requires real proof —
671
+ > an `org.hibernate:*` build dependency, a parsed `import org.hibernate.*`, or a
672
+ > parsed `import {jakarta,javax}.persistence.*`. Absent all three,
673
+ > `hibernate.detected` is `false` (no `hibernate_rewrite` headline, no phantom
674
+ > effort). Scanning runs on source with comments + string/char literals stripped, so
675
+ > an `org.hibernate.*` substring in Javadoc or a classpath resource path never
676
+ > triggers a verdict; bare-name SPI matches (`implements XInterceptor`) require an
677
+ > `org.hibernate` import in the same file. The proof is recorded under
678
+ > `hibernate.evidence{}` with a `confidence`.
679
+
680
+ **Four layers** (each on its own risk axis):
681
+
682
+ | Layer | Baseline | Escalates to |
683
+ |-------|----------|--------------|
684
+ | `jpa_annotations` | LOW (namespace handled by jakarta) | HIGH on deprecated `@Type(type=)` / `@TypeDef` / `@GenericGenerator` |
685
+ | `criteria_api` | HIGH (JPA Criteria semantics changed; legacy `org.hibernate.Criteria` removed) | **CRITICAL** when built via reflection / abstraction DAOs (`DynamicEntityDao`, `GenericDao`, `BasicPersistenceModule`) |
686
+ | `hql_string_queries` | MEDIUM (revalidate against H6 parser) | HIGH on string concatenation (SQL shape not statically inferable) |
687
+ | `hibernate_spi_internal` | CRITICAL blocker | `UserType`, `CompositeUserType`, `Interceptor`, `EventListener`, `org.hibernate.engine.spi` |
688
+
689
+ **Output keys (under `hibernate`):**
690
+
691
+ - `classification` — `upgrade_zone` / `upgrade_with_care` / `rewrite_zone`. Any of
692
+ {dynamic Criteria, custom SPI, reflection-built queries, concatenated query
693
+ strings} forces **`rewrite_zone`** ("HIGH RISK REWRITE ZONE, NOT UPGRADE ZONE").
694
+ - `risk_matrix[]` — per layer: `risk`, `reason`, `effort_range {low, high, confidence}`,
695
+ `file_count`, `occurrence_count`, migration-kind sub-counts (`manual_count`,
696
+ `assisted_count`, `mechanical_count`, `review_count`); Criteria adds
697
+ `static_count` vs `dynamic_count`; SPI adds `userType_rewrite_count` vs
698
+ `userType_resolvable_count`.
699
+ - `rewrite_targets[]` — one actionable target per call site: `id`, `layer`,
700
+ `source_file`, `line_start`/`line_end`, `current_pattern`, `current_snippet`,
701
+ `target_api` (the Hibernate-6 destination), `migration_kind`
702
+ (`manual_rewrite` / `assisted` / `mechanical` / `review`), `auto_migratable`,
703
+ `blocking_reason`, `symbol` (enclosing `Class#method`), `module`, `dynamic`.
704
+ - `module_exposure_map` — per Maven/Gradle module: `max_risk`, layers present, and
705
+ `dynamic-criteria` / `custom-SPI` / `reflection` tags.
706
+ - `critical_call_chains[]` — dynamic query-generation paths (reflection-based DAOs).
707
+ - `golden_sql_hotspots[]` — classes/methods ranked by dynamic-query volume — where
708
+ to pin golden-SQL behaviour tests before migrating.
709
+ - `total_effort_range_days` + `effort_model` — aggregate range plus the auditable
710
+ formula (and the caveat that layers may share files, so the total is an upper bound).
711
+ - `stop_conditions_triggered[]`, `risk_separation` (observable vs inferred runtime risk).
712
+
713
+ The report also exposes **`hibernate_readiness`** (0–100) as a fourth readiness
714
+ dimension alongside `jakarta_readiness` / `boot3_readiness` / `jdk_modernization`.
715
+ Hibernate is an orthogonal rewrite axis, so it does not sink the headline
716
+ `readiness_score`; instead, in a rewrite zone the top-level `headline_blocker` is set
717
+ to `"hibernate_rewrite"` so a reader of the headline score is not misled.
718
+
719
+ A dimension that does not apply (e.g. Hibernate on a repo with no Hibernate) is
720
+ reported as **N/A** (`score: null`), never as `0`. The top-level
721
+ `applicable_dimensions{}` records which dimensions apply and `readiness_note`
722
+ states that `readiness_score` is a derived aggregate over applicable dimensions
723
+ only — for decisions, read the per-dimension breakdown + `blocking_count`.
724
+
725
+ ```bash
726
+ # inspect only the Hibernate rewrite targets
727
+ sourcecode migrate-check . --format json | jq '.hibernate.rewrite_targets[]'
728
+ ```
729
+
660
730
  ### `rename-class` — Java class rename
661
731
 
662
732
  ```bash
@@ -339,6 +339,8 @@ Extracts all Spring MVC (`@GetMapping`, `@PostMapping`, `@RequestMapping`, etc.)
339
339
 
340
340
  **Functional / WebFlux routing (honest limitation).** Routes registered via the functional DSL — `route().GET("/path", handler)` / `RouterFunction` / `CustomEndpoint`, common in reactive Spring apps — are **not** modeled (their real paths depend on `nest()`/group-version prefixes that can't be resolved statically). Rather than emit partial paths that would mislead, the output reports a `functional_routing` block (`files`, `route_registrations`, `modeled: false`) plus a warning. When the annotation surface is empty but functional routes exist, the warning explicitly tells you not to read it as "no endpoints". Annotation-based (MVC/JAX-RS) repos are unaffected.
341
341
 
342
+ **Non-Spring REST frameworks (never "no API").** When the Spring-MVC surface is empty but the repo exposes REST another way — Alfresco WebScripts (`*.desc.xml` descriptors + classes extending `AbstractWebScript`/`DeclarativeWebScript`), JAX-RS, or mapped Servlets — `security_model` is reported as `"undetermined"` (never `"unknown"`, which downstream reads as "no security"), a `non_spring_rest_surface` block names the detected frameworks, and a warning states the surface is unmodeled. `total: 0` therefore can never be read as "this application exposes no API".
343
+
342
344
  **Custom security annotations.** Enterprise repos often guard endpoints with a bespoke annotation instead of `@PreAuthorize`/`@Secured`. Drop a `sourcecode.config.json` at the repo root to teach the scanner about it — otherwise those endpoints report `policy: "none_detected"`:
343
345
 
344
346
  ```json
@@ -619,6 +621,74 @@ Detects migration blockers across Java source files, Spring XML config files, an
619
621
 
620
622
  Each finding includes `severity`, `title`, `source_file`, `first_line`, `explanation`, `fix_hint`, `migration_target`, and `openrewrite_recipe` (when an automated recipe exists).
621
623
 
624
+ #### Hibernate 5.x → 6.x stratification (the `hibernate` output section)
625
+
626
+ A Hibernate major upgrade is **not** a single dependency bump for systems that use
627
+ dynamic persistence. `migrate-check` stratifies Hibernate exposure into four
628
+ independent migration domains — never one aggregated score — and emits **actionable,
629
+ machine-readable rewrite targets** so a migration agent can consume the output
630
+ directly instead of re-parsing the repo. Sub-`schema_version`: `2.1`.
631
+
632
+ > **Evidence-gated (no false blockers).** Hibernate detection requires real proof —
633
+ > an `org.hibernate:*` build dependency, a parsed `import org.hibernate.*`, or a
634
+ > parsed `import {jakarta,javax}.persistence.*`. Absent all three,
635
+ > `hibernate.detected` is `false` (no `hibernate_rewrite` headline, no phantom
636
+ > effort). Scanning runs on source with comments + string/char literals stripped, so
637
+ > an `org.hibernate.*` substring in Javadoc or a classpath resource path never
638
+ > triggers a verdict; bare-name SPI matches (`implements XInterceptor`) require an
639
+ > `org.hibernate` import in the same file. The proof is recorded under
640
+ > `hibernate.evidence{}` with a `confidence`.
641
+
642
+ **Four layers** (each on its own risk axis):
643
+
644
+ | Layer | Baseline | Escalates to |
645
+ |-------|----------|--------------|
646
+ | `jpa_annotations` | LOW (namespace handled by jakarta) | HIGH on deprecated `@Type(type=)` / `@TypeDef` / `@GenericGenerator` |
647
+ | `criteria_api` | HIGH (JPA Criteria semantics changed; legacy `org.hibernate.Criteria` removed) | **CRITICAL** when built via reflection / abstraction DAOs (`DynamicEntityDao`, `GenericDao`, `BasicPersistenceModule`) |
648
+ | `hql_string_queries` | MEDIUM (revalidate against H6 parser) | HIGH on string concatenation (SQL shape not statically inferable) |
649
+ | `hibernate_spi_internal` | CRITICAL blocker | `UserType`, `CompositeUserType`, `Interceptor`, `EventListener`, `org.hibernate.engine.spi` |
650
+
651
+ **Output keys (under `hibernate`):**
652
+
653
+ - `classification` — `upgrade_zone` / `upgrade_with_care` / `rewrite_zone`. Any of
654
+ {dynamic Criteria, custom SPI, reflection-built queries, concatenated query
655
+ strings} forces **`rewrite_zone`** ("HIGH RISK REWRITE ZONE, NOT UPGRADE ZONE").
656
+ - `risk_matrix[]` — per layer: `risk`, `reason`, `effort_range {low, high, confidence}`,
657
+ `file_count`, `occurrence_count`, migration-kind sub-counts (`manual_count`,
658
+ `assisted_count`, `mechanical_count`, `review_count`); Criteria adds
659
+ `static_count` vs `dynamic_count`; SPI adds `userType_rewrite_count` vs
660
+ `userType_resolvable_count`.
661
+ - `rewrite_targets[]` — one actionable target per call site: `id`, `layer`,
662
+ `source_file`, `line_start`/`line_end`, `current_pattern`, `current_snippet`,
663
+ `target_api` (the Hibernate-6 destination), `migration_kind`
664
+ (`manual_rewrite` / `assisted` / `mechanical` / `review`), `auto_migratable`,
665
+ `blocking_reason`, `symbol` (enclosing `Class#method`), `module`, `dynamic`.
666
+ - `module_exposure_map` — per Maven/Gradle module: `max_risk`, layers present, and
667
+ `dynamic-criteria` / `custom-SPI` / `reflection` tags.
668
+ - `critical_call_chains[]` — dynamic query-generation paths (reflection-based DAOs).
669
+ - `golden_sql_hotspots[]` — classes/methods ranked by dynamic-query volume — where
670
+ to pin golden-SQL behaviour tests before migrating.
671
+ - `total_effort_range_days` + `effort_model` — aggregate range plus the auditable
672
+ formula (and the caveat that layers may share files, so the total is an upper bound).
673
+ - `stop_conditions_triggered[]`, `risk_separation` (observable vs inferred runtime risk).
674
+
675
+ The report also exposes **`hibernate_readiness`** (0–100) as a fourth readiness
676
+ dimension alongside `jakarta_readiness` / `boot3_readiness` / `jdk_modernization`.
677
+ Hibernate is an orthogonal rewrite axis, so it does not sink the headline
678
+ `readiness_score`; instead, in a rewrite zone the top-level `headline_blocker` is set
679
+ to `"hibernate_rewrite"` so a reader of the headline score is not misled.
680
+
681
+ A dimension that does not apply (e.g. Hibernate on a repo with no Hibernate) is
682
+ reported as **N/A** (`score: null`), never as `0`. The top-level
683
+ `applicable_dimensions{}` records which dimensions apply and `readiness_note`
684
+ states that `readiness_score` is a derived aggregate over applicable dimensions
685
+ only — for decisions, read the per-dimension breakdown + `blocking_count`.
686
+
687
+ ```bash
688
+ # inspect only the Hibernate rewrite targets
689
+ sourcecode migrate-check . --format json | jq '.hibernate.rewrite_targets[]'
690
+ ```
691
+
622
692
  ### `rename-class` — Java class rename
623
693
 
624
694
  ```bash
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "sourcecode"
7
- version = "1.62.0"
7
+ version = "1.64.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"
@@ -1,3 +1,3 @@
1
1
  """sourcecode — Deterministic codebase context maps for AI coding agents."""
2
2
 
3
- __version__ = "1.62.0"
3
+ __version__ = "1.64.0"
@@ -4841,9 +4841,12 @@ def migrate_check_cmd(
4841
4841
  \b
4842
4842
  Hibernate 5→6 stratification (in the 'hibernate' output section):
4843
4843
  4 independent layers (JPA annotations / Criteria / HQL / SPI), a per-layer
4844
- risk matrix, a module exposure map, critical call-chain detection, and an
4845
- UPGRADE vs REWRITE verdict (dynamic Criteria, custom SPI, reflection-built
4846
- queries, or concatenated query strings force the REWRITE classification).
4844
+ risk matrix with effort ranges, a module exposure map, critical call-chain
4845
+ detection, golden-SQL hotspots, a hibernate_readiness score, and an UPGRADE
4846
+ vs REWRITE verdict (dynamic Criteria, custom SPI, reflection-built queries,
4847
+ or concatenated query strings force the REWRITE classification).
4848
+ Emits actionable rewrite_targets[] (call-site line ranges → target_api +
4849
+ migration_kind) so a migration agent can consume the output directly.
4847
4850
 
4848
4851
  \b
4849
4852
  Examples: