sourcecode 1.63.0__tar.gz → 1.65.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 (122) hide show
  1. {sourcecode-1.63.0 → sourcecode-1.65.0}/CHANGELOG.md +105 -0
  2. {sourcecode-1.63.0 → sourcecode-1.65.0}/PKG-INFO +52 -4
  3. {sourcecode-1.63.0 → sourcecode-1.65.0}/README.md +51 -3
  4. {sourcecode-1.63.0 → sourcecode-1.65.0}/pyproject.toml +1 -1
  5. {sourcecode-1.63.0 → sourcecode-1.65.0}/src/sourcecode/__init__.py +1 -1
  6. {sourcecode-1.63.0 → sourcecode-1.65.0}/src/sourcecode/hibernate_strat.py +296 -15
  7. {sourcecode-1.63.0 → sourcecode-1.65.0}/src/sourcecode/integration_detector.py +31 -0
  8. {sourcecode-1.63.0 → sourcecode-1.65.0}/src/sourcecode/migrate_check.py +334 -58
  9. {sourcecode-1.63.0 → sourcecode-1.65.0}/src/sourcecode/path_filters.py +33 -0
  10. {sourcecode-1.63.0 → sourcecode-1.65.0}/src/sourcecode/repository_ir.py +70 -0
  11. {sourcecode-1.63.0 → sourcecode-1.65.0}/.github/workflows/build-windows.yml +0 -0
  12. {sourcecode-1.63.0 → sourcecode-1.65.0}/.gitignore +0 -0
  13. {sourcecode-1.63.0 → sourcecode-1.65.0}/.ruff.toml +0 -0
  14. {sourcecode-1.63.0 → sourcecode-1.65.0}/CONTRIBUTING.md +0 -0
  15. {sourcecode-1.63.0 → sourcecode-1.65.0}/LICENSE +0 -0
  16. {sourcecode-1.63.0 → sourcecode-1.65.0}/SECURITY.md +0 -0
  17. {sourcecode-1.63.0 → sourcecode-1.65.0}/raw +0 -0
  18. {sourcecode-1.63.0 → sourcecode-1.65.0}/src/sourcecode/adaptive_scanner.py +0 -0
  19. {sourcecode-1.63.0 → sourcecode-1.65.0}/src/sourcecode/architecture_analyzer.py +0 -0
  20. {sourcecode-1.63.0 → sourcecode-1.65.0}/src/sourcecode/architecture_summary.py +0 -0
  21. {sourcecode-1.63.0 → sourcecode-1.65.0}/src/sourcecode/ast_extractor.py +0 -0
  22. {sourcecode-1.63.0 → sourcecode-1.65.0}/src/sourcecode/cache.py +0 -0
  23. {sourcecode-1.63.0 → sourcecode-1.65.0}/src/sourcecode/canonical_ir.py +0 -0
  24. {sourcecode-1.63.0 → sourcecode-1.65.0}/src/sourcecode/cir_graphs.py +0 -0
  25. {sourcecode-1.63.0 → sourcecode-1.65.0}/src/sourcecode/classifier.py +0 -0
  26. {sourcecode-1.63.0 → sourcecode-1.65.0}/src/sourcecode/cli.py +0 -0
  27. {sourcecode-1.63.0 → sourcecode-1.65.0}/src/sourcecode/code_notes_analyzer.py +0 -0
  28. {sourcecode-1.63.0 → sourcecode-1.65.0}/src/sourcecode/confidence_analyzer.py +0 -0
  29. {sourcecode-1.63.0 → sourcecode-1.65.0}/src/sourcecode/context_scorer.py +0 -0
  30. {sourcecode-1.63.0 → sourcecode-1.65.0}/src/sourcecode/context_summarizer.py +0 -0
  31. {sourcecode-1.63.0 → sourcecode-1.65.0}/src/sourcecode/contract_model.py +0 -0
  32. {sourcecode-1.63.0 → sourcecode-1.65.0}/src/sourcecode/contract_pipeline.py +0 -0
  33. {sourcecode-1.63.0 → sourcecode-1.65.0}/src/sourcecode/coverage_parser.py +0 -0
  34. {sourcecode-1.63.0 → sourcecode-1.65.0}/src/sourcecode/dependency_analyzer.py +0 -0
  35. {sourcecode-1.63.0 → sourcecode-1.65.0}/src/sourcecode/detectors/__init__.py +0 -0
  36. {sourcecode-1.63.0 → sourcecode-1.65.0}/src/sourcecode/detectors/base.py +0 -0
  37. {sourcecode-1.63.0 → sourcecode-1.65.0}/src/sourcecode/detectors/csproj_parser.py +0 -0
  38. {sourcecode-1.63.0 → sourcecode-1.65.0}/src/sourcecode/detectors/dart.py +0 -0
  39. {sourcecode-1.63.0 → sourcecode-1.65.0}/src/sourcecode/detectors/dotnet.py +0 -0
  40. {sourcecode-1.63.0 → sourcecode-1.65.0}/src/sourcecode/detectors/elixir.py +0 -0
  41. {sourcecode-1.63.0 → sourcecode-1.65.0}/src/sourcecode/detectors/go.py +0 -0
  42. {sourcecode-1.63.0 → sourcecode-1.65.0}/src/sourcecode/detectors/heuristic.py +0 -0
  43. {sourcecode-1.63.0 → sourcecode-1.65.0}/src/sourcecode/detectors/hybrid.py +0 -0
  44. {sourcecode-1.63.0 → sourcecode-1.65.0}/src/sourcecode/detectors/java.py +0 -0
  45. {sourcecode-1.63.0 → sourcecode-1.65.0}/src/sourcecode/detectors/jvm_ext.py +0 -0
  46. {sourcecode-1.63.0 → sourcecode-1.65.0}/src/sourcecode/detectors/nodejs.py +0 -0
  47. {sourcecode-1.63.0 → sourcecode-1.65.0}/src/sourcecode/detectors/parsers.py +0 -0
  48. {sourcecode-1.63.0 → sourcecode-1.65.0}/src/sourcecode/detectors/php.py +0 -0
  49. {sourcecode-1.63.0 → sourcecode-1.65.0}/src/sourcecode/detectors/project.py +0 -0
  50. {sourcecode-1.63.0 → sourcecode-1.65.0}/src/sourcecode/detectors/python.py +0 -0
  51. {sourcecode-1.63.0 → sourcecode-1.65.0}/src/sourcecode/detectors/ruby.py +0 -0
  52. {sourcecode-1.63.0 → sourcecode-1.65.0}/src/sourcecode/detectors/rust.py +0 -0
  53. {sourcecode-1.63.0 → sourcecode-1.65.0}/src/sourcecode/detectors/systems.py +0 -0
  54. {sourcecode-1.63.0 → sourcecode-1.65.0}/src/sourcecode/detectors/terraform.py +0 -0
  55. {sourcecode-1.63.0 → sourcecode-1.65.0}/src/sourcecode/detectors/tooling.py +0 -0
  56. {sourcecode-1.63.0 → sourcecode-1.65.0}/src/sourcecode/doc_analyzer.py +0 -0
  57. {sourcecode-1.63.0 → sourcecode-1.65.0}/src/sourcecode/entrypoint_classifier.py +0 -0
  58. {sourcecode-1.63.0 → sourcecode-1.65.0}/src/sourcecode/env_analyzer.py +0 -0
  59. {sourcecode-1.63.0 → sourcecode-1.65.0}/src/sourcecode/error_schema.py +0 -0
  60. {sourcecode-1.63.0 → sourcecode-1.65.0}/src/sourcecode/explain.py +0 -0
  61. {sourcecode-1.63.0 → sourcecode-1.65.0}/src/sourcecode/file_chunker.py +0 -0
  62. {sourcecode-1.63.0 → sourcecode-1.65.0}/src/sourcecode/file_classifier.py +0 -0
  63. {sourcecode-1.63.0 → sourcecode-1.65.0}/src/sourcecode/flow_analyzer.py +0 -0
  64. {sourcecode-1.63.0 → sourcecode-1.65.0}/src/sourcecode/format_contract.py +0 -0
  65. {sourcecode-1.63.0 → sourcecode-1.65.0}/src/sourcecode/fqn_utils.py +0 -0
  66. {sourcecode-1.63.0 → sourcecode-1.65.0}/src/sourcecode/git_analyzer.py +0 -0
  67. {sourcecode-1.63.0 → sourcecode-1.65.0}/src/sourcecode/graph_analyzer.py +0 -0
  68. {sourcecode-1.63.0 → sourcecode-1.65.0}/src/sourcecode/license.py +0 -0
  69. {sourcecode-1.63.0 → sourcecode-1.65.0}/src/sourcecode/mcp/__init__.py +0 -0
  70. {sourcecode-1.63.0 → sourcecode-1.65.0}/src/sourcecode/mcp/onboarding/__init__.py +0 -0
  71. {sourcecode-1.63.0 → sourcecode-1.65.0}/src/sourcecode/mcp/onboarding/applier.py +0 -0
  72. {sourcecode-1.63.0 → sourcecode-1.65.0}/src/sourcecode/mcp/onboarding/backup.py +0 -0
  73. {sourcecode-1.63.0 → sourcecode-1.65.0}/src/sourcecode/mcp/onboarding/detector.py +0 -0
  74. {sourcecode-1.63.0 → sourcecode-1.65.0}/src/sourcecode/mcp/onboarding/planner.py +0 -0
  75. {sourcecode-1.63.0 → sourcecode-1.65.0}/src/sourcecode/mcp/orchestrator.py +0 -0
  76. {sourcecode-1.63.0 → sourcecode-1.65.0}/src/sourcecode/mcp/registry.py +0 -0
  77. {sourcecode-1.63.0 → sourcecode-1.65.0}/src/sourcecode/mcp/runner.py +0 -0
  78. {sourcecode-1.63.0 → sourcecode-1.65.0}/src/sourcecode/mcp/server.py +0 -0
  79. {sourcecode-1.63.0 → sourcecode-1.65.0}/src/sourcecode/mcp_nudge.py +0 -0
  80. {sourcecode-1.63.0 → sourcecode-1.65.0}/src/sourcecode/metrics_analyzer.py +0 -0
  81. {sourcecode-1.63.0 → sourcecode-1.65.0}/src/sourcecode/openapi_surface.py +0 -0
  82. {sourcecode-1.63.0 → sourcecode-1.65.0}/src/sourcecode/output_budget.py +0 -0
  83. {sourcecode-1.63.0 → sourcecode-1.65.0}/src/sourcecode/pr_comment_renderer.py +0 -0
  84. {sourcecode-1.63.0 → sourcecode-1.65.0}/src/sourcecode/pr_impact.py +0 -0
  85. {sourcecode-1.63.0 → sourcecode-1.65.0}/src/sourcecode/prepare_context.py +0 -0
  86. {sourcecode-1.63.0 → sourcecode-1.65.0}/src/sourcecode/progress.py +0 -0
  87. {sourcecode-1.63.0 → sourcecode-1.65.0}/src/sourcecode/ranking_engine.py +0 -0
  88. {sourcecode-1.63.0 → sourcecode-1.65.0}/src/sourcecode/redactor.py +0 -0
  89. {sourcecode-1.63.0 → sourcecode-1.65.0}/src/sourcecode/relevance_scorer.py +0 -0
  90. {sourcecode-1.63.0 → sourcecode-1.65.0}/src/sourcecode/rename_refactor.py +0 -0
  91. {sourcecode-1.63.0 → sourcecode-1.65.0}/src/sourcecode/repo_classifier.py +0 -0
  92. {sourcecode-1.63.0 → sourcecode-1.65.0}/src/sourcecode/ris.py +0 -0
  93. {sourcecode-1.63.0 → sourcecode-1.65.0}/src/sourcecode/runtime_classifier.py +0 -0
  94. {sourcecode-1.63.0 → sourcecode-1.65.0}/src/sourcecode/scanner.py +0 -0
  95. {sourcecode-1.63.0 → sourcecode-1.65.0}/src/sourcecode/schema.py +0 -0
  96. {sourcecode-1.63.0 → sourcecode-1.65.0}/src/sourcecode/security_config.py +0 -0
  97. {sourcecode-1.63.0 → sourcecode-1.65.0}/src/sourcecode/semantic_analyzer.py +0 -0
  98. {sourcecode-1.63.0 → sourcecode-1.65.0}/src/sourcecode/serializer.py +0 -0
  99. {sourcecode-1.63.0 → sourcecode-1.65.0}/src/sourcecode/spring_event_topology.py +0 -0
  100. {sourcecode-1.63.0 → sourcecode-1.65.0}/src/sourcecode/spring_findings.py +0 -0
  101. {sourcecode-1.63.0 → sourcecode-1.65.0}/src/sourcecode/spring_impact.py +0 -0
  102. {sourcecode-1.63.0 → sourcecode-1.65.0}/src/sourcecode/spring_model.py +0 -0
  103. {sourcecode-1.63.0 → sourcecode-1.65.0}/src/sourcecode/spring_security_audit.py +0 -0
  104. {sourcecode-1.63.0 → sourcecode-1.65.0}/src/sourcecode/spring_semantic.py +0 -0
  105. {sourcecode-1.63.0 → sourcecode-1.65.0}/src/sourcecode/spring_tx_analyzer.py +0 -0
  106. {sourcecode-1.63.0 → sourcecode-1.65.0}/src/sourcecode/summarizer.py +0 -0
  107. {sourcecode-1.63.0 → sourcecode-1.65.0}/src/sourcecode/telemetry/__init__.py +0 -0
  108. {sourcecode-1.63.0 → sourcecode-1.65.0}/src/sourcecode/telemetry/config.py +0 -0
  109. {sourcecode-1.63.0 → sourcecode-1.65.0}/src/sourcecode/telemetry/consent.py +0 -0
  110. {sourcecode-1.63.0 → sourcecode-1.65.0}/src/sourcecode/telemetry/events.py +0 -0
  111. {sourcecode-1.63.0 → sourcecode-1.65.0}/src/sourcecode/telemetry/filters.py +0 -0
  112. {sourcecode-1.63.0 → sourcecode-1.65.0}/src/sourcecode/telemetry/transport.py +0 -0
  113. {sourcecode-1.63.0 → sourcecode-1.65.0}/src/sourcecode/tree_utils.py +0 -0
  114. {sourcecode-1.63.0 → sourcecode-1.65.0}/src/sourcecode/validation_surface.py +0 -0
  115. {sourcecode-1.63.0 → sourcecode-1.65.0}/src/sourcecode/version_check.py +0 -0
  116. {sourcecode-1.63.0 → sourcecode-1.65.0}/src/sourcecode/workspace.py +0 -0
  117. {sourcecode-1.63.0 → sourcecode-1.65.0}/supabase/functions/README.md +0 -0
  118. {sourcecode-1.63.0 → sourcecode-1.65.0}/supabase/functions/get-license/index.ts +0 -0
  119. {sourcecode-1.63.0 → sourcecode-1.65.0}/supabase/functions/lemonsqueezy-webhook/index.ts +0 -0
  120. {sourcecode-1.63.0 → sourcecode-1.65.0}/supabase/functions/telemetry/index.ts +0 -0
  121. {sourcecode-1.63.0 → sourcecode-1.65.0}/supabase/sql/license_event_ordering.sql +0 -0
  122. {sourcecode-1.63.0 → sourcecode-1.65.0}/supabase/sql/telemetry_events.sql +0 -0
