conexus 6.3.1__tar.gz → 6.3.2__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 (556) hide show
  1. {conexus-6.3.1 → conexus-6.3.2}/PKG-INFO +1 -1
  2. {conexus-6.3.1 → conexus-6.3.2}/docs/rdr/README.md +2 -0
  3. {conexus-6.3.1 → conexus-6.3.2}/mcpb/pyproject.toml +2 -2
  4. {conexus-6.3.1 → conexus-6.3.2}/pyproject.toml +1 -1
  5. {conexus-6.3.1 → conexus-6.3.2}/service/src/main/java/dev/nexus/service/db/CatalogRepository.java +222 -9
  6. {conexus-6.3.1 → conexus-6.3.2}/service/src/main/java/dev/nexus/service/db/ChashRepository.java +22 -2
  7. conexus-6.3.2/service/src/main/java/dev/nexus/service/db/DeadlockRetry.java +107 -0
  8. {conexus-6.3.1 → conexus-6.3.2}/service/src/main/java/dev/nexus/service/db/TaxonomyRepository.java +156 -67
  9. {conexus-6.3.1 → conexus-6.3.2}/service/src/main/java/dev/nexus/service/http/CatalogHandler.java +70 -0
  10. {conexus-6.3.1 → conexus-6.3.2}/service/src/main/java/dev/nexus/service/http/TaxonomyHandler.java +44 -0
  11. {conexus-6.3.1 → conexus-6.3.2}/service/src/main/java/dev/nexus/service/http/VectorHandler.java +32 -4
  12. {conexus-6.3.1 → conexus-6.3.2}/service/src/main/java/dev/nexus/service/vectors/PgVectorRepository.java +516 -47
  13. {conexus-6.3.1 → conexus-6.3.2}/service/src/test/java/dev/nexus/service/CatalogRepositoryTest.java +224 -0
  14. {conexus-6.3.1 → conexus-6.3.2}/service/src/test/java/dev/nexus/service/ChashRepositoryTest.java +20 -0
  15. conexus-6.3.2/service/src/test/java/dev/nexus/service/PgVectorEmbedSkipGcRaceTest.java +344 -0
  16. {conexus-6.3.1 → conexus-6.3.2}/service/src/test/java/dev/nexus/service/PgVectorRepositoryContractTest.java +20 -0
  17. conexus-6.3.2/service/src/test/java/dev/nexus/service/PgVectorUpsertDeadlockTest.java +202 -0
  18. {conexus-6.3.1 → conexus-6.3.2}/service/src/test/java/dev/nexus/service/TaxonomyRepositoryTest.java +64 -1
  19. conexus-6.3.2/service/src/test/java/dev/nexus/service/db/DeadlockRetryTest.java +83 -0
  20. conexus-6.3.2/service/src/test/java/dev/nexus/service/vectors/PgVectorEmbedSkipIntegrationTest.java +673 -0
  21. conexus-6.3.2/service/src/test/java/dev/nexus/service/vectors/PgVectorEmbedSkipTest.java +131 -0
  22. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/catalog/catalog.py +16 -0
  23. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/catalog/catalog_protocol.py +3 -0
  24. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/catalog/http_catalog_client.py +120 -12
  25. conexus-6.3.2/src/nexus/chunk_batcher.py +364 -0
  26. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/code_indexer.py +25 -0
  27. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/commands/index.py +108 -13
  28. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/commands/service_cmd.py +92 -0
  29. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/daemon/binary_install.py +1 -1
  30. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/daemon/catalog_write_shim.py +12 -0
  31. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/daemon/t2_client.py +2 -2
  32. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/db/http_vector_client.py +179 -45
  33. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/db/t2/http_chash_index.py +9 -1
  34. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/db/t2/http_taxonomy_store.py +22 -3
  35. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/db/t3.py +16 -1
  36. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/doc_indexer.py +28 -3
  37. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/hook_registry.py +13 -0
  38. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/index_context.py +9 -0
  39. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/indexer.py +427 -63
  40. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/indexer_utils.py +45 -5
  41. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/mcp/core.py +30 -6
  42. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/mcp_infra.py +99 -12
  43. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/prose_indexer.py +23 -0
  44. {conexus-6.3.1 → conexus-6.3.2}/.beads/README.md +0 -0
  45. {conexus-6.3.1 → conexus-6.3.2}/.gitignore +0 -0
  46. {conexus-6.3.1 → conexus-6.3.2}/LICENSE +0 -0
  47. {conexus-6.3.1 → conexus-6.3.2}/README.md +0 -0
  48. {conexus-6.3.1 → conexus-6.3.2}/conexus/README.md +0 -0
  49. {conexus-6.3.1 → conexus-6.3.2}/conexus/agents/_shared/README.md +0 -0
  50. {conexus-6.3.1 → conexus-6.3.2}/conexus/daemon/com.nexus.service.plist +0 -0
  51. {conexus-6.3.1 → conexus-6.3.2}/conexus/daemon/com.nexus.t2.plist +0 -0
  52. {conexus-6.3.1 → conexus-6.3.2}/conexus/daemon/com.nexus.t3.plist +0 -0
  53. {conexus-6.3.1 → conexus-6.3.2}/conexus/daemon/nexus-service.service +0 -0
  54. {conexus-6.3.1 → conexus-6.3.2}/conexus/daemon/nexus-t2.service +0 -0
  55. {conexus-6.3.1 → conexus-6.3.2}/conexus/daemon/nexus-t3.service +0 -0
  56. {conexus-6.3.1 → conexus-6.3.2}/conexus/hooks/scripts/routing/README.md +0 -0
  57. {conexus-6.3.1 → conexus-6.3.2}/conexus/plans/builtin/abstract-themes.yml +0 -0
  58. {conexus-6.3.1 → conexus-6.3.2}/conexus/plans/builtin/analyze-default.yml +0 -0
  59. {conexus-6.3.1 → conexus-6.3.2}/conexus/plans/builtin/citation-traversal.yml +0 -0
  60. {conexus-6.3.1 → conexus-6.3.2}/conexus/plans/builtin/debug-default.yml +0 -0
  61. {conexus-6.3.1 → conexus-6.3.2}/conexus/plans/builtin/document-default.yml +0 -0
  62. {conexus-6.3.1 → conexus-6.3.2}/conexus/plans/builtin/find-by-author.yml +0 -0
  63. {conexus-6.3.1 → conexus-6.3.2}/conexus/plans/builtin/hybrid-factual-lookup.yml +0 -0
  64. {conexus-6.3.1 → conexus-6.3.2}/conexus/plans/builtin/plan-author-default.yml +0 -0
  65. {conexus-6.3.1 → conexus-6.3.2}/conexus/plans/builtin/plan-inspect-default.yml +0 -0
  66. {conexus-6.3.1 → conexus-6.3.2}/conexus/plans/builtin/plan-inspect-dimensions.yml +0 -0
  67. {conexus-6.3.1 → conexus-6.3.2}/conexus/plans/builtin/plan-promote-propose.yml +0 -0
  68. {conexus-6.3.1 → conexus-6.3.2}/conexus/plans/builtin/research-default.yml +0 -0
  69. {conexus-6.3.1 → conexus-6.3.2}/conexus/plans/builtin/review-default.yml +0 -0
  70. {conexus-6.3.1 → conexus-6.3.2}/conexus/plans/builtin/traverse-then-generate.yml +0 -0
  71. {conexus-6.3.1 → conexus-6.3.2}/conexus/plans/builtin/type-scoped-search.yml +0 -0
  72. {conexus-6.3.1 → conexus-6.3.2}/conexus/plans/dimensions.yml +0 -0
  73. {conexus-6.3.1 → conexus-6.3.2}/conexus/plans/purposes.yml +0 -0
  74. {conexus-6.3.1 → conexus-6.3.2}/data/calibration/rdr-109/README.md +0 -0
  75. {conexus-6.3.1 → conexus-6.3.2}/docs/README.md +0 -0
  76. {conexus-6.3.1 → conexus-6.3.2}/docs/migration/README.md +0 -0
  77. {conexus-6.3.1 → conexus-6.3.2}/dt/scripts/Index Current Group in nx.applescript +0 -0
  78. {conexus-6.3.1 → conexus-6.3.2}/dt/scripts/Index Selection in nx (Knowledge).applescript +0 -0
  79. {conexus-6.3.1 → conexus-6.3.2}/dt/scripts/Index Selection in nx.applescript +0 -0
  80. {conexus-6.3.1 → conexus-6.3.2}/mcpb/src/server.py +0 -0
  81. {conexus-6.3.1 → conexus-6.3.2}/scripts/cron/README.md +0 -0
  82. {conexus-6.3.1 → conexus-6.3.2}/scripts/launchd/README.md +0 -0
  83. {conexus-6.3.1 → conexus-6.3.2}/scripts/rdr152-sandbox/README.md +0 -0
  84. {conexus-6.3.1 → conexus-6.3.2}/scripts/spikes/s04-build/src/main/java/dev/nexus/spike/s04/Main.java +0 -0
  85. {conexus-6.3.1 → conexus-6.3.2}/scripts/spikes/s04-build/src/main/resources/META-INF/native-image/reachability-metadata.json +0 -0
  86. {conexus-6.3.1 → conexus-6.3.2}/scripts/spikes/s04-build/src/main/resources/db/changelog/db.changelog-master.xml +0 -0
  87. {conexus-6.3.1 → conexus-6.3.2}/scripts/spikes/s04-build/src/main/resources/logback.xml +0 -0
  88. {conexus-6.3.1 → conexus-6.3.2}/service/README.md +0 -0
  89. {conexus-6.3.1 → conexus-6.3.2}/service/src/main/java/dev/nexus/service/Main.java +0 -0
  90. {conexus-6.3.1 → conexus-6.3.2}/service/src/main/java/dev/nexus/service/NexusService.java +0 -0
  91. {conexus-6.3.1 → conexus-6.3.2}/service/src/main/java/dev/nexus/service/db/AspectRepository.java +0 -0
  92. {conexus-6.3.1 → conexus-6.3.2}/service/src/main/java/dev/nexus/service/db/CollectionRegistry.java +0 -0
  93. {conexus-6.3.1 → conexus-6.3.2}/service/src/main/java/dev/nexus/service/db/MemoryRepository.java +0 -0
  94. {conexus-6.3.1 → conexus-6.3.2}/service/src/main/java/dev/nexus/service/db/MigrationJobRepository.java +0 -0
  95. {conexus-6.3.1 → conexus-6.3.2}/service/src/main/java/dev/nexus/service/db/PgSession.java +0 -0
  96. {conexus-6.3.1 → conexus-6.3.2}/service/src/main/java/dev/nexus/service/db/PlanRepository.java +0 -0
  97. {conexus-6.3.1 → conexus-6.3.2}/service/src/main/java/dev/nexus/service/db/PoolerModeCheck.java +0 -0
  98. {conexus-6.3.1 → conexus-6.3.2}/service/src/main/java/dev/nexus/service/db/SchemaMigrator.java +0 -0
  99. {conexus-6.3.1 → conexus-6.3.2}/service/src/main/java/dev/nexus/service/db/ScratchRepository.java +0 -0
  100. {conexus-6.3.1 → conexus-6.3.2}/service/src/main/java/dev/nexus/service/db/SessionPrincipal.java +0 -0
  101. {conexus-6.3.1 → conexus-6.3.2}/service/src/main/java/dev/nexus/service/db/TelemetryRepository.java +0 -0
  102. {conexus-6.3.1 → conexus-6.3.2}/service/src/main/java/dev/nexus/service/db/TenantConstants.java +0 -0
  103. {conexus-6.3.1 → conexus-6.3.2}/service/src/main/java/dev/nexus/service/db/TenantScope.java +0 -0
  104. {conexus-6.3.1 → conexus-6.3.2}/service/src/main/java/dev/nexus/service/db/TokenCache.java +0 -0
  105. {conexus-6.3.1 → conexus-6.3.2}/service/src/main/java/dev/nexus/service/db/TokenHashing.java +0 -0
  106. {conexus-6.3.1 → conexus-6.3.2}/service/src/main/java/dev/nexus/service/db/TokenStore.java +0 -0
  107. {conexus-6.3.1 → conexus-6.3.2}/service/src/main/java/dev/nexus/service/http/AspectHandler.java +0 -0
  108. {conexus-6.3.1 → conexus-6.3.2}/service/src/main/java/dev/nexus/service/http/AuthFilter.java +0 -0
  109. {conexus-6.3.1 → conexus-6.3.2}/service/src/main/java/dev/nexus/service/http/ChashHandler.java +0 -0
  110. {conexus-6.3.1 → conexus-6.3.2}/service/src/main/java/dev/nexus/service/http/HealthHandler.java +0 -0
  111. {conexus-6.3.1 → conexus-6.3.2}/service/src/main/java/dev/nexus/service/http/HttpUtil.java +0 -0
  112. {conexus-6.3.1 → conexus-6.3.2}/service/src/main/java/dev/nexus/service/http/MemoryHandler.java +0 -0
  113. {conexus-6.3.1 → conexus-6.3.2}/service/src/main/java/dev/nexus/service/http/MigrationHandler.java +0 -0
  114. {conexus-6.3.1 → conexus-6.3.2}/service/src/main/java/dev/nexus/service/http/PlanHandler.java +0 -0
  115. {conexus-6.3.1 → conexus-6.3.2}/service/src/main/java/dev/nexus/service/http/RequestContext.java +0 -0
  116. {conexus-6.3.1 → conexus-6.3.2}/service/src/main/java/dev/nexus/service/http/ScratchHandler.java +0 -0
  117. {conexus-6.3.1 → conexus-6.3.2}/service/src/main/java/dev/nexus/service/http/SessionTokenHandler.java +0 -0
  118. {conexus-6.3.1 → conexus-6.3.2}/service/src/main/java/dev/nexus/service/http/TelemetryHandler.java +0 -0
  119. {conexus-6.3.1 → conexus-6.3.2}/service/src/main/java/dev/nexus/service/http/TokenAdminHandler.java +0 -0
  120. {conexus-6.3.1 → conexus-6.3.2}/service/src/main/java/dev/nexus/service/http/VersionHandler.java +0 -0
  121. {conexus-6.3.1 → conexus-6.3.2}/service/src/main/java/dev/nexus/service/http/WhoamiHandler.java +0 -0
  122. {conexus-6.3.1 → conexus-6.3.2}/service/src/main/java/dev/nexus/service/jooq/binding/Vector.java +0 -0
  123. {conexus-6.3.1 → conexus-6.3.2}/service/src/main/java/dev/nexus/service/jooq/binding/VectorBinding.java +0 -0
  124. {conexus-6.3.1 → conexus-6.3.2}/service/src/main/java/dev/nexus/service/nativeimage/JooqRecordReflectionFeature.java +0 -0
  125. {conexus-6.3.1 → conexus-6.3.2}/service/src/main/java/dev/nexus/service/resolver/ChromaSchemeHandler.java +0 -0
  126. {conexus-6.3.1 → conexus-6.3.2}/service/src/main/java/dev/nexus/service/resolver/ChunkTextFetcher.java +0 -0
  127. {conexus-6.3.1 → conexus-6.3.2}/service/src/main/java/dev/nexus/service/resolver/HttpsSchemeHandler.java +0 -0
  128. {conexus-6.3.1 → conexus-6.3.2}/service/src/main/java/dev/nexus/service/resolver/ResolveResult.java +0 -0
  129. {conexus-6.3.1 → conexus-6.3.2}/service/src/main/java/dev/nexus/service/resolver/UnknownSchemeException.java +0 -0
  130. {conexus-6.3.1 → conexus-6.3.2}/service/src/main/java/dev/nexus/service/resolver/UriSchemeHandler.java +0 -0
  131. {conexus-6.3.1 → conexus-6.3.2}/service/src/main/java/dev/nexus/service/resolver/UriSchemeResolverRegistry.java +0 -0
  132. {conexus-6.3.1 → conexus-6.3.2}/service/src/main/java/dev/nexus/service/vectors/Bge768Embedder.java +0 -0
  133. {conexus-6.3.1 → conexus-6.3.2}/service/src/main/java/dev/nexus/service/vectors/CceEmbedder.java +0 -0
  134. {conexus-6.3.1 → conexus-6.3.2}/service/src/main/java/dev/nexus/service/vectors/ChromaQuotaValidator.java +0 -0
  135. {conexus-6.3.1 → conexus-6.3.2}/service/src/main/java/dev/nexus/service/vectors/ChromaRestClient.java +0 -0
  136. {conexus-6.3.1 → conexus-6.3.2}/service/src/main/java/dev/nexus/service/vectors/DimTables.java +0 -0
  137. {conexus-6.3.1 → conexus-6.3.2}/service/src/main/java/dev/nexus/service/vectors/EgressProxy.java +0 -0
  138. {conexus-6.3.1 → conexus-6.3.2}/service/src/main/java/dev/nexus/service/vectors/EmbedResult.java +0 -0
  139. {conexus-6.3.1 → conexus-6.3.2}/service/src/main/java/dev/nexus/service/vectors/Embedder.java +0 -0
  140. {conexus-6.3.1 → conexus-6.3.2}/service/src/main/java/dev/nexus/service/vectors/EmbedderRouter.java +0 -0
  141. {conexus-6.3.1 → conexus-6.3.2}/service/src/main/java/dev/nexus/service/vectors/EmbeddingModelUnavailableException.java +0 -0
  142. {conexus-6.3.1 → conexus-6.3.2}/service/src/main/java/dev/nexus/service/vectors/LocalChromaServer.java +0 -0
  143. {conexus-6.3.1 → conexus-6.3.2}/service/src/main/java/dev/nexus/service/vectors/OnnxEmbedder.java +0 -0
  144. {conexus-6.3.1 → conexus-6.3.2}/service/src/main/java/dev/nexus/service/vectors/TaxonomyCentroidRepository.java +0 -0
  145. {conexus-6.3.1 → conexus-6.3.2}/service/src/main/java/dev/nexus/service/vectors/VectorRepository.java +0 -0
  146. {conexus-6.3.1 → conexus-6.3.2}/service/src/main/java/dev/nexus/service/vectors/VoyageEmbedder.java +0 -0
  147. {conexus-6.3.1 → conexus-6.3.2}/service/src/main/resources/META-INF/native-image/native-image.properties +0 -0
  148. {conexus-6.3.1 → conexus-6.3.2}/service/src/main/resources/META-INF/native-image/reflect-config.json +0 -0
  149. {conexus-6.3.1 → conexus-6.3.2}/service/src/main/resources/META-INF/native-image/resource-config.json +0 -0
  150. {conexus-6.3.1 → conexus-6.3.2}/service/src/main/resources/META-INF/native-image/traced/reachability-metadata.json +0 -0
  151. {conexus-6.3.1 → conexus-6.3.2}/service/src/main/resources/META-INF/nexus/release.properties +0 -0
  152. {conexus-6.3.1 → conexus-6.3.2}/service/src/main/resources/db/changelog/aspects-001-baseline.xml +0 -0
  153. {conexus-6.3.1 → conexus-6.3.2}/service/src/main/resources/db/changelog/aspects-002-next-retry-at.xml +0 -0
  154. {conexus-6.3.1 → conexus-6.3.2}/service/src/main/resources/db/changelog/catalog-001-baseline.xml +0 -0
  155. {conexus-6.3.1 → conexus-6.3.2}/service/src/main/resources/db/changelog/catalog-002-hygiene.xml +0 -0
  156. {conexus-6.3.1 → conexus-6.3.2}/service/src/main/resources/db/changelog/catalog-003-soft-delete.xml +0 -0
  157. {conexus-6.3.1 → conexus-6.3.2}/service/src/main/resources/db/changelog/catalog-004-manifest-functions.xml +0 -0
  158. {conexus-6.3.1 → conexus-6.3.2}/service/src/main/resources/db/changelog/catalog-005-collection-vector-stats.xml +0 -0
  159. {conexus-6.3.1 → conexus-6.3.2}/service/src/main/resources/db/changelog/catalog-006-combined-query-functions.xml +0 -0
  160. {conexus-6.3.1 → conexus-6.3.2}/service/src/main/resources/db/changelog/catalog-007-graph-hop-functions.xml +0 -0
  161. {conexus-6.3.1 → conexus-6.3.2}/service/src/main/resources/db/changelog/catalog-008-combined-query-extensions.xml +0 -0
  162. {conexus-6.3.1 → conexus-6.3.2}/service/src/main/resources/db/changelog/catalog-009-read-shape-views.xml +0 -0
  163. {conexus-6.3.1 → conexus-6.3.2}/service/src/main/resources/db/changelog/catalog-011-collection-health-stale-age.xml +0 -0
  164. {conexus-6.3.1 → conexus-6.3.2}/service/src/main/resources/db/changelog/chash-001-baseline.xml +0 -0
  165. {conexus-6.3.1 → conexus-6.3.2}/service/src/main/resources/db/changelog/db.changelog-master.xml +0 -0
  166. {conexus-6.3.1 → conexus-6.3.2}/service/src/main/resources/db/changelog/fk-001-catalog-cross-store.xml +0 -0
  167. {conexus-6.3.1 → conexus-6.3.2}/service/src/main/resources/db/changelog/fk-002-collection-registry.xml +0 -0
  168. {conexus-6.3.1 → conexus-6.3.2}/service/src/main/resources/db/changelog/fk-002-validate.xml +0 -0
  169. {conexus-6.3.1 → conexus-6.3.2}/service/src/main/resources/db/changelog/fk-003-collection-registry-extra.xml +0 -0
  170. {conexus-6.3.1 → conexus-6.3.2}/service/src/main/resources/db/changelog/fk-003-validate.xml +0 -0
  171. {conexus-6.3.1 → conexus-6.3.2}/service/src/main/resources/db/changelog/grants-nexus-svc.xml +0 -0
  172. {conexus-6.3.1 → conexus-6.3.2}/service/src/main/resources/db/changelog/memory-001-baseline.xml +0 -0
  173. {conexus-6.3.1 → conexus-6.3.2}/service/src/main/resources/db/changelog/migration-001-baseline.xml +0 -0
  174. {conexus-6.3.1 → conexus-6.3.2}/service/src/main/resources/db/changelog/perf-001-rename-collection-indexes.xml +0 -0
  175. {conexus-6.3.1 → conexus-6.3.2}/service/src/main/resources/db/changelog/plans-001-baseline.xml +0 -0
  176. {conexus-6.3.1 → conexus-6.3.2}/service/src/main/resources/db/changelog/role-001-nexus-svc.xml +0 -0
  177. {conexus-6.3.1 → conexus-6.3.2}/service/src/main/resources/db/changelog/service-tokens-001-baseline.xml +0 -0
  178. {conexus-6.3.1 → conexus-6.3.2}/service/src/main/resources/db/changelog/service-tokens-002-single-root-index.xml +0 -0
  179. {conexus-6.3.1 → conexus-6.3.2}/service/src/main/resources/db/changelog/t1-001-baseline.xml +0 -0
  180. {conexus-6.3.1 → conexus-6.3.2}/service/src/main/resources/db/changelog/taxonomy-001-baseline.xml +0 -0
  181. {conexus-6.3.1 → conexus-6.3.2}/service/src/main/resources/db/changelog/taxonomy-002-centroids.xml +0 -0
  182. {conexus-6.3.1 → conexus-6.3.2}/service/src/main/resources/db/changelog/taxonomy-003-doc-count-trigger.xml +0 -0
  183. {conexus-6.3.1 → conexus-6.3.2}/service/src/main/resources/db/changelog/taxonomy-004-dedup-root-topics.xml +0 -0
  184. {conexus-6.3.1 → conexus-6.3.2}/service/src/main/resources/db/changelog/telemetry-001-baseline.xml +0 -0
  185. {conexus-6.3.1 → conexus-6.3.2}/service/src/main/resources/db/changelog/updated-at-001-triggers.xml +0 -0
  186. {conexus-6.3.1 → conexus-6.3.2}/service/src/main/resources/db/changelog/vectors-001-baseline.xml +0 -0
  187. {conexus-6.3.1 → conexus-6.3.2}/service/src/main/resources/db/changelog/vectors-002-trgm-index.xml +0 -0
  188. {conexus-6.3.1 → conexus-6.3.2}/service/src/main/resources/logback.xml +0 -0
  189. {conexus-6.3.1 → conexus-6.3.2}/service/src/test/java/dev/nexus/service/AspectOperatorQueryTest.java +0 -0
  190. {conexus-6.3.1 → conexus-6.3.2}/service/src/test/java/dev/nexus/service/AspectRepositoryTest.java +0 -0
  191. {conexus-6.3.1 → conexus-6.3.2}/service/src/test/java/dev/nexus/service/AuthFilterTest.java +0 -0
  192. {conexus-6.3.1 → conexus-6.3.2}/service/src/test/java/dev/nexus/service/Bge768ParityTest.java +0 -0
  193. {conexus-6.3.1 → conexus-6.3.2}/service/src/test/java/dev/nexus/service/Bge768ServiceEmbedIntegrationTest.java +0 -0
  194. {conexus-6.3.1 → conexus-6.3.2}/service/src/test/java/dev/nexus/service/BridgeAddressFieldsTest.java +0 -0
  195. {conexus-6.3.1 → conexus-6.3.2}/service/src/test/java/dev/nexus/service/CatalogDeleteCollectionCascadeTest.java +0 -0
  196. {conexus-6.3.1 → conexus-6.3.2}/service/src/test/java/dev/nexus/service/CatalogDocumentCascadeTest.java +0 -0
  197. {conexus-6.3.1 → conexus-6.3.2}/service/src/test/java/dev/nexus/service/CatalogHandlerDeleteTest.java +0 -0
  198. {conexus-6.3.1 → conexus-6.3.2}/service/src/test/java/dev/nexus/service/CatalogHandlerRenameTest.java +0 -0
  199. {conexus-6.3.1 → conexus-6.3.2}/service/src/test/java/dev/nexus/service/CatalogRenameCollectionTest.java +0 -0
  200. {conexus-6.3.1 → conexus-6.3.2}/service/src/test/java/dev/nexus/service/CatalogSchemaLiquibaseTest.java +0 -0
  201. {conexus-6.3.1 → conexus-6.3.2}/service/src/test/java/dev/nexus/service/ChashVectorConcurrencyTest.java +0 -0
  202. {conexus-6.3.1 → conexus-6.3.2}/service/src/test/java/dev/nexus/service/ChunksRlsBehavioralTest.java +0 -0
  203. {conexus-6.3.1 → conexus-6.3.2}/service/src/test/java/dev/nexus/service/CollectionRegistryFkExtraTest.java +0 -0
  204. {conexus-6.3.1 → conexus-6.3.2}/service/src/test/java/dev/nexus/service/CollectionRegistryFkTest.java +0 -0
  205. {conexus-6.3.1 → conexus-6.3.2}/service/src/test/java/dev/nexus/service/CollectionVectorStatsTest.java +0 -0
  206. {conexus-6.3.1 → conexus-6.3.2}/service/src/test/java/dev/nexus/service/CombinedQueryParityIntegrationTest.java +0 -0
  207. {conexus-6.3.1 → conexus-6.3.2}/service/src/test/java/dev/nexus/service/CombinedQueryParityTest.java +0 -0
  208. {conexus-6.3.1 → conexus-6.3.2}/service/src/test/java/dev/nexus/service/DualRunHarnessIntegrationTest.java +0 -0
  209. {conexus-6.3.1 → conexus-6.3.2}/service/src/test/java/dev/nexus/service/EmbedParityTest.java +0 -0
  210. {conexus-6.3.1 → conexus-6.3.2}/service/src/test/java/dev/nexus/service/EmbeddingModeFailLoudTest.java +0 -0
  211. {conexus-6.3.1 → conexus-6.3.2}/service/src/test/java/dev/nexus/service/ForeignKeyConstraintTest.java +0 -0
  212. {conexus-6.3.1 → conexus-6.3.2}/service/src/test/java/dev/nexus/service/GraphHopParityIntegrationTest.java +0 -0
  213. {conexus-6.3.1 → conexus-6.3.2}/service/src/test/java/dev/nexus/service/GraphHopParityTest.java +0 -0
  214. {conexus-6.3.1 → conexus-6.3.2}/service/src/test/java/dev/nexus/service/HybridParityIntegrationTest.java +0 -0
  215. {conexus-6.3.1 → conexus-6.3.2}/service/src/test/java/dev/nexus/service/HybridSelectiveGateTest.java +0 -0
  216. {conexus-6.3.1 → conexus-6.3.2}/service/src/test/java/dev/nexus/service/ManifestFunctionsTest.java +0 -0
  217. {conexus-6.3.1 → conexus-6.3.2}/service/src/test/java/dev/nexus/service/MemoryHandlerTest.java +0 -0
  218. {conexus-6.3.1 → conexus-6.3.2}/service/src/test/java/dev/nexus/service/MemoryRepositoryTest.java +0 -0
  219. {conexus-6.3.1 → conexus-6.3.2}/service/src/test/java/dev/nexus/service/MemorySchemaLiquibaseTest.java +0 -0
  220. {conexus-6.3.1 → conexus-6.3.2}/service/src/test/java/dev/nexus/service/PgBouncerTenantIsolationTest.java +0 -0
  221. {conexus-6.3.1 → conexus-6.3.2}/service/src/test/java/dev/nexus/service/PgContainerHelper.java +0 -0
  222. {conexus-6.3.1 → conexus-6.3.2}/service/src/test/java/dev/nexus/service/PgVectorCombinedQueryContractTest.java +0 -0
  223. {conexus-6.3.1 → conexus-6.3.2}/service/src/test/java/dev/nexus/service/PgVectorHybridSearchContractTest.java +0 -0
  224. {conexus-6.3.1 → conexus-6.3.2}/service/src/test/java/dev/nexus/service/PgVectorServingContractTest.java +0 -0
  225. {conexus-6.3.1 → conexus-6.3.2}/service/src/test/java/dev/nexus/service/PlanHandlerTest.java +0 -0
  226. {conexus-6.3.1 → conexus-6.3.2}/service/src/test/java/dev/nexus/service/PlanRepositoryTest.java +0 -0
  227. {conexus-6.3.1 → conexus-6.3.2}/service/src/test/java/dev/nexus/service/PlansSchemaLiquibaseTest.java +0 -0
  228. {conexus-6.3.1 → conexus-6.3.2}/service/src/test/java/dev/nexus/service/ReadShapeViewsTest.java +0 -0
  229. {conexus-6.3.1 → conexus-6.3.2}/service/src/test/java/dev/nexus/service/ReferenceOnlyChunkUpsertTest.java +0 -0
  230. {conexus-6.3.1 → conexus-6.3.2}/service/src/test/java/dev/nexus/service/SchemaMigratorIntegrationTest.java +0 -0
  231. {conexus-6.3.1 → conexus-6.3.2}/service/src/test/java/dev/nexus/service/ScratchHandlerTest.java +0 -0
  232. {conexus-6.3.1 → conexus-6.3.2}/service/src/test/java/dev/nexus/service/ScratchRepositoryTest.java +0 -0
  233. {conexus-6.3.1 → conexus-6.3.2}/service/src/test/java/dev/nexus/service/ScratchSchemaLiquibaseTest.java +0 -0
  234. {conexus-6.3.1 → conexus-6.3.2}/service/src/test/java/dev/nexus/service/ServiceBindHostTest.java +0 -0
  235. {conexus-6.3.1 → conexus-6.3.2}/service/src/test/java/dev/nexus/service/ServiceIntegrationTest.java +0 -0
  236. {conexus-6.3.1 → conexus-6.3.2}/service/src/test/java/dev/nexus/service/ServiceTokenSchemaLiquibaseTest.java +0 -0
  237. {conexus-6.3.1 → conexus-6.3.2}/service/src/test/java/dev/nexus/service/SessionTokenHandlerTest.java +0 -0
  238. {conexus-6.3.1 → conexus-6.3.2}/service/src/test/java/dev/nexus/service/SoftDeleteTest.java +0 -0
  239. {conexus-6.3.1 → conexus-6.3.2}/service/src/test/java/dev/nexus/service/TaxonomyCentroidHandlerTest.java +0 -0
  240. {conexus-6.3.1 → conexus-6.3.2}/service/src/test/java/dev/nexus/service/TaxonomyCentroidRepositoryTest.java +0 -0
  241. {conexus-6.3.1 → conexus-6.3.2}/service/src/test/java/dev/nexus/service/TaxonomyCentroidSchemaLiquibaseTest.java +0 -0
  242. {conexus-6.3.1 → conexus-6.3.2}/service/src/test/java/dev/nexus/service/TaxonomyPersistHandlerTest.java +0 -0
  243. {conexus-6.3.1 → conexus-6.3.2}/service/src/test/java/dev/nexus/service/TaxonomySchemaLiquibaseTest.java +0 -0
  244. {conexus-6.3.1 → conexus-6.3.2}/service/src/test/java/dev/nexus/service/TelemetryRepositoryTest.java +0 -0
  245. {conexus-6.3.1 → conexus-6.3.2}/service/src/test/java/dev/nexus/service/TelemetrySchemaLiquibaseTest.java +0 -0
  246. {conexus-6.3.1 → conexus-6.3.2}/service/src/test/java/dev/nexus/service/TenantPoolingIsolationTest.java +0 -0
  247. {conexus-6.3.1 → conexus-6.3.2}/service/src/test/java/dev/nexus/service/TokenAdminHandlerTest.java +0 -0
  248. {conexus-6.3.1 → conexus-6.3.2}/service/src/test/java/dev/nexus/service/TokenBoundaryAdversarialTest.java +0 -0
  249. {conexus-6.3.1 → conexus-6.3.2}/service/src/test/java/dev/nexus/service/UpdatedAtTriggerTest.java +0 -0
  250. {conexus-6.3.1 → conexus-6.3.2}/service/src/test/java/dev/nexus/service/VectorHandlerEmbeddingModeTest.java +0 -0
  251. {conexus-6.3.1 → conexus-6.3.2}/service/src/test/java/dev/nexus/service/VectorHandlerTokenUsageTest.java +0 -0
  252. {conexus-6.3.1 → conexus-6.3.2}/service/src/test/java/dev/nexus/service/VectorHybridHttpTest.java +0 -0
  253. {conexus-6.3.1 → conexus-6.3.2}/service/src/test/java/dev/nexus/service/VectorIntegrationTest.java +0 -0
  254. {conexus-6.3.1 → conexus-6.3.2}/service/src/test/java/dev/nexus/service/db/CatalogTsOrNullTest.java +0 -0
  255. {conexus-6.3.1 → conexus-6.3.2}/service/src/test/java/dev/nexus/service/db/CollectionRegistryTest.java +0 -0
  256. {conexus-6.3.1 → conexus-6.3.2}/service/src/test/java/dev/nexus/service/db/PoolerModeCheckTest.java +0 -0
  257. {conexus-6.3.1 → conexus-6.3.2}/service/src/test/java/dev/nexus/service/db/RawSqlGateTest.java +0 -0
  258. {conexus-6.3.1 → conexus-6.3.2}/service/src/test/java/dev/nexus/service/db/TenantScopeAdmissionTest.java +0 -0
  259. {conexus-6.3.1 → conexus-6.3.2}/service/src/test/java/dev/nexus/service/db/TenantScopeGucAllowlistTest.java +0 -0
  260. {conexus-6.3.1 → conexus-6.3.2}/service/src/test/java/dev/nexus/service/http/AspectHandlerEnqueueErrorTest.java +0 -0
  261. {conexus-6.3.1 → conexus-6.3.2}/service/src/test/java/dev/nexus/service/http/CatalogHandlerImportEmptyBodyTest.java +0 -0
  262. {conexus-6.3.1 → conexus-6.3.2}/service/src/test/java/dev/nexus/service/http/CatalogHandlerManifestFkTest.java +0 -0
  263. {conexus-6.3.1 → conexus-6.3.2}/service/src/test/java/dev/nexus/service/http/MigrationHandlerIngestCloudTest.java +0 -0
  264. {conexus-6.3.1 → conexus-6.3.2}/service/src/test/java/dev/nexus/service/http/TaxonomyHandlerAssignFkTest.java +0 -0
  265. {conexus-6.3.1 → conexus-6.3.2}/service/src/test/java/dev/nexus/service/http/VersionHandlerReleaseVersionTest.java +0 -0
  266. {conexus-6.3.1 → conexus-6.3.2}/service/src/test/java/dev/nexus/service/jooq/binding/VectorRoundTripTest.java +0 -0
  267. {conexus-6.3.1 → conexus-6.3.2}/service/src/test/java/dev/nexus/service/nativeimage/JooqRecordReflectionFeatureTest.java +0 -0
  268. {conexus-6.3.1 → conexus-6.3.2}/service/src/test/java/dev/nexus/service/resolver/ChromaSchemeHandlerTest.java +0 -0
  269. {conexus-6.3.1 → conexus-6.3.2}/service/src/test/java/dev/nexus/service/resolver/HttpsSchemeHandlerTest.java +0 -0
  270. {conexus-6.3.1 → conexus-6.3.2}/service/src/test/java/dev/nexus/service/resolver/UriSchemeResolverRegistryTest.java +0 -0
  271. {conexus-6.3.1 → conexus-6.3.2}/service/src/test/java/dev/nexus/service/vectors/Bge768EmbedderMathTest.java +0 -0
  272. {conexus-6.3.1 → conexus-6.3.2}/service/src/test/java/dev/nexus/service/vectors/EgressProxyTest.java +0 -0
  273. {conexus-6.3.1 → conexus-6.3.2}/service/src/test/java/dev/nexus/service/vectors/EmbedderRouterBge768Test.java +0 -0
  274. {conexus-6.3.1 → conexus-6.3.2}/service/src/test/java/dev/nexus/service/vectors/EmbedderRouterVoyageOnlyTest.java +0 -0
  275. {conexus-6.3.1 → conexus-6.3.2}/service/src/test/java/dev/nexus/service/vectors/PgVectorRepositoryWherePredicateTest.java +0 -0
  276. {conexus-6.3.1 → conexus-6.3.2}/service/src/test/java/dev/nexus/service/vectors/ReferenceOnlySqlShapeTest.java +0 -0
  277. {conexus-6.3.1 → conexus-6.3.2}/service/src/test/resources/bge768/parity_reference.json +0 -0
  278. {conexus-6.3.1 → conexus-6.3.2}/sn/README.md +0 -0
  279. {conexus-6.3.1 → conexus-6.3.2}/sn/hooks/scripts/routing/README.md +0 -0
  280. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/__init__.py +0 -0
  281. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/_git_hooks_meta.py +0 -0
  282. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/_locking.py +0 -0
  283. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/_mineru_pid.py +0 -0
  284. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/_session_end_launcher.py +0 -0
  285. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/aspect_extractor.py +0 -0
  286. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/aspect_promotion.py +0 -0
  287. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/aspect_readers.py +0 -0
  288. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/aspect_worker.py +0 -0
  289. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/bib_enricher.py +0 -0
  290. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/bib_enricher_openalex.py +0 -0
  291. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/bib_extractor.py +0 -0
  292. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/catalog/AGENTS.md +0 -0
  293. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/catalog/__init__.py +0 -0
  294. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/catalog/auto_linker.py +0 -0
  295. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/catalog/catalog_backup.py +0 -0
  296. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/catalog/catalog_db.py +0 -0
  297. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/catalog/catalog_docs.py +0 -0
  298. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/catalog/catalog_git.py +0 -0
  299. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/catalog/catalog_links.py +0 -0
  300. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/catalog/catalog_owners.py +0 -0
  301. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/catalog/catalog_spans.py +0 -0
  302. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/catalog/catalog_sync.py +0 -0
  303. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/catalog/catalog_writes.py +0 -0
  304. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/catalog/collection_name.py +0 -0
  305. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/catalog/collections_owner_backfill.py +0 -0
  306. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/catalog/consolidation.py +0 -0
  307. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/catalog/dedupe.py +0 -0
  308. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/catalog/dt_link_generator.py +0 -0
  309. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/catalog/event_log.py +0 -0
  310. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/catalog/events.py +0 -0
  311. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/catalog/factory.py +0 -0
  312. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/catalog/link_generator.py +0 -0
  313. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/catalog/manifest_backfill.py +0 -0
  314. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/catalog/orphan_backfill.py +0 -0
  315. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/catalog/projector.py +0 -0
  316. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/catalog/store_hook.py +0 -0
  317. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/catalog/synthesizer.py +0 -0
  318. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/catalog/tumbler.py +0 -0
  319. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/catalog/types.py +0 -0
  320. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/catalog/write_priority.py +0 -0
  321. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/checkpoint.py +0 -0
  322. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/chunk_identity.py +0 -0
  323. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/chunker.py +0 -0
  324. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/classifier.py +0 -0
  325. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/cli.py +0 -0
  326. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/collection_audit.py +0 -0
  327. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/collection_health.py +0 -0
  328. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/collection_rename.py +0 -0
  329. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/commands/__init__.py +0 -0
  330. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/commands/_helpers.py +0 -0
  331. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/commands/_migration_prompt.py +0 -0
  332. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/commands/_provision.py +0 -0
  333. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/commands/aspects.py +0 -0
  334. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/commands/catalog.py +0 -0
  335. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/commands/catalog_cmds/__init__.py +0 -0
  336. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/commands/catalog_cmds/backfill.py +0 -0
  337. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/commands/catalog_cmds/backups.py +0 -0
  338. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/commands/catalog_cmds/collections.py +0 -0
  339. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/commands/catalog_cmds/doctor.py +0 -0
  340. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/commands/catalog_cmds/integrity.py +0 -0
  341. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/commands/catalog_cmds/links.py +0 -0
  342. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/commands/catalog_cmds/maintenance.py +0 -0
  343. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/commands/catalog_cmds/migration.py +0 -0
  344. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/commands/catalog_cmds/orphan_backfill.py +0 -0
  345. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/commands/catalog_cmds/owners.py +0 -0
  346. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/commands/catalog_cmds/remediation.py +0 -0
  347. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/commands/catalog_cmds/report.py +0 -0
  348. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/commands/collection.py +0 -0
  349. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/commands/command_context.py +0 -0
  350. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/commands/config_cmd.py +0 -0
  351. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/commands/console.py +0 -0
  352. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/commands/context_cmd.py +0 -0
  353. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/commands/daemon.py +0 -0
  354. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/commands/doc.py +0 -0
  355. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/commands/doctor.py +0 -0
  356. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/commands/dt.py +0 -0
  357. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/commands/enrich.py +0 -0
  358. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/commands/guided_upgrade_cmd.py +0 -0
  359. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/commands/hook.py +0 -0
  360. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/commands/hooks.py +0 -0
  361. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/commands/init.py +0 -0
  362. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/commands/memory.py +0 -0
  363. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/commands/migrate_cmd.py +0 -0
  364. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/commands/migration_cmd.py +0 -0
  365. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/commands/mineru.py +0 -0
  366. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/commands/plan.py +0 -0
  367. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/commands/rdr.py +0 -0
  368. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/commands/scratch.py +0 -0
  369. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/commands/search_cmd.py +0 -0
  370. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/commands/storage_cmd.py +0 -0
  371. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/commands/store.py +0 -0
  372. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/commands/t3.py +0 -0
  373. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/commands/taxonomy_cmd.py +0 -0
  374. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/commands/tenant_cmd.py +0 -0
  375. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/commands/tier_status.py +0 -0
  376. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/commands/uninstall.py +0 -0
  377. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/commands/upgrade.py +0 -0
  378. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/config.py +0 -0
  379. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/console/__init__.py +0 -0
  380. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/console/app.py +0 -0
  381. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/console/config.py +0 -0
  382. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/console/routes/__init__.py +0 -0
  383. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/console/routes/activity.py +0 -0
  384. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/console/routes/campaigns.py +0 -0
  385. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/console/routes/health.py +0 -0
  386. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/console/routes/partials.py +0 -0
  387. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/console/static/alpine.min.js +0 -0
  388. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/console/static/console.css +0 -0
  389. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/console/static/htmx.min.js +0 -0
  390. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/console/static/pico.min.css +0 -0
  391. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/console/templates/activity/_detail.html +0 -0
  392. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/console/templates/activity/_stream.html +0 -0
  393. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/console/templates/activity/index.html +0 -0
  394. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/console/templates/base.html +0 -0
  395. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/console/templates/campaigns/detail.html +0 -0
  396. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/console/templates/campaigns/index.html +0 -0
  397. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/console/templates/health/_cards.html +0 -0
  398. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/console/templates/health/index.html +0 -0
  399. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/console/watchers.py +0 -0
  400. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/context.py +0 -0
  401. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/corpus.py +0 -0
  402. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/cross_encoder.py +0 -0
  403. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/daemon/AGENTS.md +0 -0
  404. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/daemon/T2_DAEMON_WIP.md +0 -0
  405. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/daemon/__init__.py +0 -0
  406. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/daemon/aspect_worker_daemon.py +0 -0
  407. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/daemon/binary_lifecycle.py +0 -0
  408. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/daemon/discovery.py +0 -0
  409. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/daemon/installer.py +0 -0
  410. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/daemon/service_registry.py +0 -0
  411. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/daemon/spin_guard.py +0 -0
  412. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/daemon/storage_service_daemon.py +0 -0
  413. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/daemon/t1_lease.py +0 -0
  414. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/daemon/t2_daemon.py +0 -0
  415. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/daemon/t3_daemon.py +0 -0
  416. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/db/AGENTS.md +0 -0
  417. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/db/__init__.py +0 -0
  418. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/db/chroma_quotas.py +0 -0
  419. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/db/collection_purge.py +0 -0
  420. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/db/embed_migrate.py +0 -0
  421. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/db/http_scratch_store.py +0 -0
  422. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/db/local_ef.py +0 -0
  423. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/db/managed_endpoint.py +0 -0
  424. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/db/migrations.py +0 -0
  425. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/db/pg_bundle.py +0 -0
  426. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/db/pg_provision.py +0 -0
  427. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/db/service_bge_model.py +0 -0
  428. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/db/service_endpoint.py +0 -0
  429. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/db/storage_mode.py +0 -0
  430. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/db/t1.py +0 -0
  431. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/db/t2/__init__.py +0 -0
  432. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/db/t2/_raw_handle_guard.py +0 -0
  433. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/db/t2/_tuning.py +0 -0
  434. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/db/t2/aspect_extraction_queue.py +0 -0
  435. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/db/t2/aspects_etl.py +0 -0
  436. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/db/t2/catalog.py +0 -0
  437. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/db/t2/catalog_etl.py +0 -0
  438. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/db/t2/catalog_taxonomy.py +0 -0
  439. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/db/t2/chash_etl.py +0 -0
  440. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/db/t2/chash_index.py +0 -0
  441. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/db/t2/document_aspects.py +0 -0
  442. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/db/t2/document_highlights.py +0 -0
  443. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/db/t2/http_aspect_queue.py +0 -0
  444. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/db/t2/http_centroid_store.py +0 -0
  445. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/db/t2/http_document_aspects_store.py +0 -0
  446. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/db/t2/http_document_highlights_store.py +0 -0
  447. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/db/t2/http_memory_store.py +0 -0
  448. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/db/t2/http_plan_library.py +0 -0
  449. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/db/t2/http_telemetry_store.py +0 -0
  450. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/db/t2/http_token_store.py +0 -0
  451. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/db/t2/memory_etl.py +0 -0
  452. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/db/t2/memory_store.py +0 -0
  453. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/db/t2/plan_etl.py +0 -0
  454. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/db/t2/plan_library.py +0 -0
  455. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/db/t2/taxonomy_compute.py +0 -0
  456. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/db/t2/taxonomy_etl.py +0 -0
  457. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/db/t2/telemetry.py +0 -0
  458. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/db/t2/telemetry_etl.py +0 -0
  459. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/db/t3_reidentify.py +0 -0
  460. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/devonthink.py +0 -0
  461. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/doc/__init__.py +0 -0
  462. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/doc/_common.py +0 -0
  463. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/doc/citations.py +0 -0
  464. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/doc/ref_scanner.py +0 -0
  465. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/doc/render.py +0 -0
  466. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/doc/resolvers.py +0 -0
  467. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/doc/resolvers_corpus.py +0 -0
  468. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/doc/tokens.py +0 -0
  469. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/doctor_search.py +0 -0
  470. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/dropped_writes.py +0 -0
  471. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/dt_writeback.py +0 -0
  472. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/errors.py +0 -0
  473. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/exporter.py +0 -0
  474. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/filters.py +0 -0
  475. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/formatters.py +0 -0
  476. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/frecency.py +0 -0
  477. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/glossary.py +0 -0
  478. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/health.py +0 -0
  479. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/hooks.py +0 -0
  480. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/languages.py +0 -0
  481. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/logging_setup.py +0 -0
  482. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/mcp/AGENTS.md +0 -0
  483. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/mcp/__init__.py +0 -0
  484. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/mcp/_first_run.py +0 -0
  485. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/mcp/_t1_state.py +0 -0
  486. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/mcp/catalog.py +0 -0
  487. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/mcp/devonthink.py +0 -0
  488. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/mcp/plan_cache_registry.py +0 -0
  489. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/mcp_client/__init__.py +0 -0
  490. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/mcp_client/core.py +0 -0
  491. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/mcp_client/devonthink.py +0 -0
  492. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/mcp_server.py +0 -0
  493. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/md_chunker.py +0 -0
  494. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/merge_candidates.py +0 -0
  495. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/metadata_schema.py +0 -0
  496. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/migration/__init__.py +0 -0
  497. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/migration/banner.py +0 -0
  498. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/migration/chroma_read.py +0 -0
  499. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/migration/detection.py +0 -0
  500. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/migration/driver.py +0 -0
  501. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/migration/etl_registry.py +0 -0
  502. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/migration/guided_upgrade.py +0 -0
  503. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/migration/manifest_check.py +0 -0
  504. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/migration/migration_report.py +0 -0
  505. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/migration/orchestrator.py +0 -0
  506. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/migration/pregate.py +0 -0
  507. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/migration/quiesce.py +0 -0
  508. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/migration/route_coverage.py +0 -0
  509. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/migration/sequencer.py +0 -0
  510. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/migration/state.py +0 -0
  511. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/migration/validation.py +0 -0
  512. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/migration/vector_etl.py +0 -0
  513. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/migration/verify_fill.py +0 -0
  514. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/name_canaries.py +0 -0
  515. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/operators/aspect_sql.py +0 -0
  516. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/operators/dispatch.py +0 -0
  517. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/pdeathsig.py +0 -0
  518. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/pdf_chunker.py +0 -0
  519. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/pdf_extractor.py +0 -0
  520. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/phase_review_sentinel.py +0 -0
  521. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/pipeline_buffer.py +0 -0
  522. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/pipeline_stages.py +0 -0
  523. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/plans/__init__.py +0 -0
  524. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/plans/bundle.py +0 -0
  525. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/plans/loader.py +0 -0
  526. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/plans/match.py +0 -0
  527. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/plans/matcher.py +0 -0
  528. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/plans/promote.py +0 -0
  529. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/plans/purposes.py +0 -0
  530. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/plans/repair.py +0 -0
  531. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/plans/runner.py +0 -0
  532. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/plans/schema.py +0 -0
  533. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/plans/scope.py +0 -0
  534. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/plans/seed_loader.py +0 -0
  535. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/plans/session_cache.py +0 -0
  536. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/registry.py +0 -0
  537. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/repo_identity.py +0 -0
  538. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/repos.py +0 -0
  539. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/retry.py +0 -0
  540. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/ripgrep_cache.py +0 -0
  541. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/routing_stats.py +0 -0
  542. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/salience.py +0 -0
  543. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/scoring.py +0 -0
  544. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/search_clusterer.py +0 -0
  545. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/search_engine.py +0 -0
  546. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/session.py +0 -0
  547. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/stage_timers.py +0 -0
  548. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/storage_boundary_lint.py +0 -0
  549. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/taxonomy.py +0 -0
  550. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/taxonomy_backfill.py +0 -0
  551. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/ttl.py +0 -0
  552. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/types.py +0 -0
  553. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/util/__init__.py +0 -0
  554. {conexus-6.3.1 → conexus-6.3.2}/src/nexus/util/process_group.py +0 -0
  555. {conexus-6.3.1 → conexus-6.3.2}/tests/cc-validation/README.md +0 -0
  556. {conexus-6.3.1 → conexus-6.3.2}/tests/e2e/t2-migration-sqlite/README.md +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: conexus
