hypertopos 0.6.0__tar.gz → 0.6.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 (260) hide show
  1. {hypertopos-0.6.0 → hypertopos-0.6.2}/CHANGELOG.md +188 -0
  2. {hypertopos-0.6.0 → hypertopos-0.6.2}/LICENSE.md +1 -1
  3. {hypertopos-0.6.0 → hypertopos-0.6.2}/PKG-INFO +1 -1
  4. {hypertopos-0.6.0 → hypertopos-0.6.2}/README.md +13 -1
  5. hypertopos-0.6.2/ROADMAP.md +89 -0
  6. {hypertopos-0.6.0 → hypertopos-0.6.2}/SECURITY.md +1 -1
  7. {hypertopos-0.6.0 → hypertopos-0.6.2}/docs/api-reference.md +7 -3
  8. {hypertopos-0.6.0 → hypertopos-0.6.2}/docs/architecture.md +2 -2
  9. {hypertopos-0.6.0 → hypertopos-0.6.2}/docs/concepts.md +1 -1
  10. {hypertopos-0.6.0 → hypertopos-0.6.2}/docs/configuration.md +20 -0
  11. {hypertopos-0.6.0 → hypertopos-0.6.2}/hypertopos/builder/builder.py +5721 -5399
  12. {hypertopos-0.6.0 → hypertopos-0.6.2}/hypertopos/builder/mapping.py +72 -0
  13. {hypertopos-0.6.0 → hypertopos-0.6.2}/hypertopos/cli/build.py +19 -0
  14. {hypertopos-0.6.0 → hypertopos-0.6.2}/hypertopos/cli/schema.py +55 -1
  15. hypertopos-0.6.2/hypertopos/engine/adjacency.py +457 -0
  16. {hypertopos-0.6.0 → hypertopos-0.6.2}/hypertopos/engine/edge_features.py +156 -0
  17. {hypertopos-0.6.0 → hypertopos-0.6.2}/hypertopos/engine/hop_predicate.py +221 -90
  18. {hypertopos-0.6.0 → hypertopos-0.6.2}/hypertopos/model/sphere.py +52 -6
  19. {hypertopos-0.6.0 → hypertopos-0.6.2}/hypertopos/navigation/navigator.py +13491 -13284
  20. {hypertopos-0.6.0 → hypertopos-0.6.2}/hypertopos/storage/reader.py +15 -0
  21. {hypertopos-0.6.0 → hypertopos-0.6.2}/hypertopos/storage/writer.py +962 -965
  22. {hypertopos-0.6.0 → hypertopos-0.6.2}/pyproject.toml +1 -1
  23. {hypertopos-0.6.0 → hypertopos-0.6.2}/tests/test_adjacency.py +4 -3
  24. hypertopos-0.6.2/tests/test_adjacency_vectorized.py +202 -0
  25. {hypertopos-0.6.0 → hypertopos-0.6.2}/tests/test_builder.py +3 -3
  26. {hypertopos-0.6.0 → hypertopos-0.6.2}/tests/test_builder_derived.py +1416 -1416
  27. hypertopos-0.6.2/tests/test_distinct_neighbor_count.py +191 -0
  28. hypertopos-0.6.2/tests/test_edge_dim_aggregations.py +173 -0
  29. hypertopos-0.6.2/tests/test_edge_dim_aggregations_builder.py +373 -0
  30. hypertopos-0.6.2/tests/test_edge_dim_aggregations_chain.py +386 -0
  31. hypertopos-0.6.2/tests/test_edge_dim_aggregations_engine.py +303 -0
  32. hypertopos-0.6.2/tests/test_edge_dim_aggregations_roundtrip.py +109 -0
  33. {hypertopos-0.6.0 → hypertopos-0.6.2}/tests/test_edge_potential.py +1 -1
  34. hypertopos-0.6.2/tests/test_find_motif_by_hops.py +470 -0
  35. {hypertopos-0.6.0 → hypertopos-0.6.2}/tests/test_fts.py +5 -7
  36. {hypertopos-0.6.0 → hypertopos-0.6.2}/tests/test_hop_predicate_engine.py +220 -3
  37. {hypertopos-0.6.0 → hypertopos-0.6.2}/tests/test_motif.py +2 -1
  38. hypertopos-0.6.2/tests/test_neighbors_window.py +119 -0
  39. {hypertopos-0.6.0 → hypertopos-0.6.2}/tests/test_root_cause_trace.py +1 -1
  40. hypertopos-0.6.2/tests/test_schema_chain_eda_validation.py +128 -0
  41. {hypertopos-0.6.0 → hypertopos-0.6.2}/tests/test_storage.py +31 -33
  42. {hypertopos-0.6.0 → hypertopos-0.6.2}/tests/test_trajectory_ann.py +4 -2
  43. hypertopos-0.6.0/ROADMAP.md +0 -100
  44. hypertopos-0.6.0/hypertopos/engine/adjacency.py +0 -119
  45. hypertopos-0.6.0/tests/test_find_motif_by_hops.py +0 -130
  46. {hypertopos-0.6.0 → hypertopos-0.6.2}/.github/workflows/publish-pypi.yml +0 -0
  47. {hypertopos-0.6.0 → hypertopos-0.6.2}/.gitignore +0 -0
  48. {hypertopos-0.6.0 → hypertopos-0.6.2}/docs/README.md +0 -0
  49. {hypertopos-0.6.0 → hypertopos-0.6.2}/docs/benchmark/LICENSE +0 -0
  50. {hypertopos-0.6.0 → hypertopos-0.6.2}/docs/benchmark/README.md +0 -0
  51. {hypertopos-0.6.0 → hypertopos-0.6.2}/docs/benchmark/berka/README.md +0 -0
  52. {hypertopos-0.6.0 → hypertopos-0.6.2}/docs/benchmark/berka/results/0.1.0/SUMMARY.md +0 -0
  53. {hypertopos-0.6.0 → hypertopos-0.6.2}/docs/benchmark/berka/results/0.1.0/r1/0.1.0-exp-a-report.md +0 -0
  54. {hypertopos-0.6.0 → hypertopos-0.6.2}/docs/benchmark/berka/results/0.1.0/r1/0.1.0-exp-a-scoring.md +0 -0
  55. {hypertopos-0.6.0 → hypertopos-0.6.2}/docs/benchmark/berka/results/0.1.0/r1/0.1.0-exp-b-report.md +0 -0
  56. {hypertopos-0.6.0 → hypertopos-0.6.2}/docs/benchmark/berka/results/0.1.0/r1/0.1.0-exp-b-scoring.md +0 -0
  57. {hypertopos-0.6.0 → hypertopos-0.6.2}/docs/benchmark/berka/results/0.1.0/r1/0.1.0-settings.md +0 -0
  58. {hypertopos-0.6.0 → hypertopos-0.6.2}/docs/benchmark/berka/results/0.1.0/r2/0.1.0-exp-a-report.md +0 -0
  59. {hypertopos-0.6.0 → hypertopos-0.6.2}/docs/benchmark/berka/results/0.1.0/r2/0.1.0-exp-a-scoring.md +0 -0
  60. {hypertopos-0.6.0 → hypertopos-0.6.2}/docs/benchmark/berka/results/0.1.0/r2/0.1.0-exp-b-report.md +0 -0
  61. {hypertopos-0.6.0 → hypertopos-0.6.2}/docs/benchmark/berka/results/0.1.0/r2/0.1.0-exp-b-scoring.md +0 -0
  62. {hypertopos-0.6.0 → hypertopos-0.6.2}/docs/benchmark/berka/results/0.1.0/r2/0.1.0-settings.md +0 -0
  63. {hypertopos-0.6.0 → hypertopos-0.6.2}/docs/benchmark/berka/results/0.1.0/r3/0.1.0-exp-a-report.md +0 -0
  64. {hypertopos-0.6.0 → hypertopos-0.6.2}/docs/benchmark/berka/results/0.1.0/r3/0.1.0-exp-a-scoring.md +0 -0
  65. {hypertopos-0.6.0 → hypertopos-0.6.2}/docs/benchmark/berka/results/0.1.0/r3/0.1.0-exp-b-report.md +0 -0
  66. {hypertopos-0.6.0 → hypertopos-0.6.2}/docs/benchmark/berka/results/0.1.0/r3/0.1.0-exp-b-scoring.md +0 -0
  67. {hypertopos-0.6.0 → hypertopos-0.6.2}/docs/benchmark/berka/results/0.1.0/r3/0.1.0-settings.md +0 -0
  68. {hypertopos-0.6.0 → hypertopos-0.6.2}/docs/benchmark/berka/results/0.1.0/r4/0.1.0-exp-a-report.md +0 -0
  69. {hypertopos-0.6.0 → hypertopos-0.6.2}/docs/benchmark/berka/results/0.1.0/r4/0.1.0-exp-a-scoring.md +0 -0
  70. {hypertopos-0.6.0 → hypertopos-0.6.2}/docs/benchmark/berka/results/0.1.0/r4/0.1.0-exp-b-report.md +0 -0
  71. {hypertopos-0.6.0 → hypertopos-0.6.2}/docs/benchmark/berka/results/0.1.0/r4/0.1.0-exp-b-scoring.md +0 -0
  72. {hypertopos-0.6.0 → hypertopos-0.6.2}/docs/benchmark/berka/results/0.1.0/r4/0.1.0-settings.md +0 -0
  73. {hypertopos-0.6.0 → hypertopos-0.6.2}/docs/benchmark/berka/results/0.1.0/r5/0.1.0-exp-a-report.md +0 -0
  74. {hypertopos-0.6.0 → hypertopos-0.6.2}/docs/benchmark/berka/results/0.1.0/r5/0.1.0-exp-a-scoring.md +0 -0
  75. {hypertopos-0.6.0 → hypertopos-0.6.2}/docs/benchmark/berka/results/0.1.0/r5/0.1.0-exp-b-report.md +0 -0
  76. {hypertopos-0.6.0 → hypertopos-0.6.2}/docs/benchmark/berka/results/0.1.0/r5/0.1.0-exp-b-scoring.md +0 -0
  77. {hypertopos-0.6.0 → hypertopos-0.6.2}/docs/benchmark/berka/results/0.1.0/r5/0.1.0-settings.md +0 -0
  78. {hypertopos-0.6.0 → hypertopos-0.6.2}/docs/benchmark/berka/results/0.1.0/r6/0.1.0-exp-a-report.md +0 -0
  79. {hypertopos-0.6.0 → hypertopos-0.6.2}/docs/benchmark/berka/results/0.1.0/r6/0.1.0-exp-a-scoring.md +0 -0
  80. {hypertopos-0.6.0 → hypertopos-0.6.2}/docs/benchmark/berka/results/0.1.0/r6/0.1.0-exp-b-report.md +0 -0
  81. {hypertopos-0.6.0 → hypertopos-0.6.2}/docs/benchmark/berka/results/0.1.0/r6/0.1.0-exp-b-scoring.md +0 -0
  82. {hypertopos-0.6.0 → hypertopos-0.6.2}/docs/benchmark/berka/results/0.1.0/r6/0.1.0-settings.md +0 -0
  83. {hypertopos-0.6.0 → hypertopos-0.6.2}/docs/benchmark/berka/sphere/prepare_accounts.py +0 -0
  84. {hypertopos-0.6.0 → hypertopos-0.6.2}/docs/benchmark/berka/sphere/prepare_cpty_banks.py +0 -0
  85. {hypertopos-0.6.0 → hypertopos-0.6.2}/docs/benchmark/berka/sphere/prepare_districts.py +0 -0
  86. {hypertopos-0.6.0 → hypertopos-0.6.2}/docs/benchmark/berka/sphere/prepare_loan_accounts.py +0 -0
  87. {hypertopos-0.6.0 → hypertopos-0.6.2}/docs/benchmark/berka/sphere/prepare_operations.py +0 -0
  88. {hypertopos-0.6.0 → hypertopos-0.6.2}/docs/benchmark/berka/sphere/prepare_orders.py +0 -0
  89. {hypertopos-0.6.0 → hypertopos-0.6.2}/docs/benchmark/berka/sphere/prepare_transactions.py +0 -0
  90. {hypertopos-0.6.0 → hypertopos-0.6.2}/docs/benchmark/berka/sphere/prepare_tx_types.py +0 -0
  91. {hypertopos-0.6.0 → hypertopos-0.6.2}/docs/benchmark/berka/sphere/sphere.yaml +0 -0
  92. {hypertopos-0.6.0 → hypertopos-0.6.2}/docs/benchmark/ibm-aml/README.md +0 -0
  93. {hypertopos-0.6.0 → hypertopos-0.6.2}/docs/benchmark/ibm-aml/_layer2_cross_eval.py +0 -0
  94. {hypertopos-0.6.0 → hypertopos-0.6.2}/docs/benchmark/ibm-aml/_layer3_cross_eval.py +0 -0
  95. {hypertopos-0.6.0 → hypertopos-0.6.2}/docs/benchmark/ibm-aml/hi_small_sphere/prepare_accounts.py +0 -0
  96. {hypertopos-0.6.0 → hypertopos-0.6.2}/docs/benchmark/ibm-aml/hi_small_sphere/prepare_currencies.py +0 -0
  97. {hypertopos-0.6.0 → hypertopos-0.6.2}/docs/benchmark/ibm-aml/hi_small_sphere/prepare_payment_formats.py +0 -0
  98. {hypertopos-0.6.0 → hypertopos-0.6.2}/docs/benchmark/ibm-aml/hi_small_sphere/prepare_transactions.py +0 -0
  99. {hypertopos-0.6.0 → hypertopos-0.6.2}/docs/benchmark/ibm-aml/hi_small_sphere/sphere.yaml +0 -0
  100. {hypertopos-0.6.0 → hypertopos-0.6.2}/docs/benchmark/ibm-aml/layer1_passive_scan.py +0 -0
  101. {hypertopos-0.6.0 → hypertopos-0.6.2}/docs/benchmark/ibm-aml/layer2_xgboost_sweep.py +0 -0
  102. {hypertopos-0.6.0 → hypertopos-0.6.2}/docs/benchmark/ibm-aml/layer3_typology_filter.py +0 -0
  103. {hypertopos-0.6.0 → hypertopos-0.6.2}/docs/benchmark/ibm-aml/li_small_sphere/prepare_accounts.py +0 -0
  104. {hypertopos-0.6.0 → hypertopos-0.6.2}/docs/benchmark/ibm-aml/li_small_sphere/prepare_currencies.py +0 -0
  105. {hypertopos-0.6.0 → hypertopos-0.6.2}/docs/benchmark/ibm-aml/li_small_sphere/prepare_payment_formats.py +0 -0
  106. {hypertopos-0.6.0 → hypertopos-0.6.2}/docs/benchmark/ibm-aml/li_small_sphere/prepare_transactions.py +0 -0
  107. {hypertopos-0.6.0 → hypertopos-0.6.2}/docs/benchmark/ibm-aml/li_small_sphere/sphere.yaml +0 -0
  108. {hypertopos-0.6.0 → hypertopos-0.6.2}/docs/benchmark/ibm-aml/passive-scan-calibration.md +0 -0
  109. {hypertopos-0.6.0 → hypertopos-0.6.2}/docs/benchmark/nyc-taxi/README.md +0 -0
  110. {hypertopos-0.6.0 → hypertopos-0.6.2}/docs/benchmark/nyc-taxi/results/0.1.0/SUMMARY.md +0 -0
  111. {hypertopos-0.6.0 → hypertopos-0.6.2}/docs/benchmark/nyc-taxi/results/0.1.0/r1/0.1.0-exp-a-report.md +0 -0
  112. {hypertopos-0.6.0 → hypertopos-0.6.2}/docs/benchmark/nyc-taxi/results/0.1.0/r1/0.1.0-exp-a-scoring.md +0 -0
  113. {hypertopos-0.6.0 → hypertopos-0.6.2}/docs/benchmark/nyc-taxi/results/0.1.0/r1/0.1.0-exp-b-report.md +0 -0
  114. {hypertopos-0.6.0 → hypertopos-0.6.2}/docs/benchmark/nyc-taxi/results/0.1.0/r1/0.1.0-exp-b-scoring.md +0 -0
  115. {hypertopos-0.6.0 → hypertopos-0.6.2}/docs/benchmark/nyc-taxi/results/0.1.0/r1/0.1.0-exp-c-report.md +0 -0
  116. {hypertopos-0.6.0 → hypertopos-0.6.2}/docs/benchmark/nyc-taxi/results/0.1.0/r1/0.1.0-settings.md +0 -0
  117. {hypertopos-0.6.0 → hypertopos-0.6.2}/docs/benchmark/nyc-taxi/results/0.1.0/r2/0.1.0-exp-a-report.md +0 -0
  118. {hypertopos-0.6.0 → hypertopos-0.6.2}/docs/benchmark/nyc-taxi/results/0.1.0/r2/0.1.0-exp-a-scoring.md +0 -0
  119. {hypertopos-0.6.0 → hypertopos-0.6.2}/docs/benchmark/nyc-taxi/results/0.1.0/r2/0.1.0-exp-b-report.md +0 -0
  120. {hypertopos-0.6.0 → hypertopos-0.6.2}/docs/benchmark/nyc-taxi/results/0.1.0/r2/0.1.0-exp-b-scoring.md +0 -0
  121. {hypertopos-0.6.0 → hypertopos-0.6.2}/docs/benchmark/nyc-taxi/results/0.1.0/r2/0.1.0-exp-c-report.md +0 -0
  122. {hypertopos-0.6.0 → hypertopos-0.6.2}/docs/benchmark/nyc-taxi/results/0.1.0/r2/0.1.0-settings.md +0 -0
  123. {hypertopos-0.6.0 → hypertopos-0.6.2}/docs/benchmark/nyc-taxi/results/0.1.0/r3/0.1.0-exp-a-report.md +0 -0
  124. {hypertopos-0.6.0 → hypertopos-0.6.2}/docs/benchmark/nyc-taxi/results/0.1.0/r3/0.1.0-exp-a-scoring.md +0 -0
  125. {hypertopos-0.6.0 → hypertopos-0.6.2}/docs/benchmark/nyc-taxi/results/0.1.0/r3/0.1.0-exp-b-report.md +0 -0
  126. {hypertopos-0.6.0 → hypertopos-0.6.2}/docs/benchmark/nyc-taxi/results/0.1.0/r3/0.1.0-exp-b-scoring.md +0 -0
  127. {hypertopos-0.6.0 → hypertopos-0.6.2}/docs/benchmark/nyc-taxi/results/0.1.0/r3/0.1.0-exp-c-report.md +0 -0
  128. {hypertopos-0.6.0 → hypertopos-0.6.2}/docs/benchmark/nyc-taxi/results/0.1.0/r3/0.1.0-settings.md +0 -0
  129. {hypertopos-0.6.0 → hypertopos-0.6.2}/docs/benchmark/nyc-taxi/sphere/prepare_trips.py +0 -0
  130. {hypertopos-0.6.0 → hypertopos-0.6.2}/docs/benchmark/nyc-taxi/sphere/sphere.yaml +0 -0
  131. {hypertopos-0.6.0 → hypertopos-0.6.2}/docs/benchmarks.md +0 -0
  132. {hypertopos-0.6.0 → hypertopos-0.6.2}/docs/data-format.md +0 -0
  133. {hypertopos-0.6.0 → hypertopos-0.6.2}/docs/images/build-pipeline.svg +0 -0
  134. {hypertopos-0.6.0 → hypertopos-0.6.2}/docs/images/core-objects.svg +0 -0
  135. {hypertopos-0.6.0 → hypertopos-0.6.2}/docs/images/cutting-plane.svg +0 -0
  136. {hypertopos-0.6.0 → hypertopos-0.6.2}/docs/images/directory-layout.svg +0 -0
  137. {hypertopos-0.6.0 → hypertopos-0.6.2}/docs/images/hypertopos-overview.svg +0 -0
  138. {hypertopos-0.6.0 → hypertopos-0.6.2}/docs/images/model-lifecycle.svg +0 -0
  139. {hypertopos-0.6.0 → hypertopos-0.6.2}/docs/images/navigation-primitives.svg +0 -0
  140. {hypertopos-0.6.0 → hypertopos-0.6.2}/docs/images/three-scales.svg +0 -0
  141. {hypertopos-0.6.0 → hypertopos-0.6.2}/docs/introduction.md +0 -0
  142. {hypertopos-0.6.0 → hypertopos-0.6.2}/docs/quickstart.md +0 -0
  143. {hypertopos-0.6.0 → hypertopos-0.6.2}/hypertopos/__init__.py +0 -0
  144. {hypertopos-0.6.0 → hypertopos-0.6.2}/hypertopos/builder/__init__.py +0 -0
  145. {hypertopos-0.6.0 → hypertopos-0.6.2}/hypertopos/builder/_bootstrap.py +0 -0
  146. {hypertopos-0.6.0 → hypertopos-0.6.2}/hypertopos/builder/_bregman.py +0 -0
  147. {hypertopos-0.6.0 → hypertopos-0.6.2}/hypertopos/builder/_scatter.py +0 -0
  148. {hypertopos-0.6.0 → hypertopos-0.6.2}/hypertopos/builder/_stats.py +0 -0
  149. {hypertopos-0.6.0 → hypertopos-0.6.2}/hypertopos/builder/_writer.py +0 -0
  150. {hypertopos-0.6.0 → hypertopos-0.6.2}/hypertopos/builder/derived.py +0 -0
  151. {hypertopos-0.6.0 → hypertopos-0.6.2}/hypertopos/builder/dim_blocks.py +0 -0
  152. {hypertopos-0.6.0 → hypertopos-0.6.2}/hypertopos/cli/__init__.py +0 -0
  153. {hypertopos-0.6.0 → hypertopos-0.6.2}/hypertopos/cli/__main__.py +0 -0
  154. {hypertopos-0.6.0 → hypertopos-0.6.2}/hypertopos/cli/info.py +0 -0
  155. {hypertopos-0.6.0 → hypertopos-0.6.2}/hypertopos/cli/main.py +0 -0
  156. {hypertopos-0.6.0 → hypertopos-0.6.2}/hypertopos/cli/sources.py +0 -0
  157. {hypertopos-0.6.0 → hypertopos-0.6.2}/hypertopos/engine/__init__.py +0 -0
  158. {hypertopos-0.6.0 → hypertopos-0.6.2}/hypertopos/engine/aggregation.py +0 -0
  159. {hypertopos-0.6.0 → hypertopos-0.6.2}/hypertopos/engine/calibration.py +0 -0
  160. {hypertopos-0.6.0 → hypertopos-0.6.2}/hypertopos/engine/chains.py +0 -0
  161. {hypertopos-0.6.0 → hypertopos-0.6.2}/hypertopos/engine/composition.py +0 -0
  162. {hypertopos-0.6.0 → hypertopos-0.6.2}/hypertopos/engine/density_gaps.py +0 -0
  163. {hypertopos-0.6.0 → hypertopos-0.6.2}/hypertopos/engine/fdr.py +0 -0
  164. {hypertopos-0.6.0 → hypertopos-0.6.2}/hypertopos/engine/forecast.py +0 -0
  165. {hypertopos-0.6.0 → hypertopos-0.6.2}/hypertopos/engine/geometry.py +0 -0
  166. {hypertopos-0.6.0 → hypertopos-0.6.2}/hypertopos/engine/graph_algorithms.py +0 -0
  167. {hypertopos-0.6.0 → hypertopos-0.6.2}/hypertopos/engine/heredity.py +0 -0
  168. {hypertopos-0.6.0 → hypertopos-0.6.2}/hypertopos/engine/invalidation.py +0 -0
  169. {hypertopos-0.6.0 → hypertopos-0.6.2}/hypertopos/engine/investigation.py +0 -0
  170. {hypertopos-0.6.0 → hypertopos-0.6.2}/hypertopos/engine/lance_sql_agg.py +0 -0
  171. {hypertopos-0.6.0 → hypertopos-0.6.2}/hypertopos/engine/selection.py +0 -0
  172. {hypertopos-0.6.0 → hypertopos-0.6.2}/hypertopos/engine/structuring.py +0 -0
  173. {hypertopos-0.6.0 → hypertopos-0.6.2}/hypertopos/model/__init__.py +0 -0
  174. {hypertopos-0.6.0 → hypertopos-0.6.2}/hypertopos/model/manifest.py +0 -0
  175. {hypertopos-0.6.0 → hypertopos-0.6.2}/hypertopos/model/objects.py +0 -0
  176. {hypertopos-0.6.0 → hypertopos-0.6.2}/hypertopos/navigation/__init__.py +0 -0
  177. {hypertopos-0.6.0 → hypertopos-0.6.2}/hypertopos/navigation/scanner.py +0 -0
  178. {hypertopos-0.6.0 → hypertopos-0.6.2}/hypertopos/sphere.py +0 -0
  179. {hypertopos-0.6.0 → hypertopos-0.6.2}/hypertopos/storage/__init__.py +0 -0
  180. {hypertopos-0.6.0 → hypertopos-0.6.2}/hypertopos/storage/_schemas.py +0 -0
  181. {hypertopos-0.6.0 → hypertopos-0.6.2}/hypertopos/storage/cache.py +0 -0
  182. {hypertopos-0.6.0 → hypertopos-0.6.2}/hypertopos/storage/calibration_history.py +0 -0
  183. {hypertopos-0.6.0 → hypertopos-0.6.2}/hypertopos/utils/__init__.py +0 -0
  184. {hypertopos-0.6.0 → hypertopos-0.6.2}/hypertopos/utils/arrow.py +0 -0
  185. {hypertopos-0.6.0 → hypertopos-0.6.2}/tests/.gitkeep +0 -0
  186. {hypertopos-0.6.0 → hypertopos-0.6.2}/tests/conftest.py +0 -0
  187. {hypertopos-0.6.0 → hypertopos-0.6.2}/tests/fixtures/generate_fixtures.py +0 -0
  188. {hypertopos-0.6.0 → hypertopos-0.6.2}/tests/test_aggregation_engine.py +0 -0
  189. {hypertopos-0.6.0 → hypertopos-0.6.2}/tests/test_arrow_utils.py +0 -0
  190. {hypertopos-0.6.0 → hypertopos-0.6.2}/tests/test_bootstrap.py +0 -0
  191. {hypertopos-0.6.0 → hypertopos-0.6.2}/tests/test_bregman.py +0 -0
  192. {hypertopos-0.6.0 → hypertopos-0.6.2}/tests/test_builder_alias.py +0 -0
  193. {hypertopos-0.6.0 → hypertopos-0.6.2}/tests/test_builder_chunking.py +0 -0
  194. {hypertopos-0.6.0 → hypertopos-0.6.2}/tests/test_builder_contagion.py +0 -0
  195. {hypertopos-0.6.0 → hypertopos-0.6.2}/tests/test_builder_edges.py +0 -0
  196. {hypertopos-0.6.0 → hypertopos-0.6.2}/tests/test_builder_rolling_z.py +0 -0
  197. {hypertopos-0.6.0 → hypertopos-0.6.2}/tests/test_builder_scatter.py +0 -0
  198. {hypertopos-0.6.0 → hypertopos-0.6.2}/tests/test_builder_temporal_perf.py +0 -0
  199. {hypertopos-0.6.0 → hypertopos-0.6.2}/tests/test_cache.py +0 -0
  200. {hypertopos-0.6.0 → hypertopos-0.6.2}/tests/test_calibration.py +0 -0
  201. {hypertopos-0.6.0 → hypertopos-0.6.2}/tests/test_calibration_drift.py +0 -0
  202. {hypertopos-0.6.0 → hypertopos-0.6.2}/tests/test_calibration_history.py +0 -0
  203. {hypertopos-0.6.0 → hypertopos-0.6.2}/tests/test_calibration_history_builder.py +0 -0
  204. {hypertopos-0.6.0 → hypertopos-0.6.2}/tests/test_calibration_history_reader.py +0 -0
  205. {hypertopos-0.6.0 → hypertopos-0.6.2}/tests/test_chains.py +0 -0
  206. {hypertopos-0.6.0 → hypertopos-0.6.2}/tests/test_cli.py +0 -0
  207. {hypertopos-0.6.0 → hypertopos-0.6.2}/tests/test_cli_alias.py +0 -0
  208. {hypertopos-0.6.0 → hypertopos-0.6.2}/tests/test_cli_sources.py +0 -0
  209. {hypertopos-0.6.0 → hypertopos-0.6.2}/tests/test_compaction.py +0 -0
  210. {hypertopos-0.6.0 → hypertopos-0.6.2}/tests/test_composition.py +0 -0
  211. {hypertopos-0.6.0 → hypertopos-0.6.2}/tests/test_continuous_event_dims.py +0 -0
  212. {hypertopos-0.6.0 → hypertopos-0.6.2}/tests/test_data_quality_prop.py +0 -0
  213. {hypertopos-0.6.0 → hypertopos-0.6.2}/tests/test_decompose_drift.py +0 -0
  214. {hypertopos-0.6.0 → hypertopos-0.6.2}/tests/test_density_gaps_engine.py +0 -0
  215. {hypertopos-0.6.0 → hypertopos-0.6.2}/tests/test_detection.py +0 -0
  216. {hypertopos-0.6.0 → hypertopos-0.6.2}/tests/test_dim_blocks.py +0 -0
  217. {hypertopos-0.6.0 → hypertopos-0.6.2}/tests/test_edge_dimensions_builder.py +0 -0
  218. {hypertopos-0.6.0 → hypertopos-0.6.2}/tests/test_edge_dimensions_yaml.py +0 -0
  219. {hypertopos-0.6.0 → hypertopos-0.6.2}/tests/test_edge_features.py +0 -0
  220. {hypertopos-0.6.0 → hypertopos-0.6.2}/tests/test_edge_features_reader.py +0 -0
  221. {hypertopos-0.6.0 → hypertopos-0.6.2}/tests/test_edge_table.py +0 -0
  222. {hypertopos-0.6.0 → hypertopos-0.6.2}/tests/test_engine.py +0 -0
  223. {hypertopos-0.6.0 → hypertopos-0.6.2}/tests/test_fdr.py +0 -0
  224. {hypertopos-0.6.0 → hypertopos-0.6.2}/tests/test_find_calibration_influencers.py +0 -0
  225. {hypertopos-0.6.0 → hypertopos-0.6.2}/tests/test_find_density_gaps.py +0 -0
  226. {hypertopos-0.6.0 → hypertopos-0.6.2}/tests/test_find_lead_lag.py +0 -0
  227. {hypertopos-0.6.0 → hypertopos-0.6.2}/tests/test_find_lead_lag_significance.py +0 -0
  228. {hypertopos-0.6.0 → hypertopos-0.6.2}/tests/test_forecast.py +0 -0
  229. {hypertopos-0.6.0 → hypertopos-0.6.2}/tests/test_geometric_path.py +0 -0
  230. {hypertopos-0.6.0 → hypertopos-0.6.2}/tests/test_geometry_stats.py +0 -0
  231. {hypertopos-0.6.0 → hypertopos-0.6.2}/tests/test_gradient_alignment.py +0 -0
  232. {hypertopos-0.6.0 → hypertopos-0.6.2}/tests/test_graph_algorithms.py +0 -0
  233. {hypertopos-0.6.0 → hypertopos-0.6.2}/tests/test_heredity.py +0 -0
  234. {hypertopos-0.6.0 → hypertopos-0.6.2}/tests/test_hybrid_search.py +0 -0
  235. {hypertopos-0.6.0 → hypertopos-0.6.2}/tests/test_incremental.py +0 -0
  236. {hypertopos-0.6.0 → hypertopos-0.6.2}/tests/test_invalidation.py +0 -0
  237. {hypertopos-0.6.0 → hypertopos-0.6.2}/tests/test_investigation.py +0 -0
  238. {hypertopos-0.6.0 → hypertopos-0.6.2}/tests/test_kind_detect.py +0 -0
  239. {hypertopos-0.6.0 → hypertopos-0.6.2}/tests/test_lance_sql_agg.py +0 -0
  240. {hypertopos-0.6.0 → hypertopos-0.6.2}/tests/test_mapping.py +0 -0
  241. {hypertopos-0.6.0 → hypertopos-0.6.2}/tests/test_model.py +0 -0
  242. {hypertopos-0.6.0 → hypertopos-0.6.2}/tests/test_mvcc_session.py +0 -0
  243. {hypertopos-0.6.0 → hypertopos-0.6.2}/tests/test_navigation.py +0 -0
  244. {hypertopos-0.6.0 → hypertopos-0.6.2}/tests/test_navigator_alerts.py +0 -0
  245. {hypertopos-0.6.0 → hypertopos-0.6.2}/tests/test_navigator_fdr_select.py +0 -0
  246. {hypertopos-0.6.0 → hypertopos-0.6.2}/tests/test_observability.py +0 -0
  247. {hypertopos-0.6.0 → hypertopos-0.6.2}/tests/test_precision_stack.py +0 -0
  248. {hypertopos-0.6.0 → hypertopos-0.6.2}/tests/test_profile_motif_perf_smoke.py +0 -0
  249. {hypertopos-0.6.0 → hypertopos-0.6.2}/tests/test_reputation.py +0 -0
  250. {hypertopos-0.6.0 → hypertopos-0.6.2}/tests/test_row_id_cache.py +0 -0
  251. {hypertopos-0.6.0 → hypertopos-0.6.2}/tests/test_scanner.py +0 -0
  252. {hypertopos-0.6.0 → hypertopos-0.6.2}/tests/test_selection.py +0 -0
  253. {hypertopos-0.6.0 → hypertopos-0.6.2}/tests/test_sphere.py +0 -0
  254. {hypertopos-0.6.0 → hypertopos-0.6.2}/tests/test_sphere_overview_perf.py +0 -0
  255. {hypertopos-0.6.0 → hypertopos-0.6.2}/tests/test_stats_guard.py +0 -0
  256. {hypertopos-0.6.0 → hypertopos-0.6.2}/tests/test_streaming_reads.py +0 -0
  257. {hypertopos-0.6.0 → hypertopos-0.6.2}/tests/test_structuring_engine.py +0 -0
  258. {hypertopos-0.6.0 → hypertopos-0.6.2}/tests/test_temporal_centroids.py +0 -0
  259. {hypertopos-0.6.0 → hypertopos-0.6.2}/tests/test_witness_cohort.py +0 -0
  260. {hypertopos-0.6.0 → hypertopos-0.6.2}/tests/test_witness_set.py +0 -0