@@ -1,5 +1,110 @@
1
1
  # Changelog
2
2
 
3
+ ## [1.65.0] — 2026-06-30
4
+
5
+ ### Fixed — non-Spring / already-modernized repos no longer fabricate blockers (`migrate-check`)
6
+
7
+ A Pro audit of a real enterprise repo (**Keycloak**, Quarkus 3.33 / Jakarta EE /
8
+ Hibernate ORM 6.2.13, Jakarta migration **complete**, 7,885 Java files / 186
9
+ modules) exposed a cluster of false positives that produced `readiness 0/100`, a
10
+ phantom `hibernate_rewrite` headline, and a `boot3` dimension marked applicable
11
+ with **zero** Spring. A migration verdict shown to a CTO must never contradict its
12
+ own evidence. Keycloak is now a golden regression fixture
13
+ (`tests/test_migrate_check_keycloak_regression.py`).
14
+
15
+ - **Hibernate version is resolved before any 5→6 verdict (BUG #1).** The effective
16
+ Hibernate version is parsed from build descriptors, following Maven
17
+ `${properties}` and BOM-managed `<hibernate*.version>` values plus explicit
18
+ `hibernate-core`/`hibernate-orm` coordinates. Major ≥ 6 → the 5→6 axis is **N/A**
19
+ (migration already done), never a blocker. Unresolved version → low-confidence
20
+ hypothesis, **no** `headline_blocker`. New `hibernate.effective_version`,
21
+ `version_major`, `version_confidence`, `migration_applicable`.
22
+ - **Boot3 dimension auto-disables without Spring (BUG #2).** `boot3.applicable` is
23
+ now a function of real Spring usage (build coordinate or `org.springframework`
24
+ import). Quarkus / Micronaut / Jakarta-pure repos report `boot3` as N/A instead
25
+ of a contradictory `applicable: true`.
26
+ - **Jakarta scorer ignores permanent `javax.*` (BUG #3).** The JDK/JSR allowlist
27
+ (`javax.xml.*`, `javax.crypto.*`, `javax.naming.*`, `javax.sql.*`,
28
+ `javax.management.*`, `javax.security.auth.*`, …) is honored end-to-end, so the
29
+ Keycloak's 1,065 permanent `javax.*` imports stop counting as jakarta debt.
30
+ - **Readiness headline can no longer be a misleading 0 (BUG #4).** Framework
31
+ blockers (jakarta / Boot3 / Security) deduct uncapped; orthogonal JDK debt is
32
+ advisory-capped and best-practice hygiene is excluded — so an already-modernized
33
+ repo reads high (Keycloak 85/100), never 0. The headline cannot contradict its
34
+ own note.
35
+ - **Effort excludes N/A axes (BUG #5).** `estimated_effort_days` is computed over
36
+ product (`main`) findings only; the phantom Hibernate 5→6 effort is gone.
37
+ - **Best-practice hygiene no longer sinks a dimension (BUG #6).**
38
+ `java.util.Date`/`Calendar` (MIG-016, `java_8_best_practice`) is reported as a
39
+ separate `hygiene_findings` metric and excluded from JDK-modernization scoring.
40
+ - **MIG-006 explanation matches the actual symbol (BUG #7).** The explanation now
41
+ names the detected `javax.annotation.*` symbol instead of a fixed
42
+ `@PostConstruct/@PreDestroy/@Resource` blurb. `javax.annotation.Generated` (JSR-250,
43
+ emitted into autogenerated SCIM/JAXB sources) is downgraded to **low** and bucketed
44
+ as `generated`.
45
+ - **Test/fixture findings segregated from `blocking_count` (BUG #8).** Findings in
46
+ test harness modules (`testsuite/`, `test-framework/`, `integration-arquillian/`,
47
+ `*-test*`) and under `src/test/` are tagged `code_context: test`; autogenerated
48
+ sources `generated`. Only `main` counts toward `blocking_count`, readiness, and
49
+ effort. The other buckets surface in `non_blocking{}`. Keycloak's 10 test `web.xml`
50
+ + 14 test-framework `sun.*` no longer inflate the verdict (`blocking_count` 30 → 6).
51
+ - **`export --integrations` is no longer Spring-centric (BUG #9).** Detection now
52
+ covers plain-Java/Jakarta HTTP clients (JDK `HttpClient`, Apache, OkHttp), JNDI
53
+ LDAP, and JavaMail/SMTP in addition to Spring templates, and emits an explicit
54
+ `confidence` (`observed` / `not_analyzed`) + `coverage_note` rather than an
55
+ authoritative `0`. Keycloak: 0 → 144 integrations (80 HTTP / 33 LDAP / 31 SMTP).
56
+
57
+ ## [1.64.0] — 2026-06-30
58
+
59
+ ### Fixed — zero false-positive blockers (`migrate-check` / `endpoints`)
60
+
61
+ A Pro audit of a real enterprise repo (Alfresco Content Services Community, 6,549
62
+ classes) surfaced false blockers that would have invalidated a ~2 person-month
63
+ budget decision. A migration blocker is a high-cost claim: if the tool cannot
64
+ **prove** it from resolved AST/dependency signals, it must not be declared. This
65
+ release enforces that — blockers operate on parsed imports / fully-qualified type
66
+ references, never on a substring inside a comment, Javadoc, string literal, or
67
+ classpath resource path. The `hibernate` sub-`schema_version` is now **2.1**.
68
+
69
+ - **Phantom Hibernate eliminated.** Hibernate detection now requires real evidence:
70
+ an `org.hibernate:*` build dependency, a parsed `import org.hibernate.*`, or a
71
+ parsed `import {jakarta,javax}.persistence.*`. Absent all three →
72
+ `hibernate.detected = false`, no `hibernate_rewrite` headline, no phantom effort.
73
+ All scanning runs on source with comments + string/char literals stripped (line
74
+ numbers preserved), so an `org.hibernate.dialect.*` substring in Javadoc or an
75
+ iBatis resource path can no longer trigger a verdict. Over-generic Criteria tokens
76
+ (`Predicate`, `Root<`, `Criterion`, `Conjunction`, `Disjunction`) were dropped —
77
+ they collide with project-owned domain classes. SPI bare-name matches
78
+ (`implements XInterceptor`, `extends XEventListener`) now require an
79
+ `org.hibernate` import in the same file; FQN-anchored SPI matches still count
80
+ on their own. New `hibernate.evidence{}` records the proof + `confidence`.
81
+ - **MIG-004 / jakarta rules respect a JDK allowlist.** `javax.transaction.xa.*`
82
+ (the Java SE `java.transaction.xa` module), `javax.annotation.processing.*`,
83
+ `javax.sql.*`, `javax.xml.parsers/transform/...`, `javax.management.*`,
84
+ `javax.crypto.*`, and the other permanent JDK/JSR `javax` namespaces no longer
85
+ count as jakarta-migration findings. App-level `javax.transaction.Transactional`,
86
+ `javax.annotation.PostConstruct`, etc. are still flagged (true positives kept).
87
+ Matching is by fully-qualified import prefix, not simple name or partial token.
88
+ - **`readiness_score` no longer sinks on an N/A dimension.** A dimension that does
89
+ not apply (e.g. Hibernate on a repo with no Hibernate) is reported as N/A
90
+ (`score: null`), never as 0. New `applicable_dimensions{}` and `readiness_note`
91
+ make the aggregate's derivation explicit — read the per-dimension breakdown +
92
+ `blocking_count`, not the single number.
93
+ - **`endpoints` never implies "no API".** When the Spring-MVC surface is empty but
94
+ another REST framework is present (Alfresco WebScripts via `*.desc.xml` +
95
+ `AbstractWebScript`/`DeclarativeWebScript`, JAX-RS, or mapped Servlets),
96
+ `security_model` becomes `"undetermined"` (not `"unknown"`), a
97
+ `non_spring_rest_surface{}` block is emitted, and a warning states the surface is
98
+ unmodeled — so `total: 0` is never read as "this app exposes no endpoints".
99
+
100
+ ### Tests
101
+
102
+ - New `tests/test_falsepositive_fixes.py` — positive **and** negative fixtures per
103
+ bug (phantom comment-only repo, project-owned `Dialect`/`Criteria`/`Interceptor`
104
+ classes, `javax.transaction.xa`, WebScripts) alongside the true positives that
105
+ must be preserved (real Hibernate, `javax.transaction.Transactional`,
106
+ `@RestController`). Full suite: 2827 passed.
107
+
3
108
  ## [1.63.0] — 2026-06-29
4
109
 
5
110
  ### Added — actionable Hibernate rewrite targets (`migrate-check`)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: sourcecode
3
- Version: 1.63.0
3
+ Version: 1.65.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
@@ -409,7 +411,7 @@ Emits **structured, tool-agnostic** codebase views as plain JSON/YAML — the ki
409
411
  |------|--------|
410
412
  | `--by-directory` | One group per source directory, each symbol with a `source_file:line` reference. |
411
413
  | `--module-graph` | `{nodes, edges, summary}` — directories as modules, inter-module dependencies rolled up from class-level relation edges with hit counts + edge types. |
412
- | `--integrations` | Outbound integrations (`RestTemplate`, `WebClient`, `@FeignClient`, `LdapTemplate`, `JmsTemplate`, ActiveMQ) with `file:line` evidence and a literal `target` URL/name when present. |
414
+ | `--integrations` | Outbound integrations across Spring **and** plain-Java/Jakarta stacks: HTTP (`RestTemplate`, `WebClient`, `@FeignClient`, JDK `HttpClient`, Apache, OkHttp), LDAP (`LdapTemplate`, JNDI `InitialDirContext`/`LdapContext`), SMTP (`JavaMailSender`, JavaMail `Transport`/`MimeMessage`), and JMS — with `file:line` evidence and a literal `target` when present. Emits an explicit `confidence` (`observed` / `not_analyzed`) + `coverage_note`: a count of `0` means "no client construct found", **not** "no integrations" (runtime/DI-wired clients are not statically visible). |
413
415
  | `--c4` | Unified document: `c4.{context, containers, components, code}` + `api_surface` + a `manifest` with per-directory content hashes for **incremental** consumers (skip directories whose hash is unchanged). `components.module_roots` rolls leaf source dirs up to architectural module roots and classifies each `layered` (DDD: ≥2 of `domain`/`application`/`infrastructure`) vs `flat` (legacy/flat package), with a verifiable `module_count` — so a consumer enumerates real modules instead of inferring boundaries from leaf directories. |
414
416
 
415
417
  The section flags compose (pass several for one multi-section document); `--c4` assembles the full export on its own. URLs assembled at runtime yield `target: null` (honest absence, never a guess); containers are derived from build files (Maven/Gradle) and reported as a limitation when none are found.
@@ -608,7 +610,7 @@ Detects migration blockers across Java source files, Spring XML config files, an
608
610
  | `MIG-002` | high | `javax.servlet` import — Servlet API changed |
609
611
  | `MIG-003` | high | `javax.validation` import — Bean Validation changed |
610
612
  | `MIG-004` | high | `javax.transaction` import — TX API changed |
611
- | `MIG-006` | medium | `javax.annotation` import — CDI annotations changed |
613
+ | `MIG-006` | medium¹ | `javax.annotation` import — CDI annotations changed (¹`javax.annotation.Generated` in autogenerated code → **low**, bucketed `generated`; explanation names the actual symbol) |
612
614
  | `MIG-007` | medium | `javax.inject` import — DI annotations changed |
613
615
  | `MIG-008` | medium | `javax.ws.rs` import — JAX-RS changed |
614
616
  | `MIG-009` | medium | `javax.jms` import — JMS API changed |
@@ -663,7 +665,17 @@ A Hibernate major upgrade is **not** a single dependency bump for systems that u
663
665
  dynamic persistence. `migrate-check` stratifies Hibernate exposure into four
664
666
  independent migration domains — never one aggregated score — and emits **actionable,
665
667
  machine-readable rewrite targets** so a migration agent can consume the output
666
- directly instead of re-parsing the repo. Sub-`schema_version`: `2.0`.
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`.
667
679
 
668
680
  **Four layers** (each on its own risk axis):
669
681
 
@@ -704,9 +716,45 @@ Hibernate is an orthogonal rewrite axis, so it does not sink the headline
704
716
  `readiness_score`; instead, in a rewrite zone the top-level `headline_blocker` is set
705
717
  to `"hibernate_rewrite"` so a reader of the headline score is not misled.
706
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
+ #### Reliability guarantees (no version, no verdict)
726
+
727
+ A migration verdict shown to a decision-maker must never contradict its own
728
+ evidence. `migrate-check` enforces:
729
+
730
+ - **Version-gated framework axes.** The Hibernate 5→6 axis applies only when the
731
+ effective Hibernate version (resolved from `pom.xml`/Gradle, following Maven
732
+ `${properties}` and BOM-managed `<hibernate*.version>`) is `< 6`. A resolved
733
+ Hibernate **6+** repo is reported `migration_applicable: false` (N/A) — no
734
+ `hibernate_rewrite` headline. An **unresolved** version degrades to a
735
+ low-confidence hypothesis with no headline blocker. See
736
+ `hibernate.effective_version` / `version_major` / `version_confidence`.
737
+ - **Boot3 auto-disables without Spring.** `boot3.applicable` tracks real Spring
738
+ usage; Quarkus / Micronaut / Helidon / Jakarta-pure repos report `boot3` as N/A
739
+ (`spring_present: false`), not a contradictory `applicable: true`.
740
+ - **Permanent `javax.*` are never jakarta debt.** JDK/JSR namespaces
741
+ (`javax.xml.*`, `javax.crypto.*`, `javax.naming.*`, `javax.sql.*`,
742
+ `javax.management.*`, `javax.security.auth.*`, …) are allowlisted across every
743
+ jakarta scorer.
744
+ - **Three buckets: blocker ≠ hygiene ≠ test.** Only product (`main`) code counts
745
+ toward `blocking_count`, readiness, and effort. Test harnesses
746
+ (`testsuite/`, `test-framework/`, `integration-arquillian/`, `*-test*`,
747
+ `src/test/`) and autogenerated sources are tagged `code_context` and surfaced in
748
+ `non_blocking{}`. Best-practice hygiene (`java.util.Date`) is reported as
749
+ `hygiene_findings` and never sinks a dimension. Each finding carries
750
+ `code_context: main | test | generated`.
751
+
707
752
  ```bash
708
753
  # inspect only the Hibernate rewrite targets
709
754
  sourcecode migrate-check . --format json | jq '.hibernate.rewrite_targets[]'
755
+
756
+ # product blockers only (excludes test/fixtures + hygiene)
757
+ sourcecode migrate-check . --format json | jq '.blocking_count, .non_blocking, .hygiene_findings'
710
758
  ```
711
759
 
712
760
  ### `rename-class` — Java class rename
@@ -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
@@ -371,7 +373,7 @@ Emits **structured, tool-agnostic** codebase views as plain JSON/YAML — the ki
371
373
  |------|--------|
372
374
  | `--by-directory` | One group per source directory, each symbol with a `source_file:line` reference. |
373
375
  | `--module-graph` | `{nodes, edges, summary}` — directories as modules, inter-module dependencies rolled up from class-level relation edges with hit counts + edge types. |
374
- | `--integrations` | Outbound integrations (`RestTemplate`, `WebClient`, `@FeignClient`, `LdapTemplate`, `JmsTemplate`, ActiveMQ) with `file:line` evidence and a literal `target` URL/name when present. |
376
+ | `--integrations` | Outbound integrations across Spring **and** plain-Java/Jakarta stacks: HTTP (`RestTemplate`, `WebClient`, `@FeignClient`, JDK `HttpClient`, Apache, OkHttp), LDAP (`LdapTemplate`, JNDI `InitialDirContext`/`LdapContext`), SMTP (`JavaMailSender`, JavaMail `Transport`/`MimeMessage`), and JMS — with `file:line` evidence and a literal `target` when present. Emits an explicit `confidence` (`observed` / `not_analyzed`) + `coverage_note`: a count of `0` means "no client construct found", **not** "no integrations" (runtime/DI-wired clients are not statically visible). |
375
377
  | `--c4` | Unified document: `c4.{context, containers, components, code}` + `api_surface` + a `manifest` with per-directory content hashes for **incremental** consumers (skip directories whose hash is unchanged). `components.module_roots` rolls leaf source dirs up to architectural module roots and classifies each `layered` (DDD: ≥2 of `domain`/`application`/`infrastructure`) vs `flat` (legacy/flat package), with a verifiable `module_count` — so a consumer enumerates real modules instead of inferring boundaries from leaf directories. |
376
378
 
377
379
  The section flags compose (pass several for one multi-section document); `--c4` assembles the full export on its own. URLs assembled at runtime yield `target: null` (honest absence, never a guess); containers are derived from build files (Maven/Gradle) and reported as a limitation when none are found.
@@ -570,7 +572,7 @@ Detects migration blockers across Java source files, Spring XML config files, an
570
572
  | `MIG-002` | high | `javax.servlet` import — Servlet API changed |
571
573
  | `MIG-003` | high | `javax.validation` import — Bean Validation changed |
572
574
  | `MIG-004` | high | `javax.transaction` import — TX API changed |
573
- | `MIG-006` | medium | `javax.annotation` import — CDI annotations changed |
575
+ | `MIG-006` | medium¹ | `javax.annotation` import — CDI annotations changed (¹`javax.annotation.Generated` in autogenerated code → **low**, bucketed `generated`; explanation names the actual symbol) |
574
576
  | `MIG-007` | medium | `javax.inject` import — DI annotations changed |
575
577
  | `MIG-008` | medium | `javax.ws.rs` import — JAX-RS changed |
576
578
  | `MIG-009` | medium | `javax.jms` import — JMS API changed |
@@ -625,7 +627,17 @@ A Hibernate major upgrade is **not** a single dependency bump for systems that u
625
627
  dynamic persistence. `migrate-check` stratifies Hibernate exposure into four
626
628
  independent migration domains — never one aggregated score — and emits **actionable,
627
629
  machine-readable rewrite targets** so a migration agent can consume the output
628
- directly instead of re-parsing the repo. Sub-`schema_version`: `2.0`.
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`.
629
641
 
630
642
  **Four layers** (each on its own risk axis):
631
643
 
@@ -666,9 +678,45 @@ Hibernate is an orthogonal rewrite axis, so it does not sink the headline
666
678
  `readiness_score`; instead, in a rewrite zone the top-level `headline_blocker` is set
667
679
  to `"hibernate_rewrite"` so a reader of the headline score is not misled.
668
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
+ #### Reliability guarantees (no version, no verdict)
688
+
689
+ A migration verdict shown to a decision-maker must never contradict its own
690
+ evidence. `migrate-check` enforces:
691
+
692
+ - **Version-gated framework axes.** The Hibernate 5→6 axis applies only when the
693
+ effective Hibernate version (resolved from `pom.xml`/Gradle, following Maven
694
+ `${properties}` and BOM-managed `<hibernate*.version>`) is `< 6`. A resolved
695
+ Hibernate **6+** repo is reported `migration_applicable: false` (N/A) — no
696
+ `hibernate_rewrite` headline. An **unresolved** version degrades to a
697
+ low-confidence hypothesis with no headline blocker. See
698
+ `hibernate.effective_version` / `version_major` / `version_confidence`.
699
+ - **Boot3 auto-disables without Spring.** `boot3.applicable` tracks real Spring
700
+ usage; Quarkus / Micronaut / Helidon / Jakarta-pure repos report `boot3` as N/A
701
+ (`spring_present: false`), not a contradictory `applicable: true`.
702
+ - **Permanent `javax.*` are never jakarta debt.** JDK/JSR namespaces
703
+ (`javax.xml.*`, `javax.crypto.*`, `javax.naming.*`, `javax.sql.*`,
704
+ `javax.management.*`, `javax.security.auth.*`, …) are allowlisted across every
705
+ jakarta scorer.
706
+ - **Three buckets: blocker ≠ hygiene ≠ test.** Only product (`main`) code counts
707
+ toward `blocking_count`, readiness, and effort. Test harnesses
708
+ (`testsuite/`, `test-framework/`, `integration-arquillian/`, `*-test*`,
709
+ `src/test/`) and autogenerated sources are tagged `code_context` and surfaced in
710
+ `non_blocking{}`. Best-practice hygiene (`java.util.Date`) is reported as
711
+ `hygiene_findings` and never sinks a dimension. Each finding carries
712
+ `code_context: main | test | generated`.
713
+
669
714
  ```bash
670
715
  # inspect only the Hibernate rewrite targets
671
716
  sourcecode migrate-check . --format json | jq '.hibernate.rewrite_targets[]'
717
+
718
+ # product blockers only (excludes test/fixtures + hygiene)
719
+ sourcecode migrate-check . --format json | jq '.blocking_count, .non_blocking, .hygiene_findings'
672
720
  ```
673
721
 
674
722
  ### `rename-class` — Java class rename
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "sourcecode"
7
- version = "1.63.0"
7
+ version = "1.65.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.63.0"
3
+ __version__ = "1.65.0"