3
- Version: 6.3.1
3
+ Version: 6.3.2
4
4
  Summary: Self-hosted semantic search and knowledge management for LLM-driven development
5
5
  Project-URL: Homepage, https://github.com/Hellblazer/nexus
6
6
  Project-URL: Repository, https://github.com/Hellblazer/nexus
@@ -194,6 +194,8 @@ An RDR (Research-Design-Review) is a short document that records a technical dec
194
194
  | [RDR-176](rdr-176-survivable-managed-migration-readiness.md) | Survivable Managed-Migration Readiness: Batched ETL, First-Class Downgrade with an Immutable Source, Unified Config-First Auth, Edge Route Coverage, and Migration Observability | Architecture | Closed | 2026-06-30 |
195
195
  | [RDR-177](rdr-177-tenant-telemetry-usage-metering.md) | Unified Tenant-Scoped Telemetry, Observability, and Usage Metering for the Engine Service: One Stats Layer for Local Users and Cloud Tenants | Architecture | Draft | 2026-07-01 |
196
196
  | [RDR-178](rdr-178-unattended-migration.md) | Unattended Migration: Industrialize the Store-Migration Path from Babysat to Autonomous | Architecture | Closed | 2026-07-01 |
197
+ | [RDR-179](rdr-179-self-correction-machinery-remediation.md) | Self-Correction Machinery Remediation: Relight Plan-Reuse, Retrieval Benchmarking, Plan-Library Hygiene, and Taxonomy-Aware Recall | Architecture | Draft | 2026-07-04 |
198
+ | [RDR-181](rdr-181-server-side-embed-skip-on-reindex.md) | Server-Side Embed-Skip on Re-Index: Stop Re-Embedding Chunks Whose Vector the Store Already Holds | Technical Debt | Accepted | 2026-07-05 |
197
199
 
198
200
  > **Scrapped 2026-05-19 (RDR-110-119 arc).** Bundled the storage-substrate split with new abstractions (tuplespace, ORB, host-trust, surfaces-as-tuples, UI fabric); scope discipline failed across nine RDRs and 67 stranded beads. Files preserved as tombstones per the "never delete RDR files" rule. Postmortem: [docs/postmortem/2026-05-16-rdr110-113-remediation-chain.md](../postmortem/2026-05-16-rdr110-113-remediation-chain.md). Active substrate work continues as [RDR-120](rdr-120-storage-substrate-split.md) with an explicit moratorium on co-shipped consumers. Numbers RDR-114 through RDR-117 are unused on `main` (drafted on feature branches that never merged).
199
201
 
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "conexus-mcpb"
3
- version = "6.3.1"
3
+ version = "6.3.2"
4
4
  description = "Conexus packaged as Claude Desktop .mcpb (Desktop Extension)"
5
5
  requires-python = ">=3.12"
6
6
  dependencies = [
@@ -10,7 +10,7 @@ dependencies = [
10
10
  # while collections are indexed at 768/1024-dim, so every T3 search hits a
11
11
  # dimension mismatch and returns zero results. The .mcpb cannot run the
12
12
  # interactive `nx init` embedder choice, so it must pin [local] explicitly.
13
- "conexus[local]>=6.3.1",
13
+ "conexus[local]>=6.3.2",
14
14
  ]
15
15
 
16
16
  [tool.uv]
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "conexus"
7
- version = "6.3.1"
7
+ version = "6.3.2"
8
8
  description = "Self-hosted semantic search and knowledge management for LLM-driven development"
9
9
  readme = { file = "README.md", content-type = "text/markdown" }
10
10
  requires-python = ">=3.12,<3.14"
@@ -450,6 +450,152 @@ public final class CatalogRepository {
450
450
  });
451
451
  }
452
452
 
453
+ /**
454
+ * Batch variant of {@link #registerDocument} (nexus-9dvqy, duoak.11 sink #2).
455
+ *
456
+ * <p>Registers N documents under one owner in a SINGLE transaction, returning
457
+ * their tumblers in INPUT ORDER. The per-doc {@code registerDocument} path pays
458
+ * one {@code SELECT next_seq FOR UPDATE} owner-row lock per call — 2,133 serial
459
+ * WAN round-trips on a --force index (333s / 16% of the duoak.11 gate wall), all
460
+ * queued on the SAME owner lock (so client concurrency cannot help). This claims
461
+ * the whole contiguous sequence block under ONE lock acquisition and inserts all
462
+ * new rows in one multi-row INSERT.
463
+ *
464
+ * <p>Idempotency matches the single-doc path exactly: a doc whose {@code source_uri}
465
+ * (then {@code file_path}) already maps to a LIVE (non-tombstoned) document returns
466
+ * that existing tumbler and does NOT consume a sequence number — so a re-registration
467
+ * leaves no seq gap. Only genuinely-new docs draw from the claimed block.
468
+ *
469
+ * <p>Caller (the HTTP handler) caps the batch under the PostgreSQL 32767 bind-param
470
+ * ceiling; with ~24 columns per row the safe cap is 1000 rows (24000 params).
471
+ */
472
+ public java.util.List<String> registerDocumentMany(
473
+ String tenant, String ownerPrefix, java.util.List<java.util.Map<String, Object>> docs) {
474
+ if (TenantConstants.isWildcard(tenant)) {
475
+ throw new IllegalArgumentException(
476
+ "tenant '*' is a reserved sentinel and cannot own catalog entries");
477
+ }
478
+ if (docs == null || docs.isEmpty()) {
479
+ return java.util.List.of();
480
+ }
481
+ return tenantScope.withTenant(tenant, ctx -> {
482
+ // Ensure owner row exists (idempotent upsert, minimal fields) — once.
483
+ ctx.insertInto(CATALOG_OWNERS, CATALOG_OWNERS.TENANT_ID, CATALOG_OWNERS.TUMBLER_PREFIX, CATALOG_OWNERS.NAME, CATALOG_OWNERS.OWNER_TYPE,
484
+ CATALOG_OWNERS.REPO_HASH, CATALOG_OWNERS.DESCRIPTION, CATALOG_OWNERS.REPO_ROOT, CATALOG_OWNERS.HEAD_HASH, CATALOG_OWNERS.NEXT_SEQ)
485
+ .values(tenant, ownerPrefix,
486
+ s(docs.get(0), "owner_name", ownerPrefix),
487
+ s(docs.get(0), "owner_type", "repo"),
488
+ null, null, "", null, 0L)
489
+ .onConflict(CATALOG_OWNERS.TENANT_ID, CATALOG_OWNERS.TUMBLER_PREFIX)
490
+ .doNothing()
491
+ .execute();
492
+
493
+ // Batch idempotency: fetch existing LIVE docs for every source_uri and
494
+ // file_path in the batch in ONE query per direction, then join locally.
495
+ java.util.List<String> srcUris = new java.util.ArrayList<>();
496
+ java.util.List<String> filePaths = new java.util.ArrayList<>();
497
+ for (var d : docs) {
498
+ String su = s(d, "source_uri", "");
499
+ if (!su.isEmpty()) srcUris.add(su);
500
+ String fp = s(d, "file_path", "");
501
+ if (!fp.isEmpty()) filePaths.add(fp);
502
+ }
503
+ java.util.Map<String, String> tumblerBySrcUri = new java.util.HashMap<>();
504
+ if (!srcUris.isEmpty()) {
505
+ ctx.select(CATALOG_DOCUMENTS.SOURCE_URI, CATALOG_DOCUMENTS.TUMBLER)
506
+ .from(CATALOG_DOCUMENTS)
507
+ .where(CATALOG_DOCUMENTS.TENANT_ID.eq(tenant)
508
+ .and(CATALOG_DOCUMENTS.SOURCE_URI.in(srcUris))
509
+ .and(CATALOG_DOCUMENTS.DELETED_AT.isNull()))
510
+ .fetch()
511
+ .forEach(r -> tumblerBySrcUri.putIfAbsent(r.value1(), r.value2()));
512
+ }
513
+ java.util.Map<String, String> tumblerByFilePath = new java.util.HashMap<>();
514
+ if (!filePaths.isEmpty()) {
515
+ ctx.select(CATALOG_DOCUMENTS.FILE_PATH, CATALOG_DOCUMENTS.TUMBLER)
516
+ .from(CATALOG_DOCUMENTS)
517
+ .where(CATALOG_DOCUMENTS.TENANT_ID.eq(tenant)
518
+ .and(CATALOG_DOCUMENTS.FILE_PATH.in(filePaths))
519
+ .and(CATALOG_DOCUMENTS.TUMBLER.startsWith(ownerPrefix + "."))
520
+ .and(CATALOG_DOCUMENTS.DELETED_AT.isNull()))
521
+ .fetch()
522
+ .forEach(r -> tumblerByFilePath.putIfAbsent(r.value1(), r.value2()));
523
+ }
524
+
525
+ // Resolve each doc to an existing tumbler or mark it NEW (input order).
526
+ String[] out = new String[docs.size()];
527
+ java.util.List<Integer> newIdx = new java.util.ArrayList<>();
528
+ for (int i = 0; i < docs.size(); i++) {
529
+ var d = docs.get(i);
530
+ String su = s(d, "source_uri", "");
531
+ String fp = s(d, "file_path", "");
532
+ String existing = null;
533
+ if (!su.isEmpty()) existing = tumblerBySrcUri.get(su);
534
+ if (existing == null && !fp.isEmpty()) existing = tumblerByFilePath.get(fp);
535
+ if (existing != null) {
536
+ out[i] = existing;
537
+ } else {
538
+ newIdx.add(i);
539
+ }
540
+ }
541
+
542
+ if (!newIdx.isEmpty()) {
543
+ // Claim a contiguous seq block under ONE FOR UPDATE lock.
544
+ long seq = ctx.select(CATALOG_OWNERS.NEXT_SEQ).from(CATALOG_OWNERS)
545
+ .where(CATALOG_OWNERS.TENANT_ID.eq(tenant).and(CATALOG_OWNERS.TUMBLER_PREFIX.eq(ownerPrefix)))
546
+ .forUpdate()
547
+ .fetchOne(CATALOG_OWNERS.NEXT_SEQ);
548
+ long cursor = seq;
549
+
550
+ var insert = ctx.insertInto(CATALOG_DOCUMENTS,
551
+ CATALOG_DOCUMENTS.TENANT_ID, CATALOG_DOCUMENTS.TUMBLER, CATALOG_DOCUMENTS.TITLE, CATALOG_DOCUMENTS.AUTHOR, CATALOG_DOCUMENTS.YEAR,
552
+ CATALOG_DOCUMENTS.CONTENT_TYPE, CATALOG_DOCUMENTS.FILE_PATH, CATALOG_DOCUMENTS.CORPUS, CATALOG_DOCUMENTS.PHYSICAL_COLLECTION, CATALOG_DOCUMENTS.CHUNK_COUNT,
553
+ CATALOG_DOCUMENTS.HEAD_HASH, CATALOG_DOCUMENTS.INDEXED_AT, F_DOC_META, CATALOG_DOCUMENTS.SOURCE_MTIME, CATALOG_DOCUMENTS.ALIAS_OF, CATALOG_DOCUMENTS.SOURCE_URI,
554
+ CATALOG_DOCUMENTS.BIB_YEAR, CATALOG_DOCUMENTS.BIB_AUTHORS, CATALOG_DOCUMENTS.BIB_VENUE, CATALOG_DOCUMENTS.BIB_CITATION_COUNT,
555
+ CATALOG_DOCUMENTS.BIB_SEMANTIC_SCHOLAR_ID, CATALOG_DOCUMENTS.BIB_OPENALEX_ID, CATALOG_DOCUMENTS.BIB_DOI, CATALOG_DOCUMENTS.BIB_ENRICHED_AT);
556
+ for (int idx : newIdx) {
557
+ var fields = docs.get(idx);
558
+ cursor += 1;
559
+ String tumbler = ownerPrefix + "." + cursor;
560
+ out[idx] = tumbler;
561
+ String metaJson = jsonOrNull(fields.get("meta"));
562
+ insert = insert.values(tenant, tumbler,
563
+ s(fields, "title", ""),
564
+ nne(s(fields, "author", null)),
565
+ ni(i(fields, "year"), 0),
566
+ nne(s(fields, "content_type", "")),
567
+ nne(s(fields, "file_path", "")),
568
+ nne(s(fields, "corpus", "")),
569
+ nne(s(fields, "physical_collection", "")),
570
+ ni(i(fields, "chunk_count"), 0),
571
+ nne(s(fields, "head_hash", "")),
572
+ nne(s(fields, "indexed_at", "")),
573
+ jsonbVal(metaJson),
574
+ nd(dbl(fields, "source_mtime")),
575
+ nne(s(fields, "alias_of", "")),
576
+ nne(s(fields, "source_uri", "")),
577
+ ni(i(fields, "bib_year"), 0),
578
+ nne(s(fields, "bib_authors", "")),
579
+ nne(s(fields, "bib_venue", "")),
580
+ ni(i(fields, "bib_citation_count"), 0),
581
+ nne(s(fields, "bib_semantic_scholar_id", "")),
582
+ nne(s(fields, "bib_openalex_id", "")),
583
+ nne(s(fields, "bib_doi", "")),
584
+ nne(s(fields, "bib_enriched_at", "")));
585
+ }
586
+ insert.execute();
587
+
588
+ // Advance next_seq by exactly the number of new docs claimed.
589
+ ctx.update(CATALOG_OWNERS)
590
+ .set(CATALOG_OWNERS.NEXT_SEQ, cursor)
591
+ .where(CATALOG_OWNERS.TENANT_ID.eq(tenant).and(CATALOG_OWNERS.TUMBLER_PREFIX.eq(ownerPrefix)))
592
+ .execute();
593
+ }
594
+
595
+ return java.util.Arrays.asList(out);
596
+ });
597
+ }
598
+
453
599
  /** Fetch a document by tumbler. Returns null if not found. */
