iris-vector-graph 1.63.2__tar.gz → 1.63.3__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 (245) hide show
  1. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/PKG-INFO +45 -1
  2. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/README.md +44 -0
  3. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/iris_src/src/Graph/KG/Traversal.cls +21 -3
  4. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/iris_vector_graph/__init__.py +1 -0
  5. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/iris_vector_graph/engine.py +143 -0
  6. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/iris_vector_graph/security.py +4 -1
  7. iris_vector_graph-1.63.3/iris_vector_graph/status.py +136 -0
  8. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/pyproject.toml +1 -1
  9. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/unit/test_cypher_e2e_new_features.py +81 -0
  10. iris_vector_graph-1.63.3/tests/unit/test_engine_status.py +192 -0
  11. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/.gitignore +0 -0
  12. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/LICENSE +0 -0
  13. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/examples/demo_biomedical.py +0 -0
  14. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/examples/demo_fraud_detection.py +0 -0
  15. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/examples/demo_fraud_detection_sql.py +0 -0
  16. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/examples/demo_utils.py +0 -0
  17. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/examples/demo_working_system.py +0 -0
  18. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/examples/domains/__init__.py +0 -0
  19. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/examples/domains/biomedical/__init__.py +0 -0
  20. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/examples/domains/biomedical/loaders.py +0 -0
  21. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/examples/domains/biomedical/resolver.py +0 -0
  22. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/examples/domains/biomedical/types.py +0 -0
  23. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/examples/domains/biomedical_legacy/__init__.py +0 -0
  24. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/examples/domains/biomedical_legacy/biomedical_engine.py +0 -0
  25. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/examples/domains/biomedical_legacy/biomedical_schema.py +0 -0
  26. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/examples/domains/biomedical_legacy/legacy_wrapper.py +0 -0
  27. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/examples/domains/fraud/__init__.py +0 -0
  28. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/examples/domains/fraud/loaders.py +0 -0
  29. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/examples/domains/fraud/resolver.py +0 -0
  30. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/examples/domains/fraud/types.py +0 -0
  31. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/examples/graphQL.http +0 -0
  32. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/examples/hybrid_vector_graph_query.cypher +0 -0
  33. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/examples/rest.http +0 -0
  34. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/iris_src/src/Graph/KG/Algorithms.cls +0 -0
  35. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/iris_src/src/Graph/KG/ArnoAccel.cls +0 -0
  36. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/iris_src/src/Graph/KG/BM25Index.cls +0 -0
  37. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/iris_src/src/Graph/KG/BenchFormat.cls +0 -0
  38. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/iris_src/src/Graph/KG/BenchSeeder.cls +0 -0
  39. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/iris_src/src/Graph/KG/Benchmark.cls +0 -0
  40. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/iris_src/src/Graph/KG/Edge.cls +0 -0
  41. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/iris_src/src/Graph/KG/EdgeScan.cls +0 -0
  42. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/iris_src/src/Graph/KG/GraphIndex.cls +0 -0
  43. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/iris_src/src/Graph/KG/IVFIndex.cls +0 -0
  44. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/iris_src/src/Graph/KG/Loader.cls +0 -0
  45. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/iris_src/src/Graph/KG/MCPService.cls +0 -0
  46. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/iris_src/src/Graph/KG/MCPToolSet.cls +0 -0
  47. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/iris_src/src/Graph/KG/MCPTools.cls +0 -0
  48. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/iris_src/src/Graph/KG/Meta.cls +0 -0
  49. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/iris_src/src/Graph/KG/PLAIDSearch.cls +0 -0
  50. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/iris_src/src/Graph/KG/PageRank.cls +0 -0
  51. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/iris_src/src/Graph/KG/PyOps.cls +0 -0
  52. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/iris_src/src/Graph/KG/Service.cls +0 -0
  53. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/iris_src/src/Graph/KG/Snapshot.cls +0 -0
  54. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/iris_src/src/Graph/KG/Subgraph.cls +0 -0
  55. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/iris_src/src/Graph/KG/TemporalIndex.cls +0 -0
  56. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/iris_src/src/Graph/KG/TestEdge.cls +0 -0
  57. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/iris_src/src/Graph/KG/VecIndex.cls +0 -0
  58. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/iris_src/src/PageRankEmbedded.cls +0 -0
  59. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/iris_src/src/User.Exec.cls +0 -0
  60. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/iris_src/src/iris/vector/graph/GraphOperators.cls +0 -0
  61. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/iris_vector_graph/bolt_server.py +0 -0
  62. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/iris_vector_graph/bulk_loader.py +0 -0
  63. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/iris_vector_graph/capabilities.py +0 -0
  64. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/iris_vector_graph/cypher/__init__.py +0 -0
  65. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/iris_vector_graph/cypher/algorithms/__init__.py +0 -0
  66. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/iris_vector_graph/cypher/algorithms/paths.py +0 -0
  67. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/iris_vector_graph/cypher/ast.py +0 -0
  68. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/iris_vector_graph/cypher/lexer.py +0 -0
  69. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/iris_vector_graph/cypher/parser.py +0 -0
  70. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/iris_vector_graph/cypher/translator.py +0 -0
  71. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/iris_vector_graph/cypher_api.py +0 -0
  72. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/iris_vector_graph/embedded.py +0 -0
  73. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/iris_vector_graph/fusion.py +0 -0
  74. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/iris_vector_graph/gql/__init__.py +0 -0
  75. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/iris_vector_graph/gql/constants.py +0 -0
  76. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/iris_vector_graph/gql/engine.py +0 -0
  77. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/iris_vector_graph/gql/pooling.py +0 -0
  78. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/iris_vector_graph/gql/resolvers.py +0 -0
  79. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/iris_vector_graph/gql/schema.py +0 -0
  80. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/iris_vector_graph/models.py +0 -0
  81. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/iris_vector_graph/operators.py +0 -0
  82. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/iris_vector_graph/py.typed +0 -0
  83. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/iris_vector_graph/schema.py +0 -0
  84. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/iris_vector_graph/text_search.py +0 -0
  85. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/iris_vector_graph/utils.py +0 -0
  86. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/iris_vector_graph/vector_utils.py +0 -0
  87. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/sql/fhir_bridges.sql +0 -0
  88. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/sql/fraud_sample_data.sql +0 -0
  89. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/sql/globals_schema.sql +0 -0
  90. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/sql/graph_path_globals.sql +0 -0
  91. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/sql/graph_walk_tvf.sql +0 -0
  92. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/sql/migrations/000_base_schema_iris.sql +0 -0
  93. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/sql/migrations/001_add_nodepk_table.sql +0 -0
  94. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/sql/migrations/001_rollback_nodepk.sql +0 -0
  95. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/sql/migrations/002_add_fk_constraints.sql +0 -0
  96. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/sql/operators.sql +0 -0
  97. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/sql/operators_fixed.sql +0 -0
  98. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/sql/procedures/kg_PageRank.sql +0 -0
  99. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/sql/rdf_reifications.sql +0 -0
  100. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/sql/schema.sql +0 -0
  101. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/TESTING.md +0 -0
  102. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/benchmark_parser.py +0 -0
  103. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/benchmarks/benchmark_neo4j.py +0 -0
  104. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/benchmarks/bfs_benchmark.py +0 -0
  105. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/benchmarks/establish_baseline.py +0 -0
  106. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/benchmarks/graph_gen.py +0 -0
  107. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/benchmarks/iris_baseline_run.py +0 -0
  108. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/benchmarks/iris_os_run.py +0 -0
  109. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/benchmarks/load_neo4j.py +0 -0
  110. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/benchmarks/synthetic_baseline.csv +0 -0
  111. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/conftest.py +0 -0
  112. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/contract/__init__.py +0 -0
  113. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/contract/test_cypher_api.py +0 -0
  114. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/contract/test_cypher_api_errors.py +0 -0
  115. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/contract/test_graphql_queries.py +0 -0
  116. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/contract/test_graphql_schema.py +0 -0
  117. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/contract/test_ppr_api.py +0 -0
  118. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/curl_suite.sh +0 -0
  119. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/e2e/__init__.py +0 -0
  120. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/e2e/conftest.py +0 -0
  121. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/e2e/test_biomedical_demo.py +0 -0
  122. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/e2e/test_biomedical_ui.py +0 -0
  123. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/e2e/test_cypher_coerce_e2e.py +0 -0
  124. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/e2e/test_cypher_sprints_e2e.py +0 -0
  125. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/e2e/test_cypher_vector_search.py +0 -0
  126. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/e2e/test_fhir_bridges_e2e.py +0 -0
  127. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/e2e/test_fraud_demo.py +0 -0
  128. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/e2e/test_fraud_ui.py +0 -0
  129. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/e2e/test_gql_autogen_startup.py +0 -0
  130. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/e2e/test_gql_cypher_passthrough.py +0 -0
  131. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/e2e/test_gql_node_queries.py +0 -0
  132. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/e2e/test_gql_semantic_search.py +0 -0
  133. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/e2e/test_gql_traversal.py +0 -0
  134. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/e2e/test_graph_kernels_e2e.py +0 -0
  135. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/e2e/test_hla_kg_e2e.py +0 -0
  136. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/e2e/test_multi_query_engine_platform.py +0 -0
  137. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/e2e/test_named_paths_e2e.py +0 -0
  138. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/e2e/test_nkg_index_e2e.py +0 -0
  139. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/e2e/test_operator_wiring_e2e.py +0 -0
  140. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/e2e/test_plaid_search_e2e.py +0 -0
  141. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/e2e/test_ppr_cls_fast_path.py +0 -0
  142. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/e2e/test_ppr_guided_e2e.py +0 -0
  143. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/e2e/test_procedure_installation.py +0 -0
  144. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/e2e/test_reification_e2e.py +0 -0
  145. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/e2e/test_schema_procedures_e2e.py +0 -0
  146. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/e2e/test_subgraph_e2e.py +0 -0
  147. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/e2e/test_subquery_call_e2e.py +0 -0
  148. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/e2e/test_vecindex_e2e.py +0 -0
  149. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/integration/__init__.py +0 -0
  150. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/integration/conftest.py +0 -0
  151. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/integration/gql/__init__.py +0 -0
  152. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/integration/gql/test_graphql_mutations.py +0 -0
  153. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/integration/gql/test_graphql_nested_queries.py +0 -0
  154. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/integration/gql/test_graphql_queries.py +0 -0
  155. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/integration/gql/test_graphql_vector_search.py +0 -0
  156. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/integration/test_bidirectional_ppr.py +0 -0
  157. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/integration/test_cls_layer.py +0 -0
  158. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/integration/test_cypher_advanced.py +0 -0
  159. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/integration/test_cypher_enhancements.py +0 -0
  160. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/integration/test_cypher_multi_type.py +0 -0
  161. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/integration/test_cypher_rd.py +0 -0
  162. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/integration/test_cypher_rel_vars.py +0 -0
  163. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/integration/test_cypher_single_type.py +0 -0
  164. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/integration/test_cypher_untyped.py +0 -0
  165. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/integration/test_cypher_vector_search.py +0 -0
  166. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/integration/test_embeddings_api.py +0 -0
  167. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/integration/test_fastapi_graphql.py +0 -0
  168. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/integration/test_fhir_bridges_integration.py +0 -0
  169. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/integration/test_named_paths_integration.py +0 -0
  170. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/integration/test_nodepk_advanced_benchmarks.py +0 -0
  171. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/integration/test_nodepk_constraints.py +0 -0
  172. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/integration/test_nodepk_graph_analytics.py +0 -0
  173. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/integration/test_nodepk_migration.py +0 -0
  174. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/integration/test_nodepk_performance.py +0 -0
  175. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/integration/test_nodepk_production_scale.py +0 -0
  176. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/integration/test_objectscript_classes.py +0 -0
  177. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/integration/test_pagerank_sql_optimization.py +0 -0
  178. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/integration/test_reification_integration.py +0 -0
  179. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/integration/test_schema_migration.py +0 -0
  180. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/integration/test_stored_procedure_install.py +0 -0
  181. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/integration/test_subquery_call_integration.py +0 -0
  182. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/performance/conftest.py +0 -0
  183. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/performance/scale_benchmark.py +0 -0
  184. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/performance/test_ppr_stress.py +0 -0
  185. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/performance/test_stress_v1_5.py +0 -0
  186. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/python/run_all_tests.py +0 -0
  187. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/python/test_iris_rest_api.py +0 -0
  188. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/python/test_networkx_loader.py +0 -0
  189. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/python/test_performance_benchmarks.py +0 -0
  190. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/python/test_pyops_vector_conversion.py +0 -0
  191. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/python/test_python_operators.py +0 -0
  192. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/python/test_python_sdk.py +0 -0
  193. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/python/test_schema_validation.py +0 -0
  194. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/python/test_sql_queries.py +0 -0
  195. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/python/test_vector_functions.py +0 -0
  196. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/unit/cypher/__init__.py +0 -0
  197. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/unit/cypher/test_lexer.py +0 -0
  198. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/unit/cypher/test_lexer_advanced.py +0 -0
  199. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/unit/cypher/test_parser.py +0 -0
  200. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/unit/cypher/test_parser_advanced.py +0 -0
  201. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/unit/test_batch_mutations.py +0 -0
  202. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/unit/test_bfs_arno.py +0 -0
  203. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/unit/test_bm25_index.py +0 -0
  204. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/unit/test_bolt_server.py +0 -0
  205. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/unit/test_cls_deployment.py +0 -0
  206. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/unit/test_cypher_benchmark.py +0 -0
  207. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/unit/test_cypher_benchmark_scale.py +0 -0
  208. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/unit/test_cypher_case_when.py +0 -0
  209. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/unit/test_cypher_functions.py +0 -0
  210. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/unit/test_cypher_parser.py +0 -0
  211. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/unit/test_cypher_posos_bugs.py +0 -0
  212. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/unit/test_cypher_procedures.py +0 -0
  213. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/unit/test_cypher_translator.py +0 -0
  214. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/unit/test_cypher_union_exists.py +0 -0
  215. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/unit/test_cypher_var_length.py +0 -0
  216. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/unit/test_cypher_vector_search.py +0 -0
  217. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/unit/test_edge_embeddings.py +0 -0
  218. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/unit/test_edgeprop_ndjson.py +0 -0
  219. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/unit/test_embedded.py +0 -0
  220. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/unit/test_engine_dimension_fix.py +0 -0
  221. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/unit/test_engine_embeddings.py +0 -0
  222. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/unit/test_fhir_bridges.py +0 -0
  223. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/unit/test_get_nodes.py +0 -0
  224. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/unit/test_graph_kernels.py +0 -0
  225. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/unit/test_graphql_dataloader.py +0 -0
  226. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/unit/test_ingest_formats.py +0 -0
  227. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/unit/test_ivf_index.py +0 -0
  228. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/unit/test_named_graphs.py +0 -0
  229. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/unit/test_named_paths.py +0 -0
  230. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/unit/test_operators_wiring.py +0 -0
  231. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/unit/test_plaid_search.py +0 -0
  232. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/unit/test_ppr_guided_subgraph.py +0 -0
  233. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/unit/test_reification.py +0 -0
  234. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/unit/test_schema_init.py +0 -0
  235. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/unit/test_schema_procedures.py +0 -0
  236. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/unit/test_shortest_path.py +0 -0
  237. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/unit/test_snapshot.py +0 -0
  238. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/unit/test_sql_splitter.py +0 -0
  239. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/unit/test_sql_table_bridge.py +0 -0
  240. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/unit/test_subgraph.py +0 -0
  241. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/unit/test_subquery_call.py +0 -0
  242. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/unit/test_temporal_cypher.py +0 -0
  243. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/unit/test_temporal_edges.py +0 -0
  244. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/unit/test_unified_edge_store.py +0 -0
  245. {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/unit/test_weighted_shortest_path.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: iris-vector-graph
3
- Version: 1.63.2
3
+ Version: 1.63.3
4
4
  Summary: Transactional Graph + Vector retrieval system for InterSystems IRIS with hybrid search, openCypher, and GraphQL APIs
5
5
  Project-URL: Homepage, https://github.com/intersystems-community/iris-vector-graph
6
6
  Project-URL: Documentation, https://github.com/intersystems-community/iris-vector-graph/tree/main/docs
@@ -407,6 +407,43 @@ Returns `[{"s": str, "p": str, "o_id": str, "score": float}, ...]` sorted descen
407
407
 
408
408
  ---
409
409
 
410
+ ## Engine Status
411
+
412
+ Call `engine.status()` at any time to get a structured snapshot of all components. This is the canonical answer to "why is query X returning nothing?"
413
+
414
+ ```python
415
+ s = engine.status()
416
+ print(s.report())
417
+
418
+ # Readiness gates — use before running query types
419
+ s.ready_for_bfs # var-length / undirected / shortestPath — needs ^KG + edges
420
+ s.ready_for_vector_search # needs node embeddings
421
+ s.ready_for_edge_search # needs edge embeddings
422
+ s.ready_for_full_text # needs BM25 index
423
+
424
+ # Example: rebuild ^KG if stale
425
+ if not s.ready_for_bfs and s.tables.edges > 0:
426
+ engine.build_graph_globals() # calls BuildKG()
427
+ ```
428
+
429
+ Sample output:
430
+ ```
431
+ IVG Engine Status
432
+ ══════════════════════════════════════════
433
+ SQL Tables (probe: 23ms)
434
+ nodes 10,000
435
+ edges 50,000
436
+ ...
437
+ Adjacency Globals
438
+ ✓ ^KG (50,000 source nodes indexed)
439
+ ✗ ^NKG (Arno integer index)
440
+ ...
441
+ ```
442
+
443
+ `status()` is explicit-call only — never run automatically at init or before queries. Cost ~50ms.
444
+
445
+ ---
446
+
410
447
  ## PLAID Multi-Vector Search
411
448
 
412
449
  ```python
@@ -655,6 +692,13 @@ anchors = engine.get_kg_anchors(icd_codes=["J18.0", "E11.9"])
655
692
 
656
693
  ## Changelog
657
694
 
695
+ ### v1.63.3 (2026-04-26)
696
+ - feat: `engine.status() -> EngineStatus` — structured runtime snapshot: SQL row counts, `^KG`/`^NKG` population, ObjectScript classes, Arno capabilities, HNSW/IVF/BM25/PLAID index inventory. Readiness properties: `ready_for_bfs`, `ready_for_vector_search`, `ready_for_edge_search`, `ready_for_full_text`. Detects `^KG`/`rdf_edges` predicate mismatch (stale ^KG from different data snapshot). (spec 080)
697
+ - fix: `BuildKG()` `Traversal.cls` SQL cursors now use fully-qualified `Graph_KG.rdf_edges`, `Graph_KG.rdf_labels`, `Graph_KG.rdf_props` — fixes predicate mismatch when IRIS namespace default SQL schema is not `Graph_KG` (e.g. MINDWALK namespace with `SQLUser` default)
698
+ - fix: `kg_IVFMeta`, `kg_BM25Meta`, `kg_PlaidMeta` added to security allowlist
699
+ - `EngineStatus` exported from top-level `iris_vector_graph`
700
+
701
+
658
702
  ### v1.63.2 (2026-04-25)
659
703
  - fix: `MATCH (a)-[r*1..N]-(b)` undirected BFS now traverses `^KG("in",...)` for inbound edges (was outbound-only)
660
704
  - fix: `MATCH (a)<-[r*1..N]-(b)` inbound-only BFS now works
@@ -335,6 +335,43 @@ Returns `[{"s": str, "p": str, "o_id": str, "score": float}, ...]` sorted descen
335
335
 
336
336
  ---
337
337
 
338
+ ## Engine Status
339
+
340
+ Call `engine.status()` at any time to get a structured snapshot of all components. This is the canonical answer to "why is query X returning nothing?"
341
+
342
+ ```python
343
+ s = engine.status()
344
+ print(s.report())
345
+
346
+ # Readiness gates — use before running query types
347
+ s.ready_for_bfs # var-length / undirected / shortestPath — needs ^KG + edges
348
+ s.ready_for_vector_search # needs node embeddings
349
+ s.ready_for_edge_search # needs edge embeddings
350
+ s.ready_for_full_text # needs BM25 index
351
+
352
+ # Example: rebuild ^KG if stale
353
+ if not s.ready_for_bfs and s.tables.edges > 0:
354
+ engine.build_graph_globals() # calls BuildKG()
355
+ ```
356
+
357
+ Sample output:
358
+ ```
359
+ IVG Engine Status
360
+ ══════════════════════════════════════════
361
+ SQL Tables (probe: 23ms)
362
+ nodes 10,000
363
+ edges 50,000
364
+ ...
365
+ Adjacency Globals
366
+ ✓ ^KG (50,000 source nodes indexed)
367
+ ✗ ^NKG (Arno integer index)
368
+ ...
369
+ ```
370
+
371
+ `status()` is explicit-call only — never run automatically at init or before queries. Cost ~50ms.
372
+
373
+ ---
374
+
338
375
  ## PLAID Multi-Vector Search
339
376
 
340
377
  ```python
@@ -583,6 +620,13 @@ anchors = engine.get_kg_anchors(icd_codes=["J18.0", "E11.9"])
583
620
 
584
621
  ## Changelog
585
622
 
623
+ ### v1.63.3 (2026-04-26)
624
+ - feat: `engine.status() -> EngineStatus` — structured runtime snapshot: SQL row counts, `^KG`/`^NKG` population, ObjectScript classes, Arno capabilities, HNSW/IVF/BM25/PLAID index inventory. Readiness properties: `ready_for_bfs`, `ready_for_vector_search`, `ready_for_edge_search`, `ready_for_full_text`. Detects `^KG`/`rdf_edges` predicate mismatch (stale ^KG from different data snapshot). (spec 080)
625
+ - fix: `BuildKG()` `Traversal.cls` SQL cursors now use fully-qualified `Graph_KG.rdf_edges`, `Graph_KG.rdf_labels`, `Graph_KG.rdf_props` — fixes predicate mismatch when IRIS namespace default SQL schema is not `Graph_KG` (e.g. MINDWALK namespace with `SQLUser` default)
626
+ - fix: `kg_IVFMeta`, `kg_BM25Meta`, `kg_PlaidMeta` added to security allowlist
627
+ - `EngineStatus` exported from top-level `iris_vector_graph`
628
+
629
+
586
630
  ### v1.63.2 (2026-04-25)
587
631
  - fix: `MATCH (a)-[r*1..N]-(b)` undirected BFS now traverses `^KG("in",...)` for inbound edges (was outbound-only)
588
632
  - fix: `MATCH (a)<-[r*1..N]-(b)` inbound-only BFS now works
@@ -13,7 +13,7 @@ ClassMethod BuildKG() As %Status
13
13
  TStart
14
14
 
15
15
  // 1. Labels
16
- &sql(DECLARE c1 CURSOR FOR SELECT s, label FROM rdf_labels)
16
+ &sql(DECLARE c1 CURSOR FOR SELECT s, label FROM Graph_KG.rdf_labels)
17
17
  &sql(OPEN c1)
18
18
  For {
19
19
  &sql(FETCH c1 INTO :s, :label)
@@ -23,7 +23,7 @@ ClassMethod BuildKG() As %Status
23
23
  &sql(CLOSE c1)
24
24
 
25
25
  // 2. Props
26
- &sql(DECLARE c2 CURSOR FOR SELECT s, key, val FROM rdf_props)
26
+ &sql(DECLARE c2 CURSOR FOR SELECT s, key, val FROM Graph_KG.rdf_props)
27
27
  &sql(OPEN c2)
28
28
  For {
29
29
  &sql(FETCH c2 INTO :s, :key, :val)
@@ -34,7 +34,7 @@ ClassMethod BuildKG() As %Status
34
34
 
35
35
  // 3. Edges & Stats (including weights)
36
36
  Set count = 0
37
- &sql(DECLARE c3 CURSOR FOR SELECT s, p, o_id, qualifiers FROM rdf_edges)
37
+ &sql(DECLARE c3 CURSOR FOR SELECT s, p, o_id, qualifiers FROM Graph_KG.rdf_edges)
38
38
  &sql(OPEN c3)
39
39
  For {
40
40
  &sql(FETCH c3 INTO :s, :p, :o, :qual)
@@ -675,4 +675,22 @@ ClassMethod DijkstraProc(srcId As %String, dstId As %String, weightProp As %Stri
675
675
  Quit ..DijkstraJson(srcId, dstId, weightProp, maxCost, maxHops, direction)
676
676
  }
677
677
 
678
+ ClassMethod KGEdgeCount(maxCount As %Integer = 10000) As %Integer
679
+ {
680
+ Set count = 0
681
+ Set s = ""
682
+ For {
683
+ Set s = $Order(^KG("out", 0, s))
684
+ Quit:s=""
685
+ Set count = count + 1
686
+ If count >= maxCount Quit
687
+ }
688
+ Return count
689
+ }
690
+
691
+ ClassMethod NKGPopulated() As %Integer
692
+ {
693
+ Return ($Data(^NKG) > 0)
694
+ }
695
+
678
696
  }
@@ -3,6 +3,7 @@ IRIS Graph Core - Domain-Agnostic Graph Engine
3
3
  """
4
4
 
5
5
  from .engine import IRISGraphEngine
6
+ from .status import EngineStatus
6
7
  from .schema import GraphSchema
7
8
  from .capabilities import IRISCapabilities
8
9
  from .vector_utils import VectorOptimizer
@@ -20,6 +20,10 @@ from iris_vector_graph.cypher.translator import (
20
20
  )
21
21
  from iris_vector_graph.schema import GraphSchema, _call_classmethod
22
22
  from iris_vector_graph.capabilities import IRISCapabilities
23
+ from iris_vector_graph.status import (
24
+ EngineStatus, TableCounts, AdjacencyStatus,
25
+ ObjectScriptStatus, ArnoStatus, IndexInventory,
26
+ )
23
27
  from iris_vector_graph.security import validate_table_name
24
28
 
25
29
  logger = logging.getLogger(__name__)
@@ -2054,6 +2058,145 @@ class IRISGraphEngine:
2054
2058
 
2055
2059
  return {"id": row_map[id_key], "labels": labels, "properties": props}
2056
2060
 
2061
+ def status(self) -> "EngineStatus":
2062
+ import time as _time
2063
+ t0 = _time.perf_counter()
2064
+ errors: list = []
2065
+ cursor = self.conn.cursor()
2066
+
2067
+ def _count(sql):
2068
+ try:
2069
+ cursor.execute(sql)
2070
+ row = cursor.fetchone()
2071
+ return int(row[0]) if row else 0
2072
+ except Exception as e:
2073
+ errors.append(f"count probe failed: {e}")
2074
+ return 0
2075
+
2076
+ tables = TableCounts(
2077
+ nodes=_count(f"SELECT COUNT(*) FROM {_table('nodes')}"),
2078
+ edges=_count(f"SELECT COUNT(*) FROM {_table('rdf_edges')}"),
2079
+ labels=_count(f"SELECT COUNT(*) FROM {_table('rdf_labels')}"),
2080
+ props=_count(f"SELECT COUNT(*) FROM {_table('rdf_props')}"),
2081
+ node_embeddings=_count(f"SELECT COUNT(*) FROM {_table('kg_NodeEmbeddings')}"),
2082
+ edge_embeddings=_count(f"SELECT COUNT(*) FROM {_table('kg_EdgeEmbeddings')}"),
2083
+ )
2084
+
2085
+ kg_count = 0
2086
+ kg_capped = False
2087
+ kg_populated = False
2088
+ nkg_populated = False
2089
+ try:
2090
+ native = self._iris_obj()
2091
+ kg_count = int(native.classMethodValue("Graph.KG.Traversal", "KGEdgeCount", 10000))
2092
+ kg_populated = kg_count > 0
2093
+ kg_capped = kg_count >= 10000
2094
+ nkg_populated = bool(int(native.classMethodValue("Graph.KG.Traversal", "NKGPopulated")))
2095
+ except Exception as e:
2096
+ try:
2097
+ iris_native = self._iris_obj()
2098
+ kg_populated = bool(iris_native.isDefined(["KG", "out"]))
2099
+ except Exception:
2100
+ errors.append(f"^KG probe failed: {e}")
2101
+
2102
+ adjacency = AdjacencyStatus(
2103
+ kg_populated=kg_populated,
2104
+ kg_edge_count=kg_count,
2105
+ kg_edge_count_capped=kg_capped,
2106
+ nkg_populated=nkg_populated,
2107
+ )
2108
+
2109
+ if kg_populated and tables.edges > 0:
2110
+ try:
2111
+ native = self._iris_obj()
2112
+ kg_pred = str(native.get(["KG", "out", 0, ""])) or ""
2113
+ if not kg_pred:
2114
+ s_val = ""
2115
+ kg_pred_node = native.orderAll(["KG", "out", 0, s_val])
2116
+ if kg_pred_node:
2117
+ kg_pred = str(native.orderAll(
2118
+ ["KG", "out", 0, str(kg_pred_node), ""]
2119
+ ) or "")
2120
+ except Exception:
2121
+ kg_pred = ""
2122
+
2123
+ if kg_pred:
2124
+ try:
2125
+ cursor.execute(
2126
+ f"SELECT COUNT(*) FROM {_table('rdf_edges')} WHERE p = ?",
2127
+ [kg_pred],
2128
+ )
2129
+ row = cursor.fetchone()
2130
+ if row and int(row[0]) == 0:
2131
+ errors.append(
2132
+ f"^KG predicate mismatch: ^KG has '{kg_pred[:60]}' "
2133
+ f"but rdf_edges has no matching p — "
2134
+ f"^KG is stale from a different data snapshot. "
2135
+ f"Run BuildKG() after reloading graph data."
2136
+ )
2137
+ except Exception:
2138
+ pass
2139
+
2140
+ os_classes = []
2141
+ os_deployed = self.capabilities.objectscript_deployed
2142
+ _known_classes = [
2143
+ "Graph.KG.Traversal", "Graph.KG.PageRank", "Graph.KG.IVFIndex",
2144
+ "Graph.KG.BM25Index", "Graph.KG.ArnoAccel", "Graph.KG.Snapshot",
2145
+ "Graph.KG.Dijkstra",
2146
+ ]
2147
+ if os_deployed:
2148
+ for cls in _known_classes:
2149
+ try:
2150
+ cursor.execute(
2151
+ "SELECT COUNT(*) FROM %Dictionary.ClassDefinition WHERE Name = ?",
2152
+ [cls],
2153
+ )
2154
+ row = cursor.fetchone()
2155
+ if row and int(row[0]) > 0:
2156
+ os_classes.append(cls)
2157
+ except Exception:
2158
+ pass
2159
+
2160
+ objectscript = ObjectScriptStatus(deployed=os_deployed, classes=os_classes)
2161
+
2162
+ self._detect_arno()
2163
+ arno = ArnoStatus(
2164
+ loaded=bool(self._arno_available),
2165
+ capabilities=dict(self._arno_capabilities),
2166
+ )
2167
+
2168
+ hnsw_built = _count(f"SELECT COUNT(*) FROM {_table('kg_NodeEmbeddings_optimized')}") > 0
2169
+
2170
+ def _list_index(sql):
2171
+ try:
2172
+ cursor.execute(sql)
2173
+ return [row[0] for row in cursor.fetchall() if row[0]]
2174
+ except Exception:
2175
+ return []
2176
+
2177
+ ivf = _list_index(f"SELECT DISTINCT name FROM {_table('kg_IVFMeta')}")
2178
+ bm25 = _list_index(f"SELECT DISTINCT name FROM {_table('kg_BM25Meta')}")
2179
+ plaid = _list_index(f"SELECT DISTINCT idx_name FROM {_table('kg_PlaidMeta')}")
2180
+
2181
+ indexes = IndexInventory(
2182
+ hnsw_built=hnsw_built,
2183
+ ivf_indexes=ivf,
2184
+ bm25_indexes=bm25,
2185
+ plaid_indexes=plaid,
2186
+ )
2187
+
2188
+ probe_ms = (_time.perf_counter() - t0) * 1000
2189
+ return EngineStatus(
2190
+ tables=tables,
2191
+ adjacency=adjacency,
2192
+ objectscript=objectscript,
2193
+ arno=arno,
2194
+ indexes=indexes,
2195
+ embedding_dimension=self.embedding_dimension,
2196
+ probe_ms=probe_ms,
2197
+ errors=errors,
2198
+ )
2199
+
2057
2200
  def count_nodes(self, label: Optional[str] = None) -> int:
2058
2201
  """
2059
2202
  Count nodes in the graph using optimized SQL.
@@ -12,7 +12,10 @@ VALID_GRAPH_TABLES = {
12
12
  "kg_EdgeEmbeddings",
13
13
  "docs",
14
14
  "fhir_bridges",
15
- "rdf_reifications"
15
+ "rdf_reifications",
16
+ "kg_IVFMeta",
17
+ "kg_BM25Meta",
18
+ "kg_PlaidMeta",
16
19
  }
17
20
 
18
21
  def sanitize_identifier(identifier: str) -> str:
@@ -0,0 +1,136 @@
1
+ from __future__ import annotations
2
+
3
+ from dataclasses import dataclass, field
4
+ from typing import Any, Dict, List
5
+
6
+
7
+ @dataclass
8
+ class TableCounts:
9
+ nodes: int = 0
10
+ edges: int = 0
11
+ labels: int = 0
12
+ props: int = 0
13
+ node_embeddings: int = 0
14
+ edge_embeddings: int = 0
15
+
16
+
17
+ @dataclass
18
+ class AdjacencyStatus:
19
+ kg_populated: bool = False
20
+ kg_edge_count: int = 0
21
+ kg_edge_count_capped: bool = False
22
+ nkg_populated: bool = False
23
+
24
+
25
+ @dataclass
26
+ class ObjectScriptStatus:
27
+ deployed: bool = False
28
+ classes: List[str] = field(default_factory=list)
29
+
30
+
31
+ @dataclass
32
+ class ArnoStatus:
33
+ loaded: bool = False
34
+ capabilities: Dict[str, Any] = field(default_factory=dict)
35
+
36
+
37
+ @dataclass
38
+ class IndexInventory:
39
+ hnsw_built: bool = False
40
+ ivf_indexes: List[str] = field(default_factory=list)
41
+ bm25_indexes: List[str] = field(default_factory=list)
42
+ plaid_indexes: List[str] = field(default_factory=list)
43
+
44
+
45
+ @dataclass
46
+ class EngineStatus:
47
+ tables: TableCounts = field(default_factory=TableCounts)
48
+ adjacency: AdjacencyStatus = field(default_factory=AdjacencyStatus)
49
+ objectscript: ObjectScriptStatus = field(default_factory=ObjectScriptStatus)
50
+ arno: ArnoStatus = field(default_factory=ArnoStatus)
51
+ indexes: IndexInventory = field(default_factory=IndexInventory)
52
+ embedding_dimension: int = 768
53
+ probe_ms: float = 0.0
54
+ errors: List[str] = field(default_factory=list)
55
+
56
+ @property
57
+ def ready_for_bfs(self) -> bool:
58
+ return self.adjacency.kg_populated and self.tables.edges > 0
59
+
60
+ @property
61
+ def ready_for_vector_search(self) -> bool:
62
+ return self.tables.node_embeddings > 0
63
+
64
+ @property
65
+ def ready_for_edge_search(self) -> bool:
66
+ return self.tables.edge_embeddings > 0
67
+
68
+ @property
69
+ def ready_for_full_text(self) -> bool:
70
+ return bool(self.indexes.bm25_indexes)
71
+
72
+ def report(self) -> str:
73
+ def tick(ok: bool) -> str:
74
+ return "✓" if ok else "✗"
75
+
76
+ kg_count = (
77
+ f"≥{self.adjacency.kg_edge_count:,}"
78
+ if self.adjacency.kg_edge_count_capped
79
+ else f"{self.adjacency.kg_edge_count:,}"
80
+ )
81
+
82
+ lines = [
83
+ "IVG Engine Status",
84
+ "═" * 50,
85
+ f"\nSQL Tables (probe: {self.probe_ms:.0f}ms)",
86
+ f" nodes {self.tables.nodes:>10,}",
87
+ f" edges {self.tables.edges:>10,}",
88
+ f" labels {self.tables.labels:>10,}",
89
+ f" properties {self.tables.props:>10,}",
90
+ f" node embeddings {self.tables.node_embeddings:>10,}",
91
+ f" edge embeddings {self.tables.edge_embeddings:>10,}",
92
+ f" embedding dim {self.embedding_dimension:>10}",
93
+ f"\nAdjacency Globals",
94
+ f" {tick(self.adjacency.kg_populated)} ^KG ({kg_count} source nodes indexed)",
95
+ f" {tick(self.adjacency.nkg_populated)} ^NKG (Arno integer index)",
96
+ ]
97
+
98
+ if not self.adjacency.kg_populated and self.tables.edges > 0:
99
+ lines.append(
100
+ " ⚠ ^KG empty but edges exist — "
101
+ "call BuildKG() or rebuild on container startup"
102
+ )
103
+
104
+ lines += [
105
+ f"\nObjectScript Classes",
106
+ f" {tick(self.objectscript.deployed)} Deployed",
107
+ ]
108
+ for cls in sorted(self.objectscript.classes):
109
+ lines.append(f" · {cls}")
110
+
111
+ lines.append(f"\nArno Accelerator")
112
+ if self.arno.loaded:
113
+ algos = [k for k, v in self.arno.capabilities.items()
114
+ if v and k not in ("nkg_data",)]
115
+ lines.append(f" ✓ Loaded — algorithms: {', '.join(algos) or 'none'}")
116
+ else:
117
+ lines.append(" ✗ Not loaded (BFS/PPR using ObjectScript fallback)")
118
+
119
+ lines += [
120
+ f"\nIndexes",
121
+ f" {tick(self.indexes.hnsw_built)} HNSW node vector index",
122
+ f" {'✓' if self.indexes.ivf_indexes else '·'} IVF: "
123
+ f"{', '.join(self.indexes.ivf_indexes) or 'none'}",
124
+ f" {'✓' if self.indexes.bm25_indexes else '·'} BM25: "
125
+ f"{', '.join(self.indexes.bm25_indexes) or 'none'}",
126
+ f" {'✓' if self.indexes.plaid_indexes else '·'} PLAID: "
127
+ f"{', '.join(self.indexes.plaid_indexes) or 'none'}",
128
+ ]
129
+
130
+ if self.errors:
131
+ lines.append(f"\nProbe errors ({len(self.errors)})")
132
+ for e in self.errors:
133
+ lines.append(f" ! {e}")
134
+
135
+ lines.append("\n" + "═" * 50)
136
+ return "\n".join(lines)
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "iris-vector-graph"
7
- version = "1.63.2"
7
+ version = "1.63.3"
8
8
  description = "Transactional Graph + Vector retrieval system for InterSystems IRIS with hybrid search, openCypher, and GraphQL APIs"
9
9
  readme = "README.md"
10
10
  license = "MIT"
@@ -552,3 +552,84 @@ class TestUndirectedBFSE2E:
552
552
  ids = {row[0] for row in result["rows"]}
553
553
  assert b in ids, f"inbound src missing: {ids}"
554
554
  assert c not in ids, f"outbound dst should not appear: {ids}"
555
+
556
+
557
+ @pytest.mark.skipif(SKIP_IRIS_TESTS, reason="SKIP_IRIS_TESTS=true")
558
+ class TestAdjacencyIndexBuilt:
559
+ """
560
+ Guard test: BFS silently returns empty results if ^KG is not populated.
561
+ This test catches the class of bug where BuildKG() was never called after
562
+ graph load (e.g. missing from iris-init.sh on container restart).
563
+ """
564
+
565
+ @pytest.fixture(autouse=True)
566
+ def setup(self, iris_connection):
567
+ from iris_vector_graph.engine import IRISGraphEngine
568
+ self.conn = iris_connection
569
+ self.engine = IRISGraphEngine(iris_connection, embedding_dimension=4)
570
+ self.engine.initialize_schema()
571
+ self._run = uuid.uuid4().hex[:8]
572
+ self._nodes = []
573
+ yield
574
+ cursor = self.conn.cursor()
575
+ for nid in self._nodes:
576
+ try:
577
+ cursor.execute("DELETE FROM Graph_KG.rdf_edges WHERE s=? OR o_id=?", [nid, nid])
578
+ cursor.execute("DELETE FROM Graph_KG.rdf_labels WHERE s=?", [nid])
579
+ cursor.execute("DELETE FROM Graph_KG.nodes WHERE node_id=?", [nid])
580
+ except Exception:
581
+ pass
582
+ try:
583
+ self.conn.commit()
584
+ except Exception:
585
+ self.conn.rollback()
586
+
587
+ def _node(self, suffix):
588
+ nid = f"adj_{self._run}_{suffix}"
589
+ self._nodes.append(nid)
590
+ self.engine.create_node(nid, labels=["Gene"])
591
+ return nid
592
+
593
+ def test_bfs_returns_results_after_edge_creation(self):
594
+ """
595
+ After create_edge(), BFS must return the neighbor.
596
+ If ^KG is empty (BuildKG never called), this returns 0 rows silently.
597
+ The real enforcement: create_edge() calls WriteAdjacency() per-edge,
598
+ so ^KG is always populated incrementally without needing a separate BuildKG.
599
+ """
600
+ src = self._node("src")
601
+ dst = self._node("dst")
602
+ self.engine.create_edge(src, "KNOWS", dst)
603
+
604
+ result = self.engine.execute_cypher(
605
+ "MATCH (a)-[r*1..1]->(b) WHERE a.id = $id RETURN b.id",
606
+ {"id": src},
607
+ )
608
+ rows = result.get("rows", [])
609
+ ids = {row[0] for row in rows}
610
+ assert dst in ids, (
611
+ f"BFS returned 0 results after create_edge(). "
612
+ f"^KG may not be populated — check that WriteAdjacency() is called "
613
+ f"in create_edge() and that BuildKG() runs on container startup "
614
+ f"(iris-init.sh) after bulk loads."
615
+ )
616
+
617
+ def test_bulk_create_edges_populates_adjacency(self):
618
+ """bulk_create_edges() calls BuildKG() in finally block — verify."""
619
+ nodes = [self._node(f"bulk_{i}") for i in range(4)]
620
+ edges = [
621
+ {"source_id": nodes[0], "predicate": "REL", "target_id": nodes[1]},
622
+ {"source_id": nodes[1], "predicate": "REL", "target_id": nodes[2]},
623
+ {"source_id": nodes[2], "predicate": "REL", "target_id": nodes[3]},
624
+ ]
625
+ self.engine.bulk_create_edges(edges)
626
+
627
+ result = self.engine.execute_cypher(
628
+ "MATCH (a)-[r*1..3]->(b) WHERE a.id = $id RETURN b.id",
629
+ {"id": nodes[0]},
630
+ )
631
+ ids = {row[0] for row in result.get("rows", [])}
632
+ assert nodes[1] in ids and nodes[3] in ids, (
633
+ f"bulk_create_edges BFS returned {ids} — expected all 3 downstream nodes. "
634
+ f"Check that BuildKG() is called in the finally block of bulk_create_edges()."
635
+ )