@@ -7,6 +7,194 @@ Versioning follows [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [0.6.2] — 2026-05-05
11
+
12
+ ### Added
13
+ - Chain-anchor `edge_dim_aggregations:` regime — third `anchor_kind`
14
+ alongside `single` (account-style) and `pair` (k=2 composite). Chain
15
+ anchor patterns auto-emitted from `chain_lines:` config can declare
16
+ `edge_dim_aggregations: { from: <event_pid>, dims: [...] }` directly
17
+ in the `chain_lines.<id>:` block; the builder forwards it to the
18
+ auto-emitted `<id>_pattern`. Aggregation reads the source event
19
+ pattern's edge_features sidecar and bakes per-chain `<source_dim>_mean`
20
+ and `<source_dim>_max` columns into the chain anchor polygon's
21
+ `shape_snapshot`. New `_chain_lines: set[str]` registry on `GDSBuilder`
22
+ for regime detection. `aggregate_edge_dims_for_anchor` gains a
23
+ `chain_events: list[str] | None` keyword for the chain regime
24
+ (comma-joined event_keys per anchor; engine performs explosion + join
25
+ + groupby). Cross-block parse-time validation enforces
26
+ `chain_lines.<id>.event_line == src_pat.edge_table.event_line`;
27
+ zero-extracted-chains with declared aggregations raise loudly at
28
+ build dispatch. Sphere format stays at 2.4 — `chain_events` property
29
+ column on the chain anchor line is the existing membership source.
30
+ Aggregated dims surface automatically in every existing anchor-pattern
31
+ primitive (`find_anomalies`, `explain_anomaly`, `find_clusters`,
32
+ `find_calibration_influencers`, `decompose_drift`) via
33
+ `dimension_kinds` source-of-truth — no new tools, no MCP API change.
34
+
35
+ ### Added
36
+ - `AdjacencyIndex.neighbors_out_window` and
37
+ `AdjacencyIndex.neighbors_in_window` — column-selective neighbor
38
+ accessors. Return a per-column dict (`{col: list[Any]}`) for any subset
39
+ of `("to_key" / "from_key", "timestamp", "amount", "event_key")` with
40
+ an optional `ts_min` window predicate applied at the pyarrow C++ layer
41
+ before materialization. Useful for callers that need only key + timestamp
42
+ without paying the cost of materializing `amount` / `event_key`.
43
+ - `AdjacencyIndex.distinct_neighbors_out`,
44
+ `AdjacencyIndex.distinct_neighbors_in`, and
45
+ `AdjacencyIndex.max_amount_out_excl_self` — O(1) public accessors over
46
+ precomputed per-`from_key` aggregates (distinct-out-neighbor count,
47
+ distinct-in-neighbor count, max-amount-excluding-self). Self-loop
48
+ semantics preserved; null amounts skipped.
49
+
50
+ ### Fixed
51
+ - Cold-call latency on motif enumeration tools (`find_high_potential_motifs`,
52
+ `score_motif`, `find_motif_by_hops`) reduced across `bipartite_burst`,
53
+ `fan_out`, `fan_in`, and `cycle_2` motif types. No public API change.
54
+ - `AdjacencyIndex.pair_counts()` first-call cost on hub-graph workloads
55
+ reduced. The aggregate is now precomputed at adjacency build time and
56
+ surfaced in O(1) on first call. Self-loop semantics preserved
57
+ (`pair_counts` includes self-pairs; distinct counts skip them).
58
+
59
+ ### Changed
60
+ - `AdjacencyIndex` cold load path is faster on edge-table-backed
61
+ patterns; motif tools' first-call latency drops materially. No format
62
+ bump, no persisted artifact, no public API change — every public method
63
+ (`neighbors_out`, `neighbors_in`, `degree_out`, `degree_in`, `all_nodes`,
64
+ `all_edges`, `node_count`, `edge_count`, `pair_counts`) preserves its
65
+ signature and observable behavior.
66
+
67
+ ## [0.6.1] — 2026-05-01
68
+
69
+ ### Fixed
70
+ - `find_motif_by_hops` `score=True` now functional on event patterns. The
71
+ scoring branch was previously dead code (gated on
72
+ `pattern_type != "event"`, but the function rejects non-event patterns
73
+ upstream), so passing `score=True` had no observable effect since the
74
+ declarative motif API shipped. Scoring now resolves the event pattern's
75
+ anchor companion via `_resolve_anchor_pattern_for_scoring` and uses the
76
+ anchor pattern's per-entity geometry (entity-level deltas) rather than
77
+ the event pattern's per-transaction polygons. Each scored motif carries
78
+ a new `anchor_pattern_id` provenance field. Raises `GDSNavigationError`
79
+ when no anchor companion is configured for the event pattern; per-motif
80
+ scoring failures (endpoint missing in anchor geometry) leave the motif
81
+ unscored without breaking the call. Output ordering: descending on
82
+ score, unscored motifs at tail.
83
+ - Motif scoring kernel (`_score_motif_from_edges`, `_lean_score_motif`)
84
+ now event-aware via opt-in `event_keys` + `event_pattern_id` arguments.
85
+ Previously `edge_potential = delta_distance × (1/effective_pair_count)`
86
+ depended only on the node pair, so multiple distinct transactions
87
+ between the same `(from, to)` accounts produced identical motif scores
88
+ — turning ranked `find_motif_by_hops(score=True)` output into "5–10
89
+ distinct ranks with the rest as ties" whenever motifs shared a node
90
+ sequence. With the new arguments the kernel batch-reads the event
91
+ pattern's per-event polygons and multiplies each edge's potential by
92
+ `(1 + ||event_polygon[event_key]||)`; events sitting at the population
93
+ centroid (norm 0) keep the legacy score, anomalous events boost above.
94
+ Per-edge `score_breakdown` carries a new `event_factor` field when
95
+ event-aware. Backward compatible: legacy callers (`score_motif`,
96
+ `find_high_potential_motifs`, any external caller of
97
+ `_score_motif_from_edges` without event_keys) see unchanged scores.
98
+ `find_motif_by_hops` passes both arguments automatically and hoists
99
+ both anchor and event delta reads out of the per-motif loop (one
100
+ batched scan per pattern across the union of all motifs, vs.
101
+ per-motif reads pre-hoist) so the per-call I/O cost stays O(1) in
102
+ motif count.
103
+ - `Pattern.dim_labels` and `Pattern.delta_dim()` now include aggregated
104
+ edge-dim names from `edge_dim_aggregations` so callers don't see a
105
+ stale 33-element view of a 37-element delta. Previously the property
106
+ returned only `relations + event_dimensions + prop_columns` — but the
107
+ builder appends `(source_dim)_mean` and `(source_dim)_max` columns to
108
+ the polygon delta when an anchor pattern declares
109
+ `edge_dim_aggregations: { from: <event>, dims: [...] }`. The mismatch
110
+ produced two visible failure classes on patterns with aggregations
111
+ declared:
112
+ - `anomaly_summary` raised `operands could not be broadcast together
113
+ with shapes (33,) (37,) (33,)` because `dim_sq_totals` was sized
114
+ from `len(pattern.dim_labels)` (33) but cluster delta vectors had
115
+ length 37 (33 base + 4 aggregated).
116
+ - `find_clusters.dim_profile`, `find_anomalies.anomaly_dimensions`,
117
+ `explain_anomaly` top-dim labels, `contrast_populations`
118
+ effect-size labels and other label-resolving paths returned
119
+ `dim_35` / `dim_36` placeholders for the aggregated dims instead
120
+ of the build-time names (`find_motif_structuring_mean`,
121
+ `pair_edge_count_max`, etc.).
122
+ Both classes are resolved by the model property fix; the aggregated
123
+ name convention follows `f"{source_dim}_{agg}"` for each
124
+ `agg ∈ AGGREGATE_NAMES = ("mean", "max")` in
125
+ `engine/edge_features.py`. `parse_edge_dim_aggregations` now requires
126
+ `dims` to be a non-empty list — the previous `dims=None` shorthand
127
+ ("aggregate every applicable dim") was a latent build-vs-runtime
128
+ inconsistency: builder appended columns from the source event
129
+ pattern, but the runtime model had no record of which columns. Users
130
+ must now declare dims explicitly. Backward compatible for spheres
131
+ with explicit `dims:` on disk (AML HI-small etc.); spheres that
132
+ somehow built with `dims=None` fail loudly at re-load and need a
133
+ rebuild with explicit declaration. Closes the F1.d follow-up
134
+ (human-readable aggregated-dim labels) and the F6 stress-test
135
+ wildcard for the broadcast regression.
136
+
137
+ ### Changed
138
+ - `find_motif_by_hops` engine: replaced the recursive DFS walk with an
139
+ iterative BFS-by-level enumerator. Lifts the per-call hop count cap
140
+ from 6 to 8 (matches the `chain_k` motif vocabulary). Adds an optional
141
+ `time_window_hours: float | None` top-level parameter for total-
142
+ chain-span cap (independent semantic from per-hop
143
+ `time_delta_max_hours`; both apply when both are set). API surface
144
+ preserved: same enumeration output shape, all existing tests pass.
145
+ Cites the Paranjape-Benson-Leskovec delta-temporal motif algorithm as
146
+ prior art for sliding-window enumeration; the implementation is a
147
+ pragmatic level-synchronous BFS (PBL counts fixed-template motifs
148
+ without per-edge predicates, which does not fit the enumerate-with-
149
+ arbitrary-predicates use case).
150
+
151
+ ### Added
152
+ - `HopPredicate.require_anomalous_entity: bool` — new per-hop predicate
153
+ field for the declarative motif API (closes the X1 predicate set
154
+ alongside `amount_ratio_to_prev`). When `True` on hop `i`, the
155
+ destination entity (`nodes[i+1]` of the resulting motif) must satisfy
156
+ `is_anomaly=True` in the resolved anchor companion pattern's geometry.
157
+ Multiple hops can set this independently; constraints AND across hops.
158
+ Filter runs at the navigator layer after BFS enumeration but before
159
+ scoring (saves scoring work on motifs that get dropped). The seed
160
+ (`nodes[0]`) is never checked — pre-filter `seed_keys` upfront if seed
161
+ coverage is needed. `max_results` applies AFTER the filter, so a
162
+ restrictive filter can return fewer than `max_results` motifs. Raises
163
+ `GDSNavigationError` when no anchor companion is configured for the
164
+ queried event pattern, or when the anchor pattern has no `is_anomaly`
165
+ column (calibration must run first). Default `False` is a no-op,
166
+ preserving prior behavior. Reuses the same anchor-companion lookup
167
+ wired by F5; no sphere format change, no rebuild required.
168
+ - `HopPredicate.amount_ratio_to_prev: float | None` — new per-hop predicate
169
+ field for the declarative motif API. When set on hop `i ≥ 1`, the engine
170
+ rejects a candidate edge unless `current_amount / prev_hop_amount ≤
171
+ ratio`. Bounds `0 < ratio ≤ 1.0` enforced at validation; `hops[0]` must
172
+ leave the field None (no previous amount). Edges where either amount is
173
+ ≤ 0 are silently skipped, matching the existing `find_motif_structuring`
174
+ convention. Use case: declarative structuring / layering chain detection
175
+ without baking absolute amount thresholds (`amount_min` / `amount_max`).
176
+ - Anchor-pattern aggregation of edge-derived dimensions (S1 extension).
177
+ An anchor pattern can declare `edge_dim_aggregations: { from: <event_pid>, dims: [...] }`
178
+ in its YAML stanza; the builder reads the event pattern's edge_features
179
+ sidecar and bakes per-anchor-entity `_mean` and `_max` aggregates of
180
+ the named source dims into the anchor polygon's `shape_snapshot`.
181
+ Aggregation handles two anchor regimes — `single` (anchor PK matches
182
+ edge `from_key` OR `to_key`, account-style) and `pair` (anchor PK
183
+ encoded as `<from>__<to>`, composite-pair-style); chain anchors
184
+ raise `NotImplementedError` and ship in 0.6.2. New
185
+ `EdgeDimAggregationsConfig` builder dataclass, `EdgeDimAggregationsRef`
186
+ runtime dataclass on `Pattern`, and
187
+ `engine.edge_features.aggregate_edge_dims_for_anchor` engine entry
188
+ point. Builder switches to a two-phase build (event patterns first,
189
+ anchor patterns second) when any pattern declares
190
+ `edge_dim_aggregations` so the sidecar dependency holds without a
191
+ topo sort. New aggregated dims surface automatically in every
192
+ existing anchor-pattern primitive (`find_anomalies`,
193
+ `explain_anomaly`, `find_clusters`, `find_calibration_influencers`,
194
+ `decompose_drift`) via the `dimension_kinds` source-of-truth — no
195
+ new tools, no MCP API change. Sphere format stays at 2.4; spheres
196
+ without the new YAML block are byte-identical.
197
+
10
198
  ## [0.6.0] — 2026-04-30
11
199
 
12
200
  ### Theme
@@ -26,7 +26,7 @@ For purposes of this License:
26
26
  - **Internal use** within an organization is not a competitive offering. Your
27
27
  organization includes entities under common control.
28
28
 
29
- **Change Date:** 2029-04-30
29
+ **Change Date:** 2029-05-05
30
30
 
31
31
  **Change License:** Apache License, Version 2.0
32
32
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: hypertopos
3
- Version: 0.6.0
3
+ Version: 0.6.2
4
4
  Summary: Understand the structure of your data — without training machine learning models
5
5
  Project-URL: Homepage, https://github.com/hypertopos/hypertopos-py
6
6
  Project-URL: Documentation, https://github.com/hypertopos/hypertopos-py/tree/main/docs
@@ -8,7 +8,7 @@
8
8
  [![PyArrow](https://img.shields.io/badge/format-PyArrow-red.svg)](https://arrow.apache.org/docs/python/)
9
9
  [![Lance](https://img.shields.io/badge/storage-Lance-blueviolet.svg)](https://github.com/lance-format/lance)
10
10
  [![MCP](https://img.shields.io/badge/MCP-compatible-green.svg)](https://modelcontextprotocol.io)
11
- [![Version](https://img.shields.io/badge/version-0.6.0-%235500FF.svg)](pyproject.toml)
11
+ [![Version](https://img.shields.io/badge/version-0.6.2-%235500FF.svg)](pyproject.toml)
12
12
 
13
13
  hypertopos is not a database, and not a machine learning model. It is a layer that turns relational data into a coordinate system where every entity gets a position derived from its relationships and the population around it.
14
14
 
@@ -59,6 +59,16 @@ Each capability below emerges from treating entities as points in a shared, popu
59
59
  | Structural motif scoring | Product of `edge_potential` across closed-vocab motifs (fan_out, cycle_2, cycle_3, structuring) | Graph DB motif matching has no geometric rarity score | `0.5.0` |
60
60
  | Extended motif catalog | `fan_in` (sink-centric concentrator) and `chain_k` (open directed chain, 3 ≤ k ≤ 8) extend the motif vocabulary; window-filter correctness fix on fan_out/cycle_2/cycle_3 | Prior motifs silently ignored declared `time_window_hours` in production | `0.5.1` |
61
61
  | Bipartite motif catalog | `split_recombine` (diamond scatter-gather S → k intermediaries → D, forward/backward seed anchoring) and `bipartite_burst` (complete K_{k,m} bipartite subgraph in tight window) cover scatter-gather smurfing, parallel layering, and coordinated-burst atoms | Closed-vocabulary atomic queries — no manual graph inversion or per-side enumeration glue | `0.5.2` |
62
+ | Multi-epoch calibration audit | `compare_calibrations(v_from, v_to)` — per-dim μ/σ/θ drift between two retained calibration epochs of one pattern | Drift detectors compare model predictions; nothing compares the underlying coordinate system itself | `0.6.0` |
63
+ | Intrinsic vs extrinsic drift decomposition | `decompose_drift` splits an entity's geometric drift into its own movement vs population recalibration; `intrinsic_fraction ∈ [0, 1]` | Drift magnitude alone — population shift and entity behaviour change confound | `0.6.0` |
64
+ | Hidden-influencer matrix | `find_calibration_influencers` — 4-cell classification (`hidden` / `distorter` / `standard_anomaly` / `normal`) via exact leave-one-out impact on calibration | SHAP / counterfactual: explain a prediction, not the coordinate system itself | `0.6.0` |
65
+ | Cross-pattern temporal lead-lag | `find_lead_lag(pattern_a, pattern_b)` — cross-correlates differenced population-centroid drift; peak lag, Bonferroni-adjusted significance, per-dim FDR matrix | Granger causality on raw metrics — not on population-relative geometry | `0.6.0` |
66
+ | Anomaly by absence | `find_density_gaps` — joint-density gaps under independence null with BH-corrected q-values; surfaces under-populated cells in named delta-space ranges | Outlier detection finds extremes; gap detection finds *missing* combinations | `0.6.0` |
67
+ | Declarative motif API | `find_motif_by_hops(pattern_id, hops, *, seed_keys)` — caller passes per-hop `HopPredicate`s (amount / time-delta / direction / edge-dim filters); navigator walks chains of length 1..8 with optional total-span cap (`time_window_hours`) | Closed-vocab motif registry — no escape hatch for ad-hoc structural shapes | `0.6.0` |
68
+ | Anchor-pattern aggregation of edge-derived dims | Anchor patterns declare `edge_dim_aggregations:` to bake per-edge sidecar signals (`pair_edge_count`, `find_motif_structuring`, …) into per-anchor `_mean` / `_max` columns; surfaces in every anchor primitive (`find_anomalies`, `explain_anomaly`, `find_clusters`) | Hand-rolled SQL roll-up + manual feature engineering | `0.6.1` |
69
+ | Richer hop predicates | `HopPredicate.amount_ratio_to_prev` (decreasing-chain ratio) and `require_anomalous_entity` (filter chains routing through calibrated-anomalous nodes) extend the declarative motif API | Closed-vocab motif library has fixed amount thresholds and no anomaly-routing filter | `0.6.1` |
70
+ | Event-aware motif scoring | `find_motif_by_hops(score=True)` ranks motifs by the product of event-aware `edge_potential` across edges (uses both the anchor companion's per-entity geometry and the event pattern's per-transaction polygons); distinct transactions between the same accounts produce distinct scores | Pure node-pair scoring collapses ranks when motifs share a node sequence | `0.6.1` |
71
+ | Chain-anchor aggregation | Chain anchor patterns auto-emitted from `chain_lines:` declare `edge_dim_aggregations:` to bake per-event sidecar signals into per-chain `_mean` / `_max` columns; closes the third `anchor_kind` after `single` and `pair` | Per-chain manual aggregation outside the geometry, or no chain-level edge-dim summary at all | `0.6.2` |
62
72
 
63
73
  ### What changes in practice
64
74
 
@@ -77,6 +87,8 @@ The same problems look different when graph, time, and statistics are unified:
77
87
  | Root-cause an anomaly | Manual chain: explain → counterparties → contagion → hub check, 4+ tool calls | `trace_root_cause(entity)` — single call returns bounded DAG of evidence |
78
88
  | Detect relationship layering | Custom rule engine or manual rare-pair SQL queries | `edge_potential(A, B)` — per-edge score combining endpoint distance and pair rarity |
79
89
  | Match AML typology patterns | Graph DB subgraph queries + separate risk scoring | `find_motif(type="structuring", …)` — structural pattern + geometric rarity product |
90
+ | Match ad-hoc structural chains | Custom subgraph queries per shape, no built-in scoring | `find_motif_by_hops(hops=[HopPredicate(...)])` — declarative per-hop predicates (amount, time, direction, edge-dim, ratio-to-prev, anomaly filter) with event-aware geometric scoring on the same call |
91
+ | Account-level transaction layering recall | Hand-rolled SQL roll-ups of per-edge signals into account features | `edge_dim_aggregations:` on the anchor pattern bakes per-edge structuring / pair-recurrence / chain-depth signals into anchor geometry — read off `find_anomalies` like any other dim |
80
92
  | Direction of behavioural drift | Drift magnitude alone — no toward/away-from-centre signal | `attract_drift` returns `drift_direction ∈ {normalizing, deteriorating, neutral}` |
81
93
 
82
94
  ## Benchmarks
@@ -0,0 +1,89 @@
1
+ # hypertopos — Roadmap
2
+
3
+ > Planned direction. Priorities may change based on feedback.
4
+
5
+ ## 0.6.0
6
+
7
+ Architecture-emergent analytics, properly enabled — calibration is now versioned, and patent-aligned analytics ride on that versioning.
8
+
9
+ - **0.6.0** — multi-epoch calibration retention, `compare_calibrations`, intrinsic / extrinsic drift decomposition, hidden-influencer matrix (`find_calibration_influencers`), cross-pattern temporal lead-lag (`find_lead_lag`), edge-derived event-pattern dimensions, joint density gap detection (`find_density_gaps`), declarative motif API (`find_motif_by_hops`, bounded MVP). Sphere format 2.4.
10
+ - **0.6.1** — anchor-pattern aggregation of edge-derived dimensions (`edge_dim_aggregations:`); BFS-by-level enumerator on `find_motif_by_hops` with hop count cap raised 6→8 and global `time_window_hours`; declarative motif API completion via `HopPredicate.amount_ratio_to_prev` and `require_anomalous_entity`; functional anchor-companion + event-aware scoring on `find_motif_by_hops(score=True)`; broadcast-safe `Pattern.dim_labels` on patterns with aggregated edge-dim names. Additive only — no sphere format bump, no new tools.
11
+ - **0.6.2** — chain-anchor `edge_dim_aggregations:` regime closes the third `anchor_kind` after single (account-style) and pair (k=2 composite); vectorized `AdjacencyIndex` load path (pyarrow `group_by` + lazy per-key materialization) for cold-start latency cleanup; column-selective `neighbors_*_window` accessors with motif enumerator migration for `bipartite_burst`, `fan_out`, `fan_in`, `cycle_2`; new project skill `profile-before-plan` gating hot-path refactors on real-data cProfile. Additive only — sphere format stays at 2.4 (the originally proposed persisted-artifact path was empirically refuted; vectorized loader ships without any on-disk change).
12
+
13
+ See [CHANGELOG](CHANGELOG.md) for the full feature list.
14
+
15
+ ---
16
+
17
+ ## 0.5.0
18
+
19
+ Detection-quality and investigation-workflow push.
20
+
21
+ - **0.5.0** — Storey adaptive π₀ FDR; drift direction on `π9_attract_drift`; multi-hop root-cause tracing (`trace_root_cause` DAG); geometric edge potential; structural motif scoring (`fan_out`, `cycle_2`, `cycle_3`, `structuring`).
22
+ - **0.5.1** — `fan_in` and `chain_k` motifs.
23
+ - **0.5.2** — `split_recombine` and `bipartite_burst` motifs; perf-hardening pass on the catalog.
24
+
25
+ ---
26
+
27
+ ## 0.4.0
28
+
29
+ Distribution-aware geometry, calibration fidelity, and graph acceleration.
30
+
31
+ - **0.4.0** — Distribution-aware Bregman divergence with per-dim kind tags; per-dimension anomaly threshold; in-memory adjacency index.
32
+ - **0.4.1** — Native graph algorithms as build-time dimensions (PageRank, betweenness, community, clustering, components); bidirectional BFS rewrite of `find_geometric_path`.
33
+
34
+ ---
35
+
36
+ ## 0.3.0
37
+
38
+ Lance perf upgrade, FDR control, builder intelligence.
39
+
40
+ - **0.3.0** — Aggregate engine rewrite on Lance SQL; precomputed contagion stats; format 2.2.
41
+ - **0.3.1** — Benjamini-Hochberg FDR control; submodular facility location; vectorized build with adaptive memory chunking.
42
+ - **0.3.2** — NumPy graph features; chunked pre-computation; geometric heredity (`find_novel_entities`).
43
+ - **0.3.3** — Agent navigation policy; dimension-selective similarity.
44
+
45
+ ---
46
+
47
+ ## 0.2.0
48
+
49
+ Graph meets geometry — edge table, runtime traversal, contagion/influence.
50
+
51
+ - **0.2.0** — Edge table; +11 navigator functions; contagion/influence primitives.
52
+ - **0.2.1** — Witness cohort discovery; investigative peer ranking.
53
+ - **0.2.2** — As-of graph reconstruction; `detect_cross_pattern_discrepancy` latency fix.
54
+
55
+ ---
56
+
57
+ ## 0.1.0
58
+
59
+ First public release — full GDS stack, π1–π12, builder, MCP server, validation suite.
60
+
61
+ ---
62
+
63
+ ## Future
64
+
65
+ **Detection quality**
66
+ - Robust estimators, multi-scale resolution — trimmed means / MAD-based σ, hierarchical build at daily/weekly/full granularity.
67
+ - Chains as first-class geometric entities — external chains declared as anchor lines with a membership table, plus chain-aware geometric primitives (anomaly propagation inside a chain, coherent-anomaly filter, chain drift trajectory).
68
+
69
+ **Builder evolution**
70
+ - Incremental rebuild — geometry-only without `--force` wipe.
71
+
72
+ **PassiveScanner evolution**
73
+ - Native temporal source support for direct temporal inputs, without requiring manual dataset plumbing in benchmark scripts.
74
+ - Optional weighted scoring mode that uses continuous intensity instead of binary counts.
75
+ - **SphereProfiler** — autonomous sphere scanner that profiles all patterns, runs calibration sweeps across source combinations, proposes optimal PassiveScanner composition for Layer 1 surveillance.
76
+
77
+ **Code refactoring**
78
+ - Break up oversized modules into smaller, domain-focused components (post-0.5.0 `navigator.py` is over 11k lines and is the obvious first target; per-pattern parallelism and AdjacencyIndex reuse in 0.4.0/0.5.0 reduced some coupling but the module itself did not shrink).
79
+ - Consolidate repeated orchestration logic into shared helpers.
80
+
81
+ **Cross-sphere capabilities**
82
+ - Cross-sphere comparison — dimensionless metrics across independently calibrated coordinate spaces.
83
+ - What-if analysis — hypothetical edge changes producing modified coordinate vectors.
84
+
85
+ **Enterprise / governance**
86
+ - Dimension access control — per-agent visibility constraints on delta dimensions.
87
+
88
+ **Tooling**
89
+ - Runtime latency benchmarks in package docs.
@@ -1,6 +1,6 @@
1
1
  # Security
2
2
 
3
- ## Current version: 0.6.0
3
+ ## Current version: 0.6.2
4
4
 
5
5
  hypertopos runs locally. No network services, no auth layer, no multi-tenancy.
6
6
 
@@ -270,15 +270,16 @@ nav.find_motif_by_hops(
270
270
  *,
271
271
  seed_keys: list[str] | None = None,
272
272
  max_results: int = 100,
273
- score: bool = True,
273
+ score: bool = False,
274
+ time_window_hours: float | None = None,
274
275
  ) -> dict
275
276
  ```
276
277
 
277
- Declarative motif API — power-user escape hatch from the closed-vocab `find_motif` registry. Caller passes a list of `HopPredicate`s describing per-hop constraints (`amount_min`, `amount_max`, `time_delta_max_hours`, `direction` (`"forward"` / `"reverse"` / `"any"`), `edge_dim_predicates: dict[str, tuple[op, value]]`); the navigator walks the in-memory `AdjacencyIndex` for matching chains. `seed_keys=None` enumerates from all `from_key` nodes (capped at `max_results`). Returns `{pattern_id, n_results, motifs}` with each motif carrying `nodes`, `edges` (event_keys), `timestamps`, `amounts`, `dim_values_per_hop` (only when `edge_dim_predicates` were used), optional `score` (anchor patterns only) and `score_breakdown`. Raises on anchor pattern (event-only), unknown pattern, empty hops, k>6, `max_results<1`. Bounded MVP — `amount_ratio_to_prev` and `require_anomalous_entity` predicates plus k>6 land in a follow-up.
278
+ Declarative motif API — power-user escape hatch from the closed-vocab `find_motif` registry. Caller passes a list of `HopPredicate`s describing per-hop constraints (`amount_min`, `amount_max`, `time_delta_max_hours`, `amount_ratio_to_prev`, `direction` (`"forward"` / `"reverse"` / `"any"`), `edge_dim_predicates: dict[str, tuple[op, value]]`); the navigator walks the in-memory `AdjacencyIndex` for matching chains via level-synchronous BFS. `seed_keys=None` enumerates from all `from_key` nodes (capped at `max_results`). `time_window_hours` (optional, default `None`) caps the total chain span: when set, every hop after the first must satisfy `abs(current_edge_ts - first_edge_ts) <= time_window_hours`; independent of per-hop `time_delta_max_hours`, both apply when both are set. When `score=True`, the navigator resolves the event pattern's anchor companion via `_resolve_anchor_pattern_for_scoring` and scores each motif as the product of event-aware `edge_potential` (`delta_distance × (1/effective_pair_count) × (1 + event_norm)`) across its edges. The `event_norm` factor (norm of the event pattern's per-transaction polygon for each edge's `event_key`) breaks ties between motifs that share a node sequence but use different transactions. Scored motifs gain `score`, `score_breakdown` (per-edge entries carry `edge_potential`, `delta_distance`, `pair_tx_count`, `effective_weight`, `event_factor`), and `anchor_pattern_id` fields together (sorted descending on score, unscored motifs at tail). Returns `{pattern_id, n_results, motifs}` with each motif carrying `nodes`, `edges` (event_keys), `timestamps`, `amounts`, `dim_values_per_hop` (only when `edge_dim_predicates` were used), and the score triple when `score=True` succeeds. Raises on anchor pattern (event-only), unknown pattern, empty hops, hop count outside `1..8`, non-positive `time_window_hours`, `max_results<1`, or `score=True` with no anchor companion configured for the pattern.
278
279
 
279
280
  ### `HopPredicate` (dataclass, frozen)
280
281
 
281
- Fields: `amount_min`, `amount_max`, `time_delta_max_hours`, `direction` (Literal["forward", "reverse", "any"], default `"forward"`), `edge_dim_predicates` (`dict[str, tuple[str, float]]`, e.g. `{"pair_edge_count": (">=", 20.0)}`). Operators: `<`, `<=`, `>`, `>=`, `==`.
282
+ Fields: `amount_min`, `amount_max`, `time_delta_max_hours`, `amount_ratio_to_prev` (`float | None`, decreasing-chain ratio in `(0, 1.0]`; rejects edge unless `current_amount / prev_hop_amount ≤ ratio`; must be `None` on `hops[0]`; edges with non-positive amounts are silently skipped), `direction` (Literal["forward", "reverse", "any"], default `"forward"`), `edge_dim_predicates` (`dict[str, tuple[str, float]]`, e.g. `{"pair_edge_count": (">=", 20.0)}`). Operators: `<`, `<=`, `>`, `>=`, `==`. `require_anomalous_entity` (`bool`, default `False`) — when `True` on hop `i`, the destination entity (`nodes[i+1]`) must satisfy `is_anomaly=True` in the resolved anchor companion pattern's geometry; constraints AND across hops; filter runs at the navigator post-BFS, pre-scoring; `max_results` applies AFTER the filter; raises `GDSNavigationError` when no anchor companion is configured.
282
283
 
283
284
  ### Density Gaps Engine (`hypertopos.engine.density_gaps`)
284
285
 
@@ -337,6 +338,9 @@ names in user-supplied `dim_pairs`.
337
338
  |--------|-------------|
338
339
  | `EdgeDimensionsConfig(dims: dict[str, dict])` | Parsed `edge_dimensions:` block — frozen dataclass attached to `PatternMapping.edge_dimensions` |
339
340
  | `parse_edge_dimensions(raw_list, *, pattern_type)` | Parse + validate the YAML list of dim entries (bare strings or single-key dicts). Raises `ValueError` on anchor pattern, `min_position < 3`, `cv_threshold` outside `(0, 1]`, `min_count < 2`, non-positive `amt1_min` / `amt2_max` / `time_window_hours`, negative `burst_seconds`, duplicate or unknown dim names, malformed entries |
341
+ | `EdgeDimAggregationsConfig(from_event_pattern: str, dims: tuple[str, ...])` | Parsed `edge_dim_aggregations:` block on an anchor pattern — frozen dataclass attached to `PatternMapping.edge_dim_aggregations`. `dims` is a non-empty tuple of source dim names |
342
+ | `parse_edge_dim_aggregations(raw_dict, *, pattern_type)` | Parse + validate the YAML mapping. Raises `ValueError` on event pattern, missing `from`, missing or empty `dims` (non-empty list required), non-list `dims`, or unknown dim name |
343
+ | `aggregate_edge_dims_for_anchor(*, anchor_keys, edges, sidecar, dims, anchor_kind, pair_separator, chain_events)` | Aggregate per-edge sidecar dim values up to per-anchor `_mean` / `_max` columns. `anchor_kind` ∈ `{single, pair, chain}`. For chain regime, pass `chain_events: list[str]` of comma-joined event_keys per anchor (one per `anchor_keys` entry); `edges` arg is ignored. Returns a `pa.Table` keyed by `primary_key` |
340
344
 
341
345
  ### Calibration History (GDSReader)
342
346
 
@@ -30,7 +30,7 @@ The core package is split into a few layers:
30
30
  - **Builder**: transforms source data into a complete sphere
31
31
  - **CLI**: builds and inspects spheres from the command line
32
32
 
33
- The `hypertopos-mcp` package sits on top of this core library and exposes the same capabilities to agents via 67 MCP tools.
33
+ The `hypertopos-mcp` package sits on top of this core library and exposes the same capabilities to agents via 80 MCP tools.
34
34
 
35
35
  The split is deliberate:
36
36
 
@@ -175,7 +175,7 @@ graph LR
175
175
  ST --> E["Engine\ngeometry, delta,\nclustering, DTW"]
176
176
  E --> N["Navigator\nπ1–π12, detect_*"]
177
177
  N --> PS["PassiveScanner\nmulti-source\nbatch screening"]
178
- N --> MCP["MCP Server\n72 tools\nstdio transport"]
178
+ N --> MCP["MCP Server\n80 tools\nstdio transport"]
179
179
  MCP --> Agent["AI Agent"]
180
180
  CT["CalibrationTracker\nonline drift\nWelford stats"] -.-> E
181
181
  M["Manifest\nMVCC version pin"] -.-> ST
@@ -238,7 +238,7 @@ Event patterns can declare an `edge_dimensions:` block in YAML to add up to five
238
238
  | `pair_amount_zscore` (LOW_VAR pairs only) | gaussian | signed z-score of amount within `(from_key, to_key)` pairs whose CV(amount) < `cv_threshold`; HIGH_VAR pairs and pairs below `min_count` write 0.0 — direction-agnostic outlier signal on locked-amount pairs |
239
239
  | `find_motif_structuring` | bernoulli | 1.0 if the edge participates in any A→B→C→D structuring motif within `time_window_hours` with hop1 ≥ `amt1_min` and hops 2/3 ≤ `amt2_max` |
240
240
 
241
- These dims are computed at edge-table emission time, written to the `_gds_meta/edge_features/{pid}/data.lance` sidecar keyed by `event_key`, AND merged into the event polygon `shape_snapshot` (one extra dim per declared entry). Downstream primitives (`find_anomalies`, `find_similar_entities`, `find_clusters`) automatically include them in `delta` / `delta_norm` / classification — no new query API. Reject `min_position < 3` at YAML parse time. Anchor patterns reject the block — the per-edge → per-entity aggregation that would let anchor patterns use these dims is a deferred follow-up.
241
+ These dims are computed at edge-table emission time, written to the `_gds_meta/edge_features/{pid}/data.lance` sidecar keyed by `event_key`, AND merged into the event polygon `shape_snapshot` (one extra dim per declared entry). Downstream primitives (`find_anomalies`, `find_similar_entities`, `find_clusters`) automatically include them in `delta` / `delta_norm` / classification — no new query API. Reject `min_position < 3` at YAML parse time. Anchor patterns reject the `edge_dimensions:` block directly; to expose these per-edge signals on anchor entities, declare `edge_dim_aggregations:` on the anchor pattern instead — see `configuration.md` for the YAML stanza and supported aggregates (`_mean` / `_max`). For chain anchor patterns auto-emitted from `chain_lines:` config, declare `edge_dim_aggregations:` directly inside the `chain_lines.<id>:` block — same `from: <event_pid>` and `dims: [...]` schema as on regular anchor patterns; the builder forwards it to the auto-emitted `<id>_pattern`.
242
242
 
243
243
  ## Chain Interpretation
244
244
 
@@ -373,6 +373,7 @@ patterns:
373
373
  | `description` | string | `null` | Human-readable description. Stored in sphere.json — visible to agents via `get_sphere_info`. |
374
374
  | `edge_table` | dict | `null` | Explicit edge table config (see below). Auto-emitted for event patterns with 2+ FK relations to same anchor line. |
375
375
  | `edge_dimensions` | list | `null` | Build-time per-edge dims for event patterns. Each item is either a bare dim name or a single-key dict with overrides. Five dims available: `pair_edge_count`, `position_in_chain` (`min_position` ≥ 3, default 5), `time_since_pair_last_edge`, `pair_amount_zscore` (LOW_VAR pairs only), `find_motif_structuring`. |
376
+ | `edge_dim_aggregations` | dict | `null` | **Anchor patterns only.** Aggregate per-edge sidecar dims of an event pattern up to per-anchor `_mean` / `_max` columns baked into the anchor polygon. `from: <event_pid>` is required and must reference an event pattern that declares `edge_dimensions:`. `dims: [...]` is required — must be a non-empty list of source dim names from the referenced sidecar (the previous "omit `dims` to aggregate everything" shorthand was removed; explicit declaration prevents build-vs-runtime label drift). Anchor regimes: `single` (account-style, anchor PK matches edge `from_key` OR `to_key`) and `pair` (composite-key, anchor PK = `<from>__<to>`); `chain` raises `NotImplementedError`. Builder switches to a two-phase build (events first, anchors second) when this block is present. |
376
377
  | `bootstrap_iterations` | int | `200` | Number of bootstrap resamples used to compute `anomaly_confidence` per entity. Skipped automatically for N > 50K, `group_by_property`, or `use_mahalanobis`. |
377
378
 
378
379
  ### Edge Table
@@ -733,6 +734,25 @@ Automatically creates an anchor line + pattern (`{line_id}_pattern`).
733
734
  | `bidirectional` | bool | `true` | Follow edges in both directions. |
734
735
  | `anomaly_percentile` | float | `95.0` | Theta for the auto-created chain pattern. |
735
736
  | `description` | string | `null` | Description for chain line + pattern. |
737
+ | `edge_dim_aggregations` | dict | `null` | Aggregate per-edge sidecar dims of an event pattern up to per-chain `_mean` / `_max` columns baked into the chain anchor polygon. `from: <event_pid>` is required and must reference an event pattern that declares `edge_dimensions:` and whose `edge_table.event_line` matches this `chain_lines.<id>.event_line` (validated at parse time). `dims: [...]` is required — non-empty list of source dim names from the referenced sidecar. The chain anchor pattern's polygon shape grows by `2 * len(dims)` columns; downstream primitives (`find_anomalies`, `explain_anomaly`, `find_clusters`) surface the new dims transparently. |
738
+
739
+ **Example with edge-dim aggregation on chain anchor:**
740
+
741
+ ```yaml
742
+ chain_lines:
743
+ tx_chains:
744
+ event_line: transactions
745
+ from_col: from_account
746
+ to_col: to_account
747
+ features: [hop_count, is_cyclic, time_span_hours]
748
+ edge_dim_aggregations:
749
+ from: tx_pattern # event pattern declaring edge_dimensions
750
+ dims: [find_motif_structuring, position_in_chain]
751
+ ```
752
+
753
+ The chain anchor `tx_chains_pattern` then exposes `find_motif_structuring_mean`,
754
+ `find_motif_structuring_max`, `position_in_chain_mean`, `position_in_chain_max`
755
+ in `find_anomalies` response and `Pattern.dim_labels`.
736
756
 
737
757
  ---
738
758