454
600
  public Map<String, Object> getDocument(String tenant, String tumbler) {
455
601
  return tenantScope.withTenant(tenant, ctx -> {
@@ -1063,19 +1209,86 @@ public final class CatalogRepository {
1063
1209
  /** Replace manifest for docId with the provided rows (atomic delete + insert). */
1064
1210
  public void writeManifest(String tenant, String docId, List<Map<String, Object>> rows) {
1065
1211
  tenantScope.withTenant(tenant, ctx -> {
1066
- ctx.deleteFrom(CATALOG_DOCUMENT_CHUNKS).where(CATALOG_DOCUMENT_CHUNKS.DOC_ID.eq(docId)).execute();
1067
- for (var row : rows) {
1068
- ctx.insertInto(CATALOG_DOCUMENT_CHUNKS,
1069
- CATALOG_DOCUMENT_CHUNKS.TENANT_ID, CATALOG_DOCUMENT_CHUNKS.DOC_ID, CATALOG_DOCUMENT_CHUNKS.POSITION, CATALOG_DOCUMENT_CHUNKS.CHASH, CATALOG_DOCUMENT_CHUNKS.CHUNK_INDEX,
1070
- CATALOG_DOCUMENT_CHUNKS.LINE_START, CATALOG_DOCUMENT_CHUNKS.LINE_END, CATALOG_DOCUMENT_CHUNKS.CHAR_START, CATALOG_DOCUMENT_CHUNKS.CHAR_END)
1071
- .values(tenant, docId, i(row,"position"), s(row,"chash"), i(row,"chunk_index"),
1072
- i(row,"line_start"), i(row,"line_end"), i(row,"char_start"), i(row,"char_end"))
1073
- .execute();
1074
- }
1212
+ writeManifestRows(ctx, tenant, docId, rows);
1075
1213
  return null;
1076
1214
  });
1077
1215
  }
1078
1216
 
1217
+ /**
1218
+ * Shared REPLACE body (delete all rows for docId, then insert the provided
1219
+ * rows) used by both {@link #writeManifest} (one doc per transaction) and
1220
+ * {@link #writeManifestMany} (N docs, one transaction each). Assumes
1221
+ * {@code ctx} is already scoped to {@code tenant}. Does NOT touch
1222
+ * documents.chunk_count — {@code writeManifest}'s public behavior is unchanged;
1223
+ * the chunk_count fold-in is {@code writeManifestMany}'s addition.
1224
+ */
1225
+ private static void writeManifestRows(DSLContext ctx, String tenant, String docId,
1226
+ List<Map<String, Object>> rows) {
1227
+ ctx.deleteFrom(CATALOG_DOCUMENT_CHUNKS).where(CATALOG_DOCUMENT_CHUNKS.DOC_ID.eq(docId)).execute();
1228
+ for (var row : rows) {
1229
+ ctx.insertInto(CATALOG_DOCUMENT_CHUNKS,
1230
+ CATALOG_DOCUMENT_CHUNKS.TENANT_ID, CATALOG_DOCUMENT_CHUNKS.DOC_ID, CATALOG_DOCUMENT_CHUNKS.POSITION, CATALOG_DOCUMENT_CHUNKS.CHASH, CATALOG_DOCUMENT_CHUNKS.CHUNK_INDEX,
1231
+ CATALOG_DOCUMENT_CHUNKS.LINE_START, CATALOG_DOCUMENT_CHUNKS.LINE_END, CATALOG_DOCUMENT_CHUNKS.CHAR_START, CATALOG_DOCUMENT_CHUNKS.CHAR_END)
1232
+ .values(tenant, docId, i(row,"position"), s(row,"chash"), i(row,"chunk_index"),
1233
+ i(row,"line_start"), i(row,"line_end"), i(row,"char_start"), i(row,"char_end"))
1234
+ .execute();
1235
+ }
1236
+ }
1237
+
1238
+ /**
1239
+ * Batch REPLACE manifest for multiple docs (bead nexus-u2kwq). Each doc is
1240
+ * replaced in its OWN {@link TenantScope#withTenant} transaction that folds
1241
+ * together the {@link #writeManifest} REPLACE (delete all rows + insert) AND
1242
+ * a {@code documents.chunk_count = rows.size()} UPDATE — collapsing the
1243
+ * client's separate {@code /manifest/write} + chunk_count {@code /update}
1244
+ * round-trips into one atomic per-doc write. A failure on one doc rolls back
1245
+ * only that doc and its doc_id is collected in {@code failed_doc_ids}; sibling
1246
+ * docs are unaffected (per-doc atomicity, cross-doc isolation). Empty list is
1247
+ * a no-op.
1248
+ *
1249
+ * @param docs each entry {@code {"doc_id": "...", "rows": [<manifest row>...]}}.
1250
+ * @return {@code {docs: <int ok>, rows: <int total written>, failed_doc_ids: [...]}}.
1251
+ */
1252
+ public Map<String, Object> writeManifestMany(String tenant, List<Map<String, Object>> docs) {
1253
+ int okDocs = 0;
1254
+ int totalRows = 0;
1255
+ List<String> failed = new ArrayList<>();
1256
+ if (docs != null) {
1257
+ for (Map<String, Object> d : docs) {
1258
+ String docId = s(d, "doc_id");
1259
+ Object rawRows = d.get("rows");
1260
+ @SuppressWarnings("unchecked")
1261
+ List<Map<String, Object>> rows = rawRows instanceof List<?> l
1262
+ ? (List<Map<String, Object>>) l
1263
+ : List.of();
1264
+ try {
1265
+ if (docId == null || docId.isBlank()) {
1266
+ throw new IllegalArgumentException("'doc_id' required");
1267
+ }
1268
+ tenantScope.withTenant(tenant, ctx -> {
1269
+ writeManifestRows(ctx, tenant, docId, rows);
1270
+ ctx.update(CATALOG_DOCUMENTS)
1271
+ .set(CATALOG_DOCUMENTS.CHUNK_COUNT, rows.size())
1272
+ .where(CATALOG_DOCUMENTS.TUMBLER.eq(docId))
1273
+ .execute();
1274
+ return null;
1275
+ });
1276
+ okDocs++;
1277
+ totalRows += rows.size();
1278
+ } catch (Exception e) {
1279
+ log.debug("event=write_manifest_many_doc_failed tenant={} doc_id={} error={}",
1280
+ tenant, docId, e.getMessage());
1281
+ failed.add(docId);
1282
+ }
1283
+ }
1284
+ }
1285
+ Map<String, Object> result = new LinkedHashMap<>();
1286
+ result.put("docs", okDocs);
1287
+ result.put("rows", totalRows);
1288
+ result.put("failed_doc_ids", failed);
1289
+ return result;
1290
+ }
1291
+
1079
1292
  /** Append manifest rows (upsert by position). */
1080
1293
  public void appendManifestChunks(String tenant, String docId, List<Map<String, Object>> rows) {
1081
1294
  tenantScope.withTenant(tenant, ctx -> {
@@ -173,15 +173,35 @@ public final class ChashRepository {
173
173
  if (chashes == null || chashes.isEmpty()) return;
174
174
 
175
175
  OffsetDateTime now = OffsetDateTime.now(ZoneOffset.UTC);
176
+ // distinct(): a multi-VALUES INSERT .. ON CONFLICT DO UPDATE raises
177
+ // "cannot affect row a second time" (-> HTTP 500) when the same chash
178
+ // appears twice in one statement, and real files emit duplicate chunk
179
+ // text (nexus-85z0y). Dedup is semantics-free: a chash is a content
180
+ // hash, so every occurrence is identical.
181
+ // sorted(): the multi-row INSERT locks CHASH_INDEX rows in values() order.
182
+ // tenant + collection are constant within this call, so chash is the only
183
+ // varying part of the (tenant, chash, physical_collection) conflict key —
184
+ // sorting by chash gives every concurrent batch one global lock order and
185
+ // removes the cross-batch deadlock (SQLSTATE 40P01, nexus-ps9wb; same class as
186
+ // PgVectorRepository.upsertChunks). distinct(): a multi-VALUES INSERT ..
187
+ // ON CONFLICT DO UPDATE raises "cannot affect row a second time" (-> HTTP 500)
188
+ // when the same chash appears twice in one statement, and real files emit
189
+ // duplicate chunk text (nexus-85z0y). Dedup is semantics-free: a chash is a
190
+ // content hash, so every occurrence is identical.
176
191
  List<String> valid = chashes.stream()
177
192
  .filter(c -> c != null && !c.isBlank())
193
+ .distinct()
194
+ .sorted()
178
195
  .toList();
179
196
  if (valid.isEmpty()) return;
180
197
 
181
198
  // Own short committed txn — bounds the first-registration convoy DURATION
182
199
  // (see registerCollectionShortTxn doc); also handles markKnown post-commit.
183
200
  registerCollectionShortTxn(tenant, collection);
184
- tenantScope.withTenant(tenant, ctx -> {
201
+ // nexus-ps9wb belt: retry a residual cross-path deadlock (the sort removes the
202
+ // same-batch cycle; a concurrent writer on a different lock order can still
203
+ // deadlock). Idempotent ON CONFLICT batch, victim already rolled back → safe.
204
+ DeadlockRetry.run(collection, () -> tenantScope.withTenant(tenant, ctx -> {
185
205
  var insert = ctx.insertInto(CHASH_INDEX,
186
206
  CHASH_INDEX.TENANT_ID, CHASH_INDEX.CHASH, CHASH_INDEX.PHYSICAL_COLLECTION, CHASH_INDEX.CREATED_AT);
187
207
  var step = insert.values(tenant, valid.get(0), collection, now);
@@ -193,7 +213,7 @@ public final class ChashRepository {
193
213
  .set(CHASH_INDEX.CREATED_AT, DSL.field("EXCLUDED.created_at", OffsetDateTime.class))
194
214
  .execute();
195
215
  return null;
196
- });
216
+ }));
197
217
  }
198
218
 
199
219
  // ── lookup ─────────────────────────────────────────────────────────────────
@@ -0,0 +1,107 @@
1
+ // SPDX-License-Identifier: AGPL-3.0-or-later
2
+ // Copyright (c) 2026 Hal Hildebrand. All rights reserved.
3
+ package dev.nexus.service.db;
4
+
5
+ import org.slf4j.Logger;
6
+ import org.slf4j.LoggerFactory;
7
+
8
+ import java.sql.SQLException;
9
+ import java.util.concurrent.ThreadLocalRandom;
10
+ import java.util.function.Supplier;
11
+
12
+ /**
13
+ * Shared deadlock-retry belt for the service's multi-row
14
+ * {@code INSERT ... ON CONFLICT (...) DO UPDATE} write paths (bead nexus-ps9wb).
15
+ *
16
+ * <p><strong>Background.</strong> Two concurrent multi-row upsert batches into the
17
+ * same table that touch an overlapping set of conflict keys in DIFFERENT arrival
18
+ * orders lock the shared rows in opposite orders within their single statement →
19
+ * lock cycle → Postgres kills a victim with {@code deadlock detected} (SQLSTATE
20
+ * 40P01) → the caller sees HTTP 500. The PRIMARY fix at each call site is to sort a
21
+ * batch's rows by the ON CONFLICT key before binding, so every concurrent batch
22
+ * acquires row locks in one global order and no cycle can form. This helper is the
23
+ * BELT for residual deadlocks the per-site sort cannot rule out — a concurrent
24
+ * delete, or a different repository writing an overlapping keyspace in its own order.
25
+ *
26
+ * <p><strong>Safety.</strong> The deadlock victim's transaction is ALREADY rolled
27
+ * back by Postgres before the exception surfaces, so re-running an idempotent
28
+ * {@code ON CONFLICT DO UPDATE} batch is safe (no partial state, no double effect).
29
+ * Attempts are bounded ({@link #MAX_ATTEMPTS}) with jittered backoff; the original
30
+ * exception propagates unchanged on exhaustion or for any non-deadlock error. The
31
+ * wrapped unit MUST be only the DB transaction — never anything with external side
32
+ * effects (e.g. embedding calls), or a retry would repeat them.
33
+ */
34
+ public final class DeadlockRetry {
35
+
36
+ private static final Logger log = LoggerFactory.getLogger(DeadlockRetry.class);
37
+
38
+ /** Total attempts (initial try + retries) before the deadlock propagates. */
39
+ static final int MAX_ATTEMPTS = 4;
40
+
41
+ /** PostgreSQL SQLSTATE for {@code deadlock_detected}. */
42
+ static final String SQLSTATE_DEADLOCK = "40P01";
43
+
44
+ private DeadlockRetry() {
45
+ }
46
+
47
+ /**
48
+ * Run {@code writeTxn} (a single idempotent DB transaction), retrying on a
49
+ * deadlock (SQLSTATE 40P01) up to {@link #MAX_ATTEMPTS} total attempts.
50
+ *
51
+ * @param context short label for the retry log line (e.g. the collection name)
52
+ * @param writeTxn the transaction to run; MUST be free of external side effects
53
+ */
54
+ public static void run(String context, Runnable writeTxn) {
55
+ run(context, () -> {
56
+ writeTxn.run();
57
+ return null;
58
+ });
59
+ }
60
+
61
+ /**
62
+ * {@link #run(String, Runnable)} variant returning the transaction's value.
63
+ */
64
+ public static <T> T run(String context, Supplier<T> writeTxn) {
65
+ int attempt = 0;
66
+ while (true) {
67
+ try {
68
+ return writeTxn.get();
69
+ } catch (RuntimeException ex) {
70
+ if (isDeadlock(ex) && ++attempt < MAX_ATTEMPTS) {
71
+ log.warn("event=deadlock_retry context={} attempt={} maxAttempts={}",
72
+ context, attempt, MAX_ATTEMPTS);
73
+ backoff(attempt);
74
+ continue;
75
+ }
76
+ throw ex;
77
+ }
78
+ }
79
+ }
80
+
81
+ /**
82
+ * True if a {@code deadlock_detected} (SQLSTATE 40P01) SQLException appears
83
+ * anywhere in {@code t}'s cause chain. jOOQ wraps the driver SQLException in a
84
+ * {@code DataAccessException} (and TenantScope may further wrap that in a
85
+ * RuntimeException), so the SQLException is a cause, not the top-level throwable —
86
+ * hence the depth-bounded chain walk, which handles either wrapper.
87
+ */
88
+ static boolean isDeadlock(Throwable t) {
89
+ Throwable c = t;
90
+ for (int depth = 0; c != null && depth < 32; depth++, c = c.getCause()) {
91
+ if (c instanceof SQLException se && SQLSTATE_DEADLOCK.equals(se.getSQLState())) {
92
+ return true;
93
+ }
94
+ }
95
+ return false;
96
+ }
97
+
98
+ private static void backoff(int attempt) {
99
+ long ms = Math.min(attempt, MAX_ATTEMPTS) * (10L + ThreadLocalRandom.current().nextLong(20));
100
+ try {
101
+ Thread.sleep(ms);
102
+ } catch (InterruptedException ie) {
103
+ Thread.currentThread().interrupt();
104
+ throw new RuntimeException("interrupted during deadlock-retry backoff", ie);
105
+ }
106
+ }
107
+ }