engraphis 1.2.2__tar.gz → 1.3.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (370) hide show
  1. {engraphis-1.2.2 → engraphis-1.3.0}/.env.example +27 -16
  2. engraphis-1.3.0/BENCHMARKS.md +333 -0
  3. {engraphis-1.2.2 → engraphis-1.3.0}/CHANGELOG.md +90 -0
  4. {engraphis-1.2.2 → engraphis-1.3.0}/Dockerfile +13 -20
  5. {engraphis-1.2.2 → engraphis-1.3.0}/MANIFEST.in +1 -0
  6. {engraphis-1.2.2 → engraphis-1.3.0}/PKG-INFO +226 -351
  7. {engraphis-1.2.2 → engraphis-1.3.0}/README.md +218 -347
  8. {engraphis-1.2.2 → engraphis-1.3.0}/docker-compose.yml +0 -29
  9. {engraphis-1.2.2 → engraphis-1.3.0}/docker-entrypoint.sh +6 -6
  10. {engraphis-1.2.2 → engraphis-1.3.0}/engraphis/__init__.py +1 -1
  11. {engraphis-1.2.2 → engraphis-1.3.0}/engraphis/app.py +103 -10
  12. engraphis-1.3.0/engraphis/backends/embedder_deterministic.py +174 -0
  13. {engraphis-1.2.2 → engraphis-1.3.0}/engraphis/backends/extractor.py +141 -29
  14. {engraphis-1.2.2 → engraphis-1.3.0}/engraphis/backends/sync_folder.py +10 -6
  15. {engraphis-1.2.2 → engraphis-1.3.0}/engraphis/classic_assets/dashboard.js +8 -7
  16. {engraphis-1.2.2 → engraphis-1.3.0}/engraphis/commercial_manifest.json +1 -1
  17. {engraphis-1.2.2 → engraphis-1.3.0}/engraphis/config.py +3 -2
  18. {engraphis-1.2.2 → engraphis-1.3.0}/engraphis/core/__init__.py +2 -0
  19. engraphis-1.3.0/engraphis/core/adaptive_context.py +97 -0
  20. {engraphis-1.2.2 → engraphis-1.3.0}/engraphis/core/consolidate.py +65 -29
  21. {engraphis-1.2.2 → engraphis-1.3.0}/engraphis/core/context.py +11 -0
  22. {engraphis-1.2.2 → engraphis-1.3.0}/engraphis/core/engine.py +463 -51
  23. {engraphis-1.2.2 → engraphis-1.3.0}/engraphis/core/grounded.py +58 -6
  24. {engraphis-1.2.2 → engraphis-1.3.0}/engraphis/core/interfaces.py +7 -0
  25. engraphis-1.3.0/engraphis/core/poisoning.py +245 -0
  26. {engraphis-1.2.2 → engraphis-1.3.0}/engraphis/core/recall.py +182 -28
  27. {engraphis-1.2.2 → engraphis-1.3.0}/engraphis/core/resolve.py +23 -26
  28. {engraphis-1.2.2 → engraphis-1.3.0}/engraphis/core/retrieval_policy.py +49 -0
  29. {engraphis-1.2.2 → engraphis-1.3.0}/engraphis/core/schema.py +9 -1
  30. {engraphis-1.2.2 → engraphis-1.3.0}/engraphis/core/scoring.py +43 -2
  31. {engraphis-1.2.2 → engraphis-1.3.0}/engraphis/core/store.py +243 -19
  32. {engraphis-1.2.2 → engraphis-1.3.0}/engraphis/core/sync.py +175 -7
  33. {engraphis-1.2.2 → engraphis-1.3.0}/engraphis/dashboard_assets/engraphis-graph.js +143 -14
  34. {engraphis-1.2.2 → engraphis-1.3.0}/engraphis/dashboard_assets/ledger.js +3 -4
  35. {engraphis-1.2.2 → engraphis-1.3.0}/engraphis/inspector/app.py +4 -0
  36. {engraphis-1.2.2 → engraphis-1.3.0}/engraphis/mcp_server.py +60 -15
  37. {engraphis-1.2.2 → engraphis-1.3.0}/engraphis/read_only_api.py +8 -0
  38. {engraphis-1.2.2 → engraphis-1.3.0}/engraphis/routes/v2_api.py +96 -13
  39. {engraphis-1.2.2 → engraphis-1.3.0}/engraphis/service.py +325 -30
  40. {engraphis-1.2.2 → engraphis-1.3.0}/engraphis/static/dashboard.js +8 -7
  41. {engraphis-1.2.2 → engraphis-1.3.0}/engraphis.egg-info/PKG-INFO +226 -351
  42. {engraphis-1.2.2 → engraphis-1.3.0}/engraphis.egg-info/SOURCES.txt +43 -0
  43. {engraphis-1.2.2 → engraphis-1.3.0}/engraphis.egg-info/requires.txt +8 -3
  44. engraphis-1.3.0/eval/EVIDENCE.md +30 -0
  45. engraphis-1.3.0/eval/agent_benchmarks.py +630 -0
  46. {engraphis-1.2.2 → engraphis-1.3.0}/eval/benchmark.py +359 -12
  47. {engraphis-1.2.2 → engraphis-1.3.0}/eval/chunking_eval.py +53 -7
  48. engraphis-1.3.0/eval/code_agent_ab.py +238 -0
  49. engraphis-1.3.0/eval/context_economy.py +438 -0
  50. engraphis-1.3.0/eval/datasets/proactive_ranking.jsonl +5 -0
  51. engraphis-1.3.0/eval/datasets/redteam_poisoning.jsonl +9 -0
  52. engraphis-1.3.0/eval/hosted_evidence.py +554 -0
  53. engraphis-1.3.0/eval/hosted_ledger.py +439 -0
  54. engraphis-1.3.0/eval/hosted_luna.py +752 -0
  55. engraphis-1.3.0/eval/longmemeval_v2_evidence.py +256 -0
  56. {engraphis-1.2.2 → engraphis-1.3.0}/eval/performance.py +114 -4
  57. engraphis-1.3.0/eval/proactive_ranking.py +106 -0
  58. engraphis-1.3.0/eval/productivity.py +628 -0
  59. engraphis-1.3.0/eval/public_readiness.py +505 -0
  60. engraphis-1.3.0/eval/redteam_poisoning.py +526 -0
  61. engraphis-1.3.0/eval/vector_scale.py +208 -0
  62. {engraphis-1.2.2 → engraphis-1.3.0}/pyproject.toml +12 -5
  63. {engraphis-1.2.2 → engraphis-1.3.0}/scripts/check_codeql_sarif.py +36 -5
  64. {engraphis-1.2.2 → engraphis-1.3.0}/scripts/entry.py +1 -1
  65. {engraphis-1.2.2 → engraphis-1.3.0}/scripts/externalize_dashboard_assets.py +14 -1
  66. {engraphis-1.2.2 → engraphis-1.3.0}/scripts/install_shortcuts.py +71 -7
  67. engraphis-1.3.0/scripts/legacy_reference.py +57 -0
  68. {engraphis-1.2.2 → engraphis-1.3.0}/scripts/migrate_to_v2.py +89 -9
  69. engraphis-1.3.0/scripts/rescan_poisoning.py +184 -0
  70. engraphis-1.3.0/scripts/run_public_benchmark.py +408 -0
  71. {engraphis-1.2.2 → engraphis-1.3.0}/scripts/start_dashboard.py +10 -1
  72. engraphis-1.3.0/scripts/start_server.py +28 -0
  73. {engraphis-1.2.2 → engraphis-1.3.0}/scripts/sync.py +10 -2
  74. engraphis-1.3.0/scripts/test_routes.py +104 -0
  75. {engraphis-1.2.2 → engraphis-1.3.0}/scripts/update.py +113 -5
  76. {engraphis-1.2.2 → engraphis-1.3.0}/scripts/verify_distribution_contents.py +2 -0
  77. engraphis-1.3.0/tests/test_adaptive_context.py +470 -0
  78. {engraphis-1.2.2 → engraphis-1.3.0}/tests/test_app_auth.py +12 -10
  79. {engraphis-1.2.2 → engraphis-1.3.0}/tests/test_backends_factories.py +77 -0
  80. {engraphis-1.2.2 → engraphis-1.3.0}/tests/test_benchmark_evidence.py +220 -6
  81. {engraphis-1.2.2 → engraphis-1.3.0}/tests/test_chunking_eval.py +27 -0
  82. {engraphis-1.2.2 → engraphis-1.3.0}/tests/test_chunking_extractor.py +123 -2
  83. {engraphis-1.2.2 → engraphis-1.3.0}/tests/test_cli_entrypoints.py +9 -0
  84. engraphis-1.3.0/tests/test_code_agent_ab.py +142 -0
  85. {engraphis-1.2.2 → engraphis-1.3.0}/tests/test_codeql_sarif_gate.py +23 -0
  86. {engraphis-1.2.2 → engraphis-1.3.0}/tests/test_commercial_hardening.py +3 -1
  87. {engraphis-1.2.2 → engraphis-1.3.0}/tests/test_consolidate.py +182 -0
  88. engraphis-1.3.0/tests/test_context_economy.py +255 -0
  89. {engraphis-1.2.2 → engraphis-1.3.0}/tests/test_context_packing.py +35 -0
  90. {engraphis-1.2.2 → engraphis-1.3.0}/tests/test_core_store.py +4 -3
  91. {engraphis-1.2.2 → engraphis-1.3.0}/tests/test_dashboard_auth_placement.py +6 -6
  92. {engraphis-1.2.2 → engraphis-1.3.0}/tests/test_dashboard_v2.py +120 -7
  93. engraphis-1.3.0/tests/test_embeddings.py +45 -0
  94. {engraphis-1.2.2 → engraphis-1.3.0}/tests/test_engine.py +92 -2
  95. engraphis-1.3.0/tests/test_eval_agent_benchmarks.py +357 -0
  96. {engraphis-1.2.2 → engraphis-1.3.0}/tests/test_eval_harness.py +4 -0
  97. {engraphis-1.2.2 → engraphis-1.3.0}/tests/test_eval_performance.py +53 -1
  98. engraphis-1.3.0/tests/test_eval_redteam_poisoning.py +150 -0
  99. {engraphis-1.2.2 → engraphis-1.3.0}/tests/test_externalize_dashboard_assets.py +15 -0
  100. {engraphis-1.2.2 → engraphis-1.3.0}/tests/test_graph_engine_asset.py +55 -7
  101. {engraphis-1.2.2 → engraphis-1.3.0}/tests/test_graph_explorer_v2.py +1 -1
  102. {engraphis-1.2.2 → engraphis-1.3.0}/tests/test_grounded.py +161 -0
  103. engraphis-1.3.0/tests/test_hosted_evidence.py +238 -0
  104. engraphis-1.3.0/tests/test_hosted_ledger.py +194 -0
  105. engraphis-1.3.0/tests/test_hosted_luna.py +376 -0
  106. engraphis-1.3.0/tests/test_install_shortcuts.py +96 -0
  107. engraphis-1.3.0/tests/test_legacy_reference_surface.py +72 -0
  108. {engraphis-1.2.2 → engraphis-1.3.0}/tests/test_licensing_boundary_docs.py +27 -8
  109. engraphis-1.3.0/tests/test_longmemeval_v2_evidence.py +157 -0
  110. {engraphis-1.2.2 → engraphis-1.3.0}/tests/test_mcp_server.py +40 -7
  111. {engraphis-1.2.2 → engraphis-1.3.0}/tests/test_memory_routes_fixes.py +13 -4
  112. {engraphis-1.2.2 → engraphis-1.3.0}/tests/test_migration.py +35 -0
  113. {engraphis-1.2.2 → engraphis-1.3.0}/tests/test_packaging.py +5 -1
  114. engraphis-1.3.0/tests/test_poisoning.py +431 -0
  115. {engraphis-1.2.2 → engraphis-1.3.0}/tests/test_pro_cta.py +11 -4
  116. engraphis-1.3.0/tests/test_proactive_ranking.py +48 -0
  117. engraphis-1.3.0/tests/test_productivity_eval.py +339 -0
  118. {engraphis-1.2.2 → engraphis-1.3.0}/tests/test_provenance_flags.py +1 -1
  119. engraphis-1.3.0/tests/test_provider_docs.py +89 -0
  120. engraphis-1.3.0/tests/test_public_benchmark_workflow.py +62 -0
  121. engraphis-1.3.0/tests/test_public_readiness.py +299 -0
  122. engraphis-1.3.0/tests/test_public_retrieval_benchmark_workflow.py +85 -0
  123. engraphis-1.3.0/tests/test_railway_runtime.py +81 -0
  124. {engraphis-1.2.2 → engraphis-1.3.0}/tests/test_read_only_api.py +33 -2
  125. {engraphis-1.2.2 → engraphis-1.3.0}/tests/test_ready.py +4 -4
  126. {engraphis-1.2.2 → engraphis-1.3.0}/tests/test_recall.py +134 -0
  127. {engraphis-1.2.2 → engraphis-1.3.0}/tests/test_receipts.py +121 -0
  128. {engraphis-1.2.2 → engraphis-1.3.0}/tests/test_release_infrastructure.py +18 -9
  129. engraphis-1.3.0/tests/test_rescan_poisoning.py +183 -0
  130. {engraphis-1.2.2 → engraphis-1.3.0}/tests/test_resolve.py +37 -10
  131. {engraphis-1.2.2 → engraphis-1.3.0}/tests/test_retrieval_policy.py +75 -0
  132. engraphis-1.3.0/tests/test_run_public_benchmark.py +176 -0
  133. {engraphis-1.2.2 → engraphis-1.3.0}/tests/test_service.py +113 -5
  134. {engraphis-1.2.2 → engraphis-1.3.0}/tests/test_service_graph.py +13 -2
  135. {engraphis-1.2.2 → engraphis-1.3.0}/tests/test_session_idempotent.py +41 -0
  136. {engraphis-1.2.2 → engraphis-1.3.0}/tests/test_start_dashboard.py +16 -0
  137. {engraphis-1.2.2 → engraphis-1.3.0}/tests/test_store_v4_migration.py +8 -8
  138. {engraphis-1.2.2 → engraphis-1.3.0}/tests/test_sync.py +321 -6
  139. {engraphis-1.2.2 → engraphis-1.3.0}/tests/test_sync_cli.py +17 -0
  140. {engraphis-1.2.2 → engraphis-1.3.0}/tests/test_update.py +54 -0
  141. {engraphis-1.2.2 → engraphis-1.3.0}/tests/test_v1_hardening.py +6 -6
  142. {engraphis-1.2.2 → engraphis-1.3.0}/tests/test_v1_licensing.py +4 -3
  143. engraphis-1.3.0/tests/test_vector_scale.py +39 -0
  144. engraphis-1.2.2/BENCHMARKS.md +0 -147
  145. engraphis-1.2.2/engraphis/backends/embedder_deterministic.py +0 -54
  146. engraphis-1.2.2/scripts/start_server.py +0 -91
  147. engraphis-1.2.2/scripts/test_routes.py +0 -198
  148. {engraphis-1.2.2 → engraphis-1.3.0}/LICENSE +0 -0
  149. {engraphis-1.2.2 → engraphis-1.3.0}/NOTICE +0 -0
  150. {engraphis-1.2.2 → engraphis-1.3.0}/engraphis/ai_context.py +0 -0
  151. {engraphis-1.2.2 → engraphis-1.3.0}/engraphis/backends/__init__.py +0 -0
  152. {engraphis-1.2.2 → engraphis-1.3.0}/engraphis/backends/codegraph.py +0 -0
  153. {engraphis-1.2.2 → engraphis-1.3.0}/engraphis/backends/embedder_api.py +0 -0
  154. {engraphis-1.2.2 → engraphis-1.3.0}/engraphis/backends/embedder_st.py +0 -0
  155. {engraphis-1.2.2 → engraphis-1.3.0}/engraphis/backends/encrypted_db.py +0 -0
  156. {engraphis-1.2.2 → engraphis-1.3.0}/engraphis/backends/graph_extractor.py +0 -0
  157. {engraphis-1.2.2 → engraphis-1.3.0}/engraphis/backends/postgres_schema.py +0 -0
  158. {engraphis-1.2.2 → engraphis-1.3.0}/engraphis/backends/reranker.py +0 -0
  159. {engraphis-1.2.2 → engraphis-1.3.0}/engraphis/backends/resources.py +0 -0
  160. {engraphis-1.2.2 → engraphis-1.3.0}/engraphis/backends/retention.py +0 -0
  161. {engraphis-1.2.2 → engraphis-1.3.0}/engraphis/backends/sync_relay.py +0 -0
  162. {engraphis-1.2.2 → engraphis-1.3.0}/engraphis/backends/vector_numpy.py +0 -0
  163. {engraphis-1.2.2 → engraphis-1.3.0}/engraphis/backends/vector_sqlitevec.py +0 -0
  164. {engraphis-1.2.2 → engraphis-1.3.0}/engraphis/classic_assets/__init__.py +0 -0
  165. {engraphis-1.2.2 → engraphis-1.3.0}/engraphis/classic_assets/dashboard.css +0 -0
  166. {engraphis-1.2.2 → engraphis-1.3.0}/engraphis/classic_assets/engraphis-graph.js +0 -0
  167. {engraphis-1.2.2 → engraphis-1.3.0}/engraphis/classic_assets/engraphis-icon.png +0 -0
  168. {engraphis-1.2.2 → engraphis-1.3.0}/engraphis/classic_assets/engraphis.ico +0 -0
  169. {engraphis-1.2.2 → engraphis-1.3.0}/engraphis/classic_assets/favicon-32.png +0 -0
  170. {engraphis-1.2.2 → engraphis-1.3.0}/engraphis/classic_assets/index.html +0 -0
  171. {engraphis-1.2.2 → engraphis-1.3.0}/engraphis/classic_assets/vendor/d3.LICENSE +0 -0
  172. {engraphis-1.2.2 → engraphis-1.3.0}/engraphis/classic_assets/vendor/d3.min.js +0 -0
  173. {engraphis-1.2.2 → engraphis-1.3.0}/engraphis/classic_assets/vendor/force-graph.LICENSE +0 -0
  174. {engraphis-1.2.2 → engraphis-1.3.0}/engraphis/classic_assets/vendor/force-graph.min.js +0 -0
  175. {engraphis-1.2.2 → engraphis-1.3.0}/engraphis/classic_assets/vendor/marked.LICENSE +0 -0
  176. {engraphis-1.2.2 → engraphis-1.3.0}/engraphis/classic_assets/vendor/marked.min.js +0 -0
  177. {engraphis-1.2.2 → engraphis-1.3.0}/engraphis/classic_assets/vendor/purify.min.js +0 -0
  178. {engraphis-1.2.2 → engraphis-1.3.0}/engraphis/cloud_features.py +0 -0
  179. {engraphis-1.2.2 → engraphis-1.3.0}/engraphis/cloud_session.py +0 -0
  180. {engraphis-1.2.2 → engraphis-1.3.0}/engraphis/commercial.py +0 -0
  181. {engraphis-1.2.2 → engraphis-1.3.0}/engraphis/core/codegraph_export.py +0 -0
  182. {engraphis-1.2.2 → engraphis-1.3.0}/engraphis/core/conflicts.py +0 -0
  183. {engraphis-1.2.2 → engraphis-1.3.0}/engraphis/core/graph_layers.py +0 -0
  184. {engraphis-1.2.2 → engraphis-1.3.0}/engraphis/core/graph_scene.py +0 -0
  185. {engraphis-1.2.2 → engraphis-1.3.0}/engraphis/core/graphrank.py +0 -0
  186. {engraphis-1.2.2 → engraphis-1.3.0}/engraphis/core/ids.py +0 -0
  187. {engraphis-1.2.2 → engraphis-1.3.0}/engraphis/core/textutil.py +0 -0
  188. {engraphis-1.2.2 → engraphis-1.3.0}/engraphis/core/user_model.py +0 -0
  189. {engraphis-1.2.2 → engraphis-1.3.0}/engraphis/dashboard_app.py +0 -0
  190. {engraphis-1.2.2 → engraphis-1.3.0}/engraphis/dashboard_assets/__init__.py +0 -0
  191. {engraphis-1.2.2 → engraphis-1.3.0}/engraphis/dashboard_assets/engraphis-graph-compat.js +0 -0
  192. {engraphis-1.2.2 → engraphis-1.3.0}/engraphis/dashboard_assets/engraphis-icon.png +0 -0
  193. {engraphis-1.2.2 → engraphis-1.3.0}/engraphis/dashboard_assets/engraphis.ico +0 -0
  194. {engraphis-1.2.2 → engraphis-1.3.0}/engraphis/dashboard_assets/favicon-32.png +0 -0
  195. {engraphis-1.2.2 → engraphis-1.3.0}/engraphis/dashboard_assets/index.html +0 -0
  196. {engraphis-1.2.2 → engraphis-1.3.0}/engraphis/dashboard_assets/ledger.css +0 -0
  197. {engraphis-1.2.2 → engraphis-1.3.0}/engraphis/dashboard_assets/vendor/d3.LICENSE +0 -0
  198. {engraphis-1.2.2 → engraphis-1.3.0}/engraphis/dashboard_assets/vendor/d3.min.js +0 -0
  199. {engraphis-1.2.2 → engraphis-1.3.0}/engraphis/dashboard_assets/vendor/force-graph.LICENSE +0 -0
  200. {engraphis-1.2.2 → engraphis-1.3.0}/engraphis/dashboard_assets/vendor/force-graph.min.js +0 -0
  201. {engraphis-1.2.2 → engraphis-1.3.0}/engraphis/device_connect.py +0 -0
  202. {engraphis-1.2.2 → engraphis-1.3.0}/engraphis/engines/__init__.py +0 -0
  203. {engraphis-1.2.2 → engraphis-1.3.0}/engraphis/engines/embedder.py +0 -0
  204. {engraphis-1.2.2 → engraphis-1.3.0}/engraphis/engines/ingest.py +0 -0
  205. {engraphis-1.2.2 → engraphis-1.3.0}/engraphis/engines/intelligence.py +0 -0
  206. {engraphis-1.2.2 → engraphis-1.3.0}/engraphis/engines/recall.py +0 -0
  207. {engraphis-1.2.2 → engraphis-1.3.0}/engraphis/engines/reweight.py +0 -0
  208. {engraphis-1.2.2 → engraphis-1.3.0}/engraphis/engines/thoughts.py +0 -0
  209. {engraphis-1.2.2 → engraphis-1.3.0}/engraphis/graphdata.py +0 -0
  210. {engraphis-1.2.2 → engraphis-1.3.0}/engraphis/hosted_client.py +0 -0
  211. {engraphis-1.2.2 → engraphis-1.3.0}/engraphis/http_security.py +0 -0
  212. {engraphis-1.2.2 → engraphis-1.3.0}/engraphis/inspector/__init__.py +0 -0
  213. {engraphis-1.2.2 → engraphis-1.3.0}/engraphis/licensing.py +0 -0
  214. {engraphis-1.2.2 → engraphis-1.3.0}/engraphis/llm/__init__.py +0 -0
  215. {engraphis-1.2.2 → engraphis-1.3.0}/engraphis/llm/client.py +0 -0
  216. {engraphis-1.2.2 → engraphis-1.3.0}/engraphis/local_auth.py +0 -0
  217. {engraphis-1.2.2 → engraphis-1.3.0}/engraphis/logging_setup.py +0 -0
  218. {engraphis-1.2.2 → engraphis-1.3.0}/engraphis/mcp_cli.py +0 -0
  219. {engraphis-1.2.2 → engraphis-1.3.0}/engraphis/models.py +0 -0
  220. {engraphis-1.2.2 → engraphis-1.3.0}/engraphis/netutil.py +0 -0
  221. {engraphis-1.2.2 → engraphis-1.3.0}/engraphis/observability.py +0 -0
  222. {engraphis-1.2.2 → engraphis-1.3.0}/engraphis/private_state.py +0 -0
  223. {engraphis-1.2.2 → engraphis-1.3.0}/engraphis/redirector.py +0 -0
  224. {engraphis-1.2.2 → engraphis-1.3.0}/engraphis/routes/__init__.py +0 -0
  225. {engraphis-1.2.2 → engraphis-1.3.0}/engraphis/routes/memory.py +0 -0
  226. {engraphis-1.2.2 → engraphis-1.3.0}/engraphis/routes/vault.py +0 -0
  227. {engraphis-1.2.2 → engraphis-1.3.0}/engraphis/static/__init__.py +0 -0
  228. {engraphis-1.2.2 → engraphis-1.3.0}/engraphis/static/dashboard.css +0 -0
  229. {engraphis-1.2.2 → engraphis-1.3.0}/engraphis/static/engraphis-graph.js +0 -0
  230. {engraphis-1.2.2 → engraphis-1.3.0}/engraphis/static/engraphis-icon.png +0 -0
  231. {engraphis-1.2.2 → engraphis-1.3.0}/engraphis/static/engraphis.ico +0 -0
  232. {engraphis-1.2.2 → engraphis-1.3.0}/engraphis/static/favicon-32.png +0 -0
  233. {engraphis-1.2.2 → engraphis-1.3.0}/engraphis/static/index.html +0 -0
  234. {engraphis-1.2.2 → engraphis-1.3.0}/engraphis/static/vendor/d3.LICENSE +0 -0
  235. {engraphis-1.2.2 → engraphis-1.3.0}/engraphis/static/vendor/d3.min.js +0 -0
  236. {engraphis-1.2.2 → engraphis-1.3.0}/engraphis/static/vendor/force-graph.LICENSE +0 -0
  237. {engraphis-1.2.2 → engraphis-1.3.0}/engraphis/static/vendor/force-graph.min.js +0 -0
  238. {engraphis-1.2.2 → engraphis-1.3.0}/engraphis/static/vendor/marked.LICENSE +0 -0
  239. {engraphis-1.2.2 → engraphis-1.3.0}/engraphis/static/vendor/marked.min.js +0 -0
  240. {engraphis-1.2.2 → engraphis-1.3.0}/engraphis/static/vendor/purify.min.js +0 -0
  241. {engraphis-1.2.2 → engraphis-1.3.0}/engraphis/stores/__init__.py +0 -0
  242. {engraphis-1.2.2 → engraphis-1.3.0}/engraphis/stores/graph.py +0 -0
  243. {engraphis-1.2.2 → engraphis-1.3.0}/engraphis/stores/ledger.py +0 -0
  244. {engraphis-1.2.2 → engraphis-1.3.0}/engraphis/stores/vaults.py +0 -0
  245. {engraphis-1.2.2 → engraphis-1.3.0}/engraphis/stores/vectors.py +0 -0
  246. {engraphis-1.2.2 → engraphis-1.3.0}/engraphis/update_check.py +0 -0
  247. {engraphis-1.2.2 → engraphis-1.3.0}/engraphis.egg-info/dependency_links.txt +0 -0
  248. {engraphis-1.2.2 → engraphis-1.3.0}/engraphis.egg-info/entry_points.txt +0 -0
  249. {engraphis-1.2.2 → engraphis-1.3.0}/engraphis.egg-info/top_level.txt +0 -0
  250. {engraphis-1.2.2 → engraphis-1.3.0}/eval/BASELINES.md +0 -0
  251. {engraphis-1.2.2 → engraphis-1.3.0}/eval/__init__.py +0 -0
  252. {engraphis-1.2.2 → engraphis-1.3.0}/eval/ablation.py +0 -0
  253. {engraphis-1.2.2 → engraphis-1.3.0}/eval/configs/longmemeval_v2_engraphis.json +0 -0
  254. {engraphis-1.2.2 → engraphis-1.3.0}/eval/datasets/adversarial.jsonl +0 -0
  255. {engraphis-1.2.2 → engraphis-1.3.0}/eval/datasets/codemem.jsonl +0 -0
  256. {engraphis-1.2.2 → engraphis-1.3.0}/eval/datasets/graph_multihop.jsonl +0 -0
  257. {engraphis-1.2.2 → engraphis-1.3.0}/eval/datasets/longdoc.jsonl +0 -0
  258. {engraphis-1.2.2 → engraphis-1.3.0}/eval/datasets/sample.jsonl +0 -0
  259. {engraphis-1.2.2 → engraphis-1.3.0}/eval/external.py +0 -0
  260. {engraphis-1.2.2 → engraphis-1.3.0}/eval/grounded.py +0 -0
  261. {engraphis-1.2.2 → engraphis-1.3.0}/eval/harness.py +0 -0
  262. {engraphis-1.2.2 → engraphis-1.3.0}/eval/longmemeval_v2.py +0 -0
  263. {engraphis-1.2.2 → engraphis-1.3.0}/eval/metrics.py +0 -0
  264. {engraphis-1.2.2 → engraphis-1.3.0}/eval/run_longmemeval_v2.py +0 -0
  265. {engraphis-1.2.2 → engraphis-1.3.0}/railway.json +0 -0
  266. {engraphis-1.2.2 → engraphis-1.3.0}/requirements.txt +0 -0
  267. {engraphis-1.2.2 → engraphis-1.3.0}/scripts/__init__.py +0 -0
  268. {engraphis-1.2.2 → engraphis-1.3.0}/scripts/backfill_graph.py +0 -0
  269. {engraphis-1.2.2 → engraphis-1.3.0}/scripts/check_commercial_manifest.py +0 -0
  270. {engraphis-1.2.2 → engraphis-1.3.0}/scripts/cli.py +0 -0
  271. {engraphis-1.2.2 → engraphis-1.3.0}/scripts/connect.py +0 -0
  272. {engraphis-1.2.2 → engraphis-1.3.0}/scripts/consolidate.py +0 -0
  273. {engraphis-1.2.2 → engraphis-1.3.0}/scripts/graph_cli.py +0 -0
  274. {engraphis-1.2.2 → engraphis-1.3.0}/scripts/graph_server.py +0 -0
  275. {engraphis-1.2.2 → engraphis-1.3.0}/scripts/init.py +0 -0
  276. {engraphis-1.2.2 → engraphis-1.3.0}/scripts/inspector.py +0 -0
  277. {engraphis-1.2.2 → engraphis-1.3.0}/scripts/mcp_server_http.py +0 -0
  278. {engraphis-1.2.2 → engraphis-1.3.0}/scripts/release_evidence.py +0 -0
  279. {engraphis-1.2.2 → engraphis-1.3.0}/scripts/repair_embed_dim.py +0 -0
  280. {engraphis-1.2.2 → engraphis-1.3.0}/scripts/sdk_compat.py +0 -0
  281. {engraphis-1.2.2 → engraphis-1.3.0}/scripts/seed_from_obsidian.py +0 -0
  282. {engraphis-1.2.2 → engraphis-1.3.0}/scripts/verify_release_artifacts.py +0 -0
  283. {engraphis-1.2.2 → engraphis-1.3.0}/setup.cfg +0 -0
  284. {engraphis-1.2.2 → engraphis-1.3.0}/setup.py +0 -0
  285. {engraphis-1.2.2 → engraphis-1.3.0}/tests/__init__.py +0 -0
  286. {engraphis-1.2.2 → engraphis-1.3.0}/tests/conftest.py +0 -0
  287. {engraphis-1.2.2 → engraphis-1.3.0}/tests/test_agent_connect.py +0 -0
  288. {engraphis-1.2.2 → engraphis-1.3.0}/tests/test_benchmark_adversarial.py +0 -0
  289. {engraphis-1.2.2 → engraphis-1.3.0}/tests/test_benchmark_longmemeval_v2.py +0 -0
  290. {engraphis-1.2.2 → engraphis-1.3.0}/tests/test_bitemporal_recall.py +0 -0
  291. {engraphis-1.2.2 → engraphis-1.3.0}/tests/test_canonical_export.py +0 -0
  292. {engraphis-1.2.2 → engraphis-1.3.0}/tests/test_client_launch.py +0 -0
  293. {engraphis-1.2.2 → engraphis-1.3.0}/tests/test_cloud_features.py +0 -0
  294. {engraphis-1.2.2 → engraphis-1.3.0}/tests/test_cloud_session.py +0 -0
  295. {engraphis-1.2.2 → engraphis-1.3.0}/tests/test_code_index_route_security.py +0 -0
  296. {engraphis-1.2.2 → engraphis-1.3.0}/tests/test_code_recall_arm.py +0 -0
  297. {engraphis-1.2.2 → engraphis-1.3.0}/tests/test_codegraph.py +0 -0
  298. {engraphis-1.2.2 → engraphis-1.3.0}/tests/test_compact_recall.py +0 -0
  299. {engraphis-1.2.2 → engraphis-1.3.0}/tests/test_config.py +0 -0
  300. {engraphis-1.2.2 → engraphis-1.3.0}/tests/test_conflicts.py +0 -0
  301. {engraphis-1.2.2 → engraphis-1.3.0}/tests/test_core_ids.py +0 -0
  302. {engraphis-1.2.2 → engraphis-1.3.0}/tests/test_cron_write_tools_workspace_default.py +0 -0
  303. {engraphis-1.2.2 → engraphis-1.3.0}/tests/test_customer_node_hardening.py +0 -0
  304. {engraphis-1.2.2 → engraphis-1.3.0}/tests/test_dashboard_button_regressions.py +0 -0
  305. {engraphis-1.2.2 → engraphis-1.3.0}/tests/test_dashboard_dream_ui.py +0 -0
  306. {engraphis-1.2.2 → engraphis-1.3.0}/tests/test_dashboard_security_headers_and_open_window.py +0 -0
  307. {engraphis-1.2.2 → engraphis-1.3.0}/tests/test_db_path_default.py +0 -0
  308. {engraphis-1.2.2 → engraphis-1.3.0}/tests/test_decay_idempotent.py +0 -0
  309. {engraphis-1.2.2 → engraphis-1.3.0}/tests/test_device_connect.py +0 -0
  310. {engraphis-1.2.2 → engraphis-1.3.0}/tests/test_embedder_threading.py +0 -0
  311. {engraphis-1.2.2 → engraphis-1.3.0}/tests/test_encrypted_store.py +0 -0
  312. {engraphis-1.2.2 → engraphis-1.3.0}/tests/test_encryption_dependency.py +0 -0
  313. {engraphis-1.2.2 → engraphis-1.3.0}/tests/test_eval_ablation.py +0 -0
  314. {engraphis-1.2.2 → engraphis-1.3.0}/tests/test_eval_external.py +0 -0
  315. {engraphis-1.2.2 → engraphis-1.3.0}/tests/test_eval_grounded.py +0 -0
  316. {engraphis-1.2.2 → engraphis-1.3.0}/tests/test_extractor.py +0 -0
  317. {engraphis-1.2.2 → engraphis-1.3.0}/tests/test_graph_cli.py +0 -0
  318. {engraphis-1.2.2 → engraphis-1.3.0}/tests/test_graph_extractor.py +0 -0
  319. {engraphis-1.2.2 → engraphis-1.3.0}/tests/test_graph_scene_contract.py +0 -0
  320. {engraphis-1.2.2 → engraphis-1.3.0}/tests/test_graph_server.py +0 -0
  321. {engraphis-1.2.2 → engraphis-1.3.0}/tests/test_graphdata.py +0 -0
  322. {engraphis-1.2.2 → engraphis-1.3.0}/tests/test_graphrank.py +0 -0
  323. {engraphis-1.2.2 → engraphis-1.3.0}/tests/test_hosted_client.py +0 -0
  324. {engraphis-1.2.2 → engraphis-1.3.0}/tests/test_hosted_plan_resolution.py +0 -0
  325. {engraphis-1.2.2 → engraphis-1.3.0}/tests/test_http_security.py +0 -0
  326. {engraphis-1.2.2 → engraphis-1.3.0}/tests/test_import_chunking.py +0 -0
  327. {engraphis-1.2.2 → engraphis-1.3.0}/tests/test_import_error_redaction.py +0 -0
  328. {engraphis-1.2.2 → engraphis-1.3.0}/tests/test_ingest_entities.py +0 -0
  329. {engraphis-1.2.2 → engraphis-1.3.0}/tests/test_init.py +0 -0
  330. {engraphis-1.2.2 → engraphis-1.3.0}/tests/test_inspector.py +0 -0
  331. {engraphis-1.2.2 → engraphis-1.3.0}/tests/test_inspector_pro.py +0 -0
  332. {engraphis-1.2.2 → engraphis-1.3.0}/tests/test_intent_paywall.py +0 -0
  333. {engraphis-1.2.2 → engraphis-1.3.0}/tests/test_licensing_launch.py +0 -0
  334. {engraphis-1.2.2 → engraphis-1.3.0}/tests/test_llm_config.py +0 -0
  335. {engraphis-1.2.2 → engraphis-1.3.0}/tests/test_llm_dashboard.py +0 -0
  336. {engraphis-1.2.2 → engraphis-1.3.0}/tests/test_local_auth_browser_session.py +0 -0
  337. {engraphis-1.2.2 → engraphis-1.3.0}/tests/test_logging_setup.py +0 -0
  338. {engraphis-1.2.2 → engraphis-1.3.0}/tests/test_mcp_annotation_idempotency.py +0 -0
  339. {engraphis-1.2.2 → engraphis-1.3.0}/tests/test_merge.py +0 -0
  340. {engraphis-1.2.2 → engraphis-1.3.0}/tests/test_metadata_activity_forgery.py +0 -0
  341. {engraphis-1.2.2 → engraphis-1.3.0}/tests/test_netutil.py +0 -0
  342. {engraphis-1.2.2 → engraphis-1.3.0}/tests/test_observability.py +0 -0
  343. {engraphis-1.2.2 → engraphis-1.3.0}/tests/test_personal_folders.py +0 -0
  344. {engraphis-1.2.2 → engraphis-1.3.0}/tests/test_postgres_schema.py +0 -0
  345. {engraphis-1.2.2 → engraphis-1.3.0}/tests/test_private_state_boundaries.py +0 -0
  346. {engraphis-1.2.2 → engraphis-1.3.0}/tests/test_proactive_context.py +0 -0
  347. {engraphis-1.2.2 → engraphis-1.3.0}/tests/test_protocol_upgrades.py +0 -0
  348. {engraphis-1.2.2 → engraphis-1.3.0}/tests/test_provider_error_redaction.py +0 -0
  349. {engraphis-1.2.2 → engraphis-1.3.0}/tests/test_public_research_boundary.py +0 -0
  350. {engraphis-1.2.2 → engraphis-1.3.0}/tests/test_recall_entity_workspace_widening.py +0 -0
  351. {engraphis-1.2.2 → engraphis-1.3.0}/tests/test_relay_device_credentials.py +0 -0
  352. {engraphis-1.2.2 → engraphis-1.3.0}/tests/test_release_artifacts.py +0 -0
  353. {engraphis-1.2.2 → engraphis-1.3.0}/tests/test_release_evidence.py +0 -0
  354. {engraphis-1.2.2 → engraphis-1.3.0}/tests/test_remember_atomicity.py +0 -0
  355. {engraphis-1.2.2 → engraphis-1.3.0}/tests/test_resources.py +0 -0
  356. {engraphis-1.2.2 → engraphis-1.3.0}/tests/test_retention.py +0 -0
  357. {engraphis-1.2.2 → engraphis-1.3.0}/tests/test_round17_fixes.py +0 -0
  358. {engraphis-1.2.2 → engraphis-1.3.0}/tests/test_scoring.py +0 -0
  359. {engraphis-1.2.2 → engraphis-1.3.0}/tests/test_security_fixes.py +0 -0
  360. {engraphis-1.2.2 → engraphis-1.3.0}/tests/test_service_isolation.py +0 -0
  361. {engraphis-1.2.2 → engraphis-1.3.0}/tests/test_start_session_workspace_default.py +0 -0
  362. {engraphis-1.2.2 → engraphis-1.3.0}/tests/test_sync_dashboard.py +0 -0
  363. {engraphis-1.2.2 → engraphis-1.3.0}/tests/test_sync_e2ee.py +0 -0
  364. {engraphis-1.2.2 → engraphis-1.3.0}/tests/test_update_check.py +0 -0
  365. {engraphis-1.2.2 → engraphis-1.3.0}/tests/test_user_model.py +0 -0
  366. {engraphis-1.2.2 → engraphis-1.3.0}/tests/test_v1_auto_migrate.py +0 -0
  367. {engraphis-1.2.2 → engraphis-1.3.0}/tests/test_vector_numpy.py +0 -0
  368. {engraphis-1.2.2 → engraphis-1.3.0}/tests/test_vector_sqlitevec_backend.py +0 -0
  369. {engraphis-1.2.2 → engraphis-1.3.0}/tests/test_workspace_isolation.py +0 -0
  370. {engraphis-1.2.2 → engraphis-1.3.0}/tests/test_workspace_ops.py +0 -0
@@ -53,7 +53,7 @@ ENGRAPHIS_API_TOKEN=
53
53
  # A 64-hex value is used as a raw 32-byte key; anything else is treated as a passphrase.
54
54
  # WARNING: lose this key = lose the data (no recovery). In production, inject it from a
55
55
  # secrets manager (or ENGRAPHIS_DB_KEY_FILE), NOT from this file. An existing PLAINTEXT
56
- # db cannot just be keyed — migrate it (dump → import into a fresh keyed db).
56
+ # db cannot just be keyed. Migrate it (dump → import into a fresh keyed db).
57
57
  # ENGRAPHIS_DB_KEY=
58
58
  # ...or read the key from a file (e.g. a mounted docker/k8s secret):
59
59
  # ENGRAPHIS_DB_KEY_FILE=/run/secrets/engraphis_db_key
@@ -66,6 +66,7 @@ ENGRAPHIS_EMBED_MODEL=sentence-transformers/all-MiniLM-L6-v2
66
66
 
67
67
  # ── LLM (external, you choose the provider) ─────────────────────────────────
68
68
  # Provider: openai | anthropic | google | openrouter | custom
69
+ # Copy-ready provider setups and endpoint requirements: docs/LLM_PROVIDERS.md
69
70
  # ── v2 write-path fact extraction (optional) ─────────────────────────────────
70
71
  # "none" (default): store text as given. "chunk": deterministic offline chunks.
71
72
  # "llm": free-form fact extraction. "llm_structured": schema-validated typed facts,
@@ -80,7 +81,7 @@ ENGRAPHIS_LLM_AUTO_EXTRACT=0
80
81
 
81
82
  # ── Knowledge-graph extraction (powers the dashboard Graph tab) ──────────────
82
83
  # "regex" (default): dependency-free heuristic NER runs on every ingest so the Graph tab
83
- # has nodes — no API key, safe offline. "none": disable heuristic text extraction.
84
+ # has nodes: no API key, safe offline. "none": disable heuristic text extraction.
84
85
  # Validated entity/relation metadata from "llm_structured" still feeds the graph
85
86
  # automatically. Existing memories are backfilled when a workspace graph first opens.
86
87
  ENGRAPHIS_GRAPH_EXTRACTOR=regex
@@ -122,7 +123,7 @@ ENGRAPHIS_RETENTION_SUPERVISOR=none
122
123
  # header entirely, which is what you want when a fronting proxy sets its own.
123
124
  # The default CSP is strict same-origin and contains no unsafe-inline; dashboard CSS,
124
125
  # JavaScript, and vendored libraries are served under /static.
125
- # Quote the values — both contain characters a shell would otherwise split on.
126
+ # Quote the values because both contain characters a shell would otherwise split on.
126
127
  # ENGRAPHIS_CSP="default-src 'self'; frame-ancestors 'none'" # replace the policy
127
128
  # ENGRAPHIS_CSP="" # send no CSP at all
128
129
  # ENGRAPHIS_HSTS="max-age=31536000; includeSubDomains"
@@ -140,6 +141,12 @@ ENGRAPHIS_LLM_API_KEY=sk-your-key-here
140
141
  # For openrouter / custom: the base URL of the OpenAI-compatible endpoint.
141
142
  # openrouter: https://openrouter.ai/api/v1
142
143
  # custom: https://your-endpoint/v1
144
+ # ollama: http://localhost:11434/v1
145
+ # Ollama example (replace the model with one you have pulled):
146
+ # ENGRAPHIS_LLM_PROVIDER=custom
147
+ # ENGRAPHIS_LLM_MODEL=qwen2.5-coder:latest
148
+ # ENGRAPHIS_LLM_API_KEY=ollama # must be non-empty; default local Ollama ignores it
149
+ # ENGRAPHIS_LLM_BASE_URL=http://localhost:11434/v1
143
150
  # ENGRAPHIS_LLM_BASE_URL=https://openrouter.ai/api/v1
144
151
  # Optional: extra headers (JSON string) for custom providers.
145
152
  # ENGRAPHIS_LLM_EXTRA_HEADERS={"HTTP-Referer":"https://myapp.com","X-Title":"engraphis"}
@@ -179,7 +186,7 @@ ENGRAPHIS_LLM_API_KEY=sk-your-key-here
179
186
  # The plan is resolved automatically: once this installation has reached the control plane
180
187
  # it reads the authoritative entitlement (plan and feature list) and caches it beside the
181
188
  # cloud session, so a Pro or Team badge is correct on every later boot including offline
182
- # ones. The refresh is opportunistic and runs on a background thread — it never blocks or
189
+ # ones. The refresh is opportunistic and runs on a background thread. It never blocks or
183
190
  # delays startup, and it never fails the dashboard when the cloud is unreachable. Before
184
191
  # the very first successful contact a connected installation is presented as Pro, the
185
192
  # smallest paid plan, so a paying customer is never shown the free local core.
@@ -187,7 +194,7 @@ ENGRAPHIS_LLM_API_KEY=sk-your-key-here
187
194
  # ENGRAPHIS_CLOUD_PLAN is an override for the cases automatic resolution cannot cover: an
188
195
  # air-gapped deployment, or one pinned to a short-lived ENGRAPHIS_CLOUD_ACCESS_TOKEN that
189
196
  # cannot refresh. It takes precedence over the cached entitlement. Accepts pro, team, or
190
- # free. It is presentation only — setting it grants nothing, because Engraphis Cloud
197
+ # free. It is presentation only. Setting it grants nothing, because Engraphis Cloud
191
198
  # authorizes every paid call regardless of what this client displays.
192
199
  # ENGRAPHIS_CLOUD_PLAN=team
193
200
  #
@@ -208,7 +215,7 @@ ENGRAPHIS_LLM_API_KEY=sk-your-key-here
208
215
  # snapshots, while an installation connected to Engraphis Cloud is allowed by default,
209
216
  # because connecting already accepts the terms covering managed analytics, dreaming, and
210
217
  # consolidation. This variable is an explicit operator override, not a customer-facing
211
- # setting — set it to 0 to opt a connected installation back out, or to 1 to force
218
+ # setting: set it to 0 to opt a connected installation back out, or to 1 to force
212
219
  # managed compute on regardless of session state. The cloud service remains authoritative
213
220
  # for all paid computation.
214
221
  # ENGRAPHIS_MANAGED_COMPUTE_CONSENT=0
@@ -220,54 +227,58 @@ ENGRAPHIS_LLM_API_KEY=sk-your-key-here
220
227
  # These settings are used by advanced deployments, operators, and internal
221
228
  # subsystems. Leave commented unless your deployment needs them.
222
229
 
223
- # Logging — defaults to INFO, text format.
230
+ # Logging: defaults to INFO, text format.
224
231
  # ENGRAPHIS_LOG_LEVEL=INFO
225
232
  # ENGRAPHIS_LOG_FORMAT=text
226
233
  # ENGRAPHIS_LOG_JSON=0
227
234
 
228
- # CORS — comma-separated origins allowed to call the dashboard REST API.
235
+ # CORS: comma-separated origins allowed to call the dashboard REST API.
229
236
  # Default: http://127.0.0.1:<ENGRAPHIS_PORT> and
230
237
  # http://localhost:<ENGRAPHIS_PORT>. Explicit values replace both loopback origins.
231
238
  # ENGRAPHIS_CORS_ORIGINS=https://myapp.example.com
232
239
 
233
- # Rate limiting — requests per window. Default: 0 (disabled), with a 60s window
240
+ # Rate limiting: requests per window. Default: 0 (disabled), with a 60s window
234
241
  # used when ENGRAPHIS_RATE_LIMIT is set above zero.
235
242
  # ENGRAPHIS_RATE_LIMIT=0
236
243
  # ENGRAPHIS_RATE_WINDOW=60
237
244
 
238
- # HTTPS security origin — used for HTTP-to-HTTPS redirects and security headers.
245
+ # HTTPS security origin: used for HTTP-to-HTTPS redirects and security headers.
239
246
  # ENGRAPHIS_PUBLIC_URL wins; when unset, security falls back to
240
247
  # ENGRAPHIS_DASHBOARD_URL, then the legacy ENGRAPHIS_RELAY_PUBLIC_URL setting.
241
248
  # These settings do not change CORS; configure ENGRAPHIS_CORS_ORIGINS separately.
242
249
  # ENGRAPHIS_PUBLIC_URL=https://engraphis.example.com
243
250
  # ENGRAPHIS_RELAY_PUBLIC_URL=https://relay.example.com
244
251
 
245
- # Trusted local peers — comma-separated addresses exempt from rate limiting.
252
+ # Trusted local peers: comma-separated addresses exempt from rate limiting.
246
253
  # ENGRAPHIS_LOCAL_TRUSTED_PEERS=127.0.0.1,::1
247
254
 
248
- # Import roots — semicolon-separated (Windows) or colon-separated (POSIX)
255
+ # Import roots: semicolon-separated (Windows) or colon-separated (POSIX)
249
256
  # directories allowed as import sources.
250
257
  # ENGRAPHIS_IMPORT_ROOTS=/srv/docs:/home/user/notes
251
258
 
252
- # Memory engine tuning — decay halflife (days), chunk sizing (tokens),
259
+ # Memory engine tuning: decay halflife (days), chunk sizing (tokens),
253
260
  # proactive context loop, and reranker model.
254
261
  # ENGRAPHIS_DECAY_HALFLIFE_DAYS=30
255
262
  # ENGRAPHIS_CHUNK_TOKENS=512
256
263
  # ENGRAPHIS_CHUNK_MAX=2048
257
264
  # ENGRAPHIS_CHUNK_OVERLAP=64
265
+ # Optional reader-tokenizer parity for chunk sizes (requires transformers).
266
+ # Pin the revision when the resulting memories support reproducible evidence.
267
+ # ENGRAPHIS_CHUNK_TOKENIZER_MODEL=Qwen/Qwen3.5-9B
268
+ # ENGRAPHIS_CHUNK_TOKENIZER_REVISION=<immutable model commit>
258
269
  # ENGRAPHIS_LOOP_INTERVAL=300
259
270
  # ENGRAPHIS_LOOP_TOP_K=10
260
271
  # ENGRAPHIS_RERANK_MODEL=cross-encoder/ms-marco-MiniLM-L-6-v2
261
272
 
262
- # Workspace allow-list — comma-separated names. Empty = all allowed.
273
+ # Workspace allow-list: comma-separated names. Empty = all allowed.
263
274
  # ENGRAPHIS_WORKSPACES=acme,personal
264
275
 
265
- # Cloud Sync relay — endpoint and optional token for self-hosted relay.
276
+ # Cloud Sync relay: endpoint and optional token for self-hosted relay.
266
277
  # ENGRAPHIS_RELAY_URL=https://relay.example.com
267
278
  # ENGRAPHIS_SYNC_TOKEN=
268
279
  # ENGRAPHIS_SYNC_READ_ONLY=0
269
280
 
270
- # Hosted plan upgrade URLs — override the default upgrade landing pages.
281
+ # Hosted plan upgrade URLs: override the default upgrade landing pages.
271
282
  # ENGRAPHIS_UPGRADE_URL=
272
283
  # ENGRAPHIS_PRO_UPGRADE_URL=
273
284
  # ENGRAPHIS_TEAM_UPGRADE_URL=
@@ -0,0 +1,333 @@
1
+ # Benchmarks
2
+
3
+ This guide explains what Engraphis measures, how to reproduce each evaluation, and the limits of
4
+ those results. When this document and the code disagree, the code is the source of truth.
5
+
6
+ For the locked operator sequence for a public canonical run, see
7
+ [`docs/PUBLIC_BENCHMARK_RUNBOOK.md`](docs/PUBLIC_BENCHMARK_RUNBOOK.md).
8
+
9
+ ## What we measure today (all offline, no API key)
10
+
11
+ Most Engraphis evals score **retrieval**, not end-to-end QA. The separate productivity benchmark
12
+ runs a complete offline agent attempt and correction loop, but it is not an official
13
+ frontier-model QA score.
14
+
15
+ - **Correctness gate**: `eval/harness.py` over `eval/datasets/sample.jsonl` and
16
+ `codemem.jsonl` (conflict resolution) and `graph_multihop.jsonl` (multi-hop graph recall).
17
+ Runs on the deterministic embedder, so it is a plumbing/regression floor, not a public
18
+ performance claim. This is the gate CI enforces.
19
+ - **Ablation**: `eval/ablation.py`: vector-only vs. 1-hop graph vs. Personalized-PageRank arm,
20
+ to show the graph arm actually earns its place.
21
+ - **External benchmarks**: `eval/external.py` loads **LoCoMo** and **LongMemEval** and pushes
22
+ them through the *real* `MemoryEngine` write path (conflict resolution + evolution) and hybrid
23
+ recall with a real sentence-transformers embedder. It reports `recall_at_k` / `hit_at_k` /
24
+ `answer_token_recall`: i.e. *did the evidence come back*, not *did an LLM answer correctly*.
25
+ It retains source categories and abstention/no-evidence questions as explicit exclusions from
26
+ retrieval-only aggregates rather than silently dropping them. `eval.longmemeval_v2` is a local,
27
+ text-only adapter for the official LongMemEval-V2 `insert(trajectory)` / `query(query,
28
+ query_image=None)` memory interface; it does not download data or call a model.
29
+ - **Grounded**: `eval/grounded.py`: answerable → cite, off-topic → abstain.
30
+ - **Chunking (quality per token)**: `eval/chunking_eval.py` over `eval/datasets/longdoc.jsonl`
31
+ ingests a multi-topic corpus twice: once as one memory per document (`whole`) and once with
32
+ sub-file `ChunkingExtractor` (`chunked`), then queries both through the real recall pipeline.
33
+ The checked-in corpus is explicitly marked trusted eval data so the measurement isolates
34
+ chunking from the production trust gate, which excludes arbitrary raw imports from normal
35
+ agent context. This is the first cut of the context-reduction metric (item 3 below). On the
36
+ deterministic embedder:
37
+ **recall@5 1.000 for both, at ~73% fewer context tokens (809 → 219) and ~4× smaller
38
+ tokens-to-evidence (162 → 42).** Pass `--embed-model sentence-transformers/all-MiniLM-L6-v2`
39
+ for a real retrieval number (recall should then favour chunked on larger corpora, not just
40
+ tie).
41
+ - **Full-pipeline latency + quality**: `eval/performance.py` times the shipped semantic +
42
+ lexical + graph + fusion + scoring + rerank + packing path after warmup, with reinforcement
43
+ disabled so repeated measurements do not mutate their corpus. It reports p50/p95/p99 latency,
44
+ retrieval quality, and packed context tokens in one JSON-safe schema. `--filler-memories`
45
+ provides deterministic corpus scaling, and every report records the runtime, architecture,
46
+ embedder, vector backend, corpus size, warmups, and iteration count. `--candidate-k` and
47
+ `--retrieval-profile` make adaptive-depth/routing experiments executable instead of changing
48
+ production defaults from an unmeasured hunch.
49
+ - **NumPy vector scale envelope**: `eval/vector_scale.py` measures the production
50
+ `NumpyVectorIndex` directly at requested corpus sizes with deterministic normalized vectors and
51
+ queries. It records a corpus fingerprint, result hashes, environment, and observed
52
+ p50/p95/p99 search envelopes. It intentionally has no pass/fail latency threshold: the output
53
+ describes the measured machine and workload, not a universal capacity cutoff. Pair it with
54
+ `eval/performance.py` before making a deployment decision because direct vector search excludes
55
+ the rest of the recall pipeline. Its `engraphis-vector-scale/v1` JSON is a local diagnostic, not
56
+ an `engraphis-benchmark/v2` public evidence artifact.
57
+ - **Proactive ranking calibration**: `eval/proactive_ranking.py` compares the previous and current
58
+ importance-retention floors on a small deterministic queryless-ranking fixture. It reports
59
+ top-1 accuracy and minimum expected margins for that fixture only. It is a scoring regression,
60
+ not evidence of general recall quality or user-task performance.
61
+ - **Workload context economy**: `eval/context_economy.py` compares three executable strategies
62
+ across every question in a workload: uncapped full-history replay, a contiguous recency window
63
+ at the same hard budget, and shipped Engraphis hybrid recall + packing. It reports evidence and
64
+ answer-token quality, cumulative reader-context tokens, a conservative total that charges one
65
+ complete source-token pass to indexing, and the query-count break-even point. The default is
66
+ deterministic/offline; `--embed-model` enables a real retrieval model, while
67
+ `--format locomo|longmemeval` reuses the established external loaders.
68
+ - **Agent productivity**: `eval/productivity.py` compares a capped full-history baseline,
69
+ always-on retrieval, and
70
+ adaptive context through a complete answer-and-correction loop. It reports completed tasks,
71
+ first-attempt errors, abstentions, corrections, agent turns, memory calls, wall-clock latency,
72
+ and all question/context/output tokens. The bundled agent is deterministic, receives no gold
73
+ answer, and is identified in every report; inject a real agent callable for model-specific
74
+ results. Optional provider telemetry is reported separately from the deterministic token
75
+ counter and is not a provider billing estimate.
76
+
77
+ The workload benchmark is also allowed to say “this workload is too small for a memory layer.”
78
+ On the 44-memory / 26-question CodeMem regression fixture, every case already fits inside a
79
+ 64-token recency window. Full-history and recency therefore use the same 1,180 cumulative reader
80
+ tokens at perfect evidence/answer-token quality, while Engraphis uses 1,375–1,377 reader tokens
81
+ plus a conservative 631-token indexing pass. That is an honest no-break-even boundary result:
82
+ the benefit being measured begins when history is long or reused enough to outweigh retrieval
83
+ framing and indexing.
84
+
85
+ The adaptive policy removes that small-workload penalty. On the same 26 CodeMem tasks, every
86
+ history fit the 512-token prompt allowance, so adaptive routing bypassed all 26 memory calls.
87
+ It used **1,942** total agent-facing tokens versus **2,194** for always-on retrieval
88
+ (**11.5% lower**) while both strategies completed **24/26** tasks with the bundled deterministic
89
+ agent. This demonstrates the bypass behavior and token accounting, not general LLM intelligence.
90
+
91
+ The complementary real-model LoCoMo workload diagnostic covers 10 conversations and 1,986
92
+ questions with `all-MiniLM-L6-v2`, `k=10`, a 512-token reader budget, and conflict resolution
93
+ disabled. **This is an unpinned, noncanonical workload diagnostic of reader-context use only, not
94
+ answer quality or leaderboard accuracy.** Engraphis used **891,857** cumulative reader-context
95
+ tokens versus **49,915,394** for uncapped full history, **98.2133% lower**. Charging one complete
96
+ 246,539-token corpus pass to indexing produces a conservative Engraphis total of **1,138,396**,
97
+ still **97.7193% lower**, with a calculated break-even at query 10. The quality tradeoff is
98
+ explicit:
99
+
100
+ | LoCoMo workload method (unpinned, noncanonical context-use diagnostic; not answer quality or leaderboard accuracy) | Retrieval recall | Hit rate | Answer-token recall | Mean reader context |
101
+ |---|---:|---:|---:|---:|
102
+ | Engraphis hybrid recall | **0.600457** | **0.657417** | **0.679614** | **449.07** tokens |
103
+ | Same-budget recency window | 0.011289 | 0.012614 | 0.339941 | 487.87 tokens |
104
+ | Uncapped full history | 0.996997 | 0.997477 | 0.917247 | 25,133.63 tokens |
105
+
106
+ This diagnostic supports a precise statement: Engraphis recovered much more useful evidence than
107
+ a same-budget recency window while using a small fraction of full-history context. It does not
108
+ support “same quality as full history,” provider-billing, or end-to-end answer-accuracy claims.
109
+ The embedding model revision was not pinned in that run, so rerun it with an immutable revision
110
+ before treating the numbers as canonical release evidence.
111
+
112
+ ### Reproduce
113
+
114
+ ```bash
115
+ # Correctness gate (deterministic, no download)
116
+ python -m pytest tests/ -q
117
+ python -m eval.harness --dataset eval/datasets/sample.jsonl --k 5
118
+ python -m eval.harness --dataset eval/datasets/codemem.jsonl --k 5
119
+ python -m eval.harness --dataset eval/datasets/graph_multihop.jsonl --k 5
120
+ python -m eval.ablation
121
+ python -m eval.performance --dataset eval/datasets/codemem.jsonl --k 5 --iterations 10
122
+ python -m eval.performance --dataset eval/datasets/codemem.jsonl --k 5 \
123
+ --candidate-k 25 --candidate-depth adaptive --retrieval-profile auto --iterations 10
124
+ python -m eval.context_economy --dataset eval/datasets/codemem.jsonl \
125
+ --token-budget 512 --k 5
126
+ python -m eval.productivity --dataset eval/datasets/codemem.jsonl \
127
+ --max-context-tokens 512 --retrieval-token-budget 256
128
+ python -m eval.performance --dataset eval/datasets/codemem.jsonl --k 5 \
129
+ --iterations 5 --filler-memories 1000
130
+ # Direct NumPy search envelope at representative corpus sizes; timings are machine-specific.
131
+ python -m eval.vector_scale --sizes 1000,10000,100000 --queries 20 --iterations 3 --json
132
+ # Deterministic queryless-ranking calibration fixture.
133
+ python -m eval.proactive_ranking
134
+ # Canonical latency/resource protocol: requires >=1,000 queries and five processes.
135
+ python -m eval.performance --dataset fixed-1000-plus.jsonl --acceptance-matrix --processes 5
136
+
137
+ # Real retrieval numbers (downloads all-MiniLM-L6-v2)
138
+ python -m eval.external --dataset longmemeval_s.json --format longmemeval --k 10
139
+ python -m eval.external --dataset locomo10.json --format locomo --k 10
140
+ python -m eval.context_economy --dataset locomo10.json --format locomo \
141
+ --embed-model sentence-transformers/all-MiniLM-L6-v2 --token-budget 512 --k 10 --no-resolve
142
+ ```
143
+
144
+ ## What we do NOT yet claim
145
+
146
+ - **No official end-to-end LLM QA accuracy.** The deterministic productivity agent measures the
147
+ complete local control loop, not a frontier answering model. Official LoCoMo / LongMemEval QA
148
+ still requires a pinned answering model and evaluator.
149
+ - **No hosted-service latency comparison.** The in-repo p50/p95/p99 benchmark covers the local
150
+ reference pipeline and records its environment; unlike environments are not compared.
151
+ - **No neutral third-party ranking.** We have not run an external eval platform.
152
+ - **No provider bill estimate.** Context-economy counts reader evidence under its named counter.
153
+ It excludes system/tool prompts, questions, completions, prompt caching, provider pricing,
154
+ compute, and storage. Its indexing-inclusive total is a conservative text-volume proxy.
155
+
156
+ Every publishable run should emit the `engraphis-benchmark/v2` envelope: dataset/config hashes,
157
+ per-question records, explicit exclusions, fixed-budget context curves, and deterministic
158
+ stratified or paired bootstrap confidence intervals. Every run names its token counter.
159
+ Noncanonical offline fixtures may identify a deterministic estimate; canonical public evidence
160
+ requires the exact pinned reader tokenizer and immutable model revision. The lightweight CI
161
+ fixtures validate that machinery; they are not a claim about external benchmark performance.
162
+
163
+ The benchmark context metric reads strict recall usage fields rather than inferring prompt size:
164
+ `budget_tokens`, `context_tokens`, `source_tokens`, `saved_tokens`, `savings_ratio`,
165
+ `packed_count`, `omitted_count`, and `token_counter`. Use `engraphis_recall_context` for a
166
+ hard-budget prompt packet; legacy `engraphis_recall` remains available in full or compact response
167
+ mode for compatibility.
168
+
169
+ ### Canonical public artifacts
170
+
171
+ Use `python -m eval.benchmark --input report.json --output artifacts/run.json` to validate a
172
+ report and write sorted, immutable JSON plus `run.json.sha256`. The command permits an identical
173
+ retry but refuses to replace a different artifact at the same path. For an official
174
+ LongMemEval-V2 run, add `--canonical`: this requires a profile with an exact benchmark repository
175
+ revision, dataset revision, reader model revision, and embedding model revision. The checked-in
176
+ profile pins immutable upstream commits; replacing any revision with a mutable tag fails
177
+ validation. Canonical profiles label the baseline (`no_retrieval`, `lexical_only`, `dense_only`,
178
+ `dense_lexical_rrf`, `full_hybrid`, `full_history`, `no_graph`, `no_reranker`,
179
+ `no_temporal_resolution`, or `whole_document`) and declare the required fixed context-budget
180
+ matrix: 256, 512, 1024, 2048, and 4096 tokens. Canonical in-repo reports rerun every question at
181
+ all five budgets and validate each aggregate against its per-question evidence. The checked-in
182
+ LongMemEval-V2 memory-module configuration sets the official adapter's operating point to 1,024
183
+ tokens; that single official point must not be presented as a five-point curve.
184
+
185
+ `eval.external --canonical` refuses `--limit` and rejects a normalized output that omitted source
186
+ cases. Retrieval-only abstention/no-evidence records remain visible in the artifact's
187
+ `exclusions`; they are not counted as evidence-retrieval scores.
188
+
189
+ Official LongMemEval-V2 output can be converted into a public-safe QA artifact with
190
+ `python -m eval.longmemeval_v2_evidence`. The exporter keeps the official QA score, fixed-reader
191
+ context token count, latency, model revisions, source digests, repository state, and artifact
192
+ checksum. It removes raw questions, answers, prompts, reader output, and retrieved context before
193
+ the artifact can be written. See [`eval/EVIDENCE.md`](eval/EVIDENCE.md) for the exact command.
194
+
195
+ ### LongMemEval-V2 memory-module adapter
196
+
197
+ `eval.longmemeval_v2.EngraphisLongMemEvalV2Memory` follows the official
198
+ `memory_modules.memory.Memory` interface at LongMemEval-V2 commit
199
+ `6f020ac2fc3275e46c706d3406e02c3ed79b7be2`. When imported in that environment, its
200
+ `@register_memory` decorator registers `memory_type="engraphis"`; use the checked-in
201
+ [`eval/configs/longmemeval_v2_engraphis.json`](eval/configs/longmemeval_v2_engraphis.json)
202
+ with the official harness. The config pins `Qwen/Qwen3-Embedding-8B` to revision
203
+ `1d8ad4ca9b3dd8059ad90a75d4983776a23d44af`; mutable embedding revisions are rejected, and a
204
+ canonical adapter run fails instead of relabeling the deterministic offline fallback as Qwen.
205
+ Run `python -m eval.run_longmemeval_v2` with the official harness arguments and the pinned
206
+ checkout on `PYTHONPATH`. This wrapper performs the upstream registry import in the required order
207
+ before delegating to `evaluation.harness`; a direct upstream invocation must otherwise import
208
+ `eval.longmemeval_v2` before calling `build_memory`.
209
+
210
+ The checked-in configuration is canonical only when the adapter resolves the pinned Qwen reader
211
+ processor at `c202236235762e1c871ad0ccb60c8ee5ba337b9a`. The wrapper also forces the audited
212
+ official harness's otherwise-unpinned `AutoProcessor` call to that same revision. It refuses to
213
+ start if the optional processor dependency or immutable revision is unavailable; the local regex
214
+ counter is never silently relabeled as a reader budget. The recorded budget counts each returned
215
+ context item's content with that reader tokenizer (without prompt framing or inter-item
216
+ separators), so it is a hard **evidence-item content** budget, not a claim about total chat-prompt
217
+ tokens. Packed sources are returned as separate context items, preserving the largest fitting
218
+ evidence prefix instead of dropping one oversized monolithic item. The adapter does not download
219
+ benchmark data or call the reader/evaluator; the official harness owns those steps.
220
+
221
+ ## External evidence status and remaining executions
222
+
223
+ 1. **Run the official LongMemEval-V2 reader and evaluator.** The adapter, pinned runner, and
224
+ redacted evidence exporter are implemented. The exact upstream commit boots in an isolated
225
+ Python 3.11 environment and the wrapper reaches the official harness CLI. Dataset revision
226
+ `f152293e235517d504809563c833d7190b8c713b` publishes 7,120,369,667 bytes before the pinned
227
+ Qwen reader and embedding model assets. A full official run therefore still requires those
228
+ resources, sufficient compute, and evaluator configuration; no canonical QA score is claimed
229
+ until that run completes.
230
+ 2. **Publish production-backend latency.** Run `eval/performance.py` with the real embedder and
231
+ sqlite-vec/backend configuration on a fixed machine class and corpus scale.
232
+ 3. **Run the fixed-budget curve on the complete official datasets.** The v2 harness now measures
233
+ every question at 256, 512, 1,024, 2,048, and 4,096 evidence tokens and validates the
234
+ per-question records, aggregates, and pinned reader-tokenizer identity. Publish the curve only
235
+ after complete official runs produce immutable artifacts for every point.
236
+ 4. **Run an external evaluation platform** once (1)–(3) exist.
237
+
238
+ Do not make all evidence lanes variants of explicit factual recall. Executable offline adapters
239
+ now cover:
240
+
241
+ - [MemoryAgentBench](https://github.com/HUST-AI-HYZ/MemoryAgentBench): incremental multi-turn
242
+ learning, long-range understanding, and conflict/consolidation inputs.
243
+ - [LoCoMo-Plus](https://github.com/xjtuleeyf/Locomo-Plus): an old implicit constraint must affect
244
+ a later response even when the later cue does not restate the remembered fact.
245
+ - [Mem2ActBench](https://github.com/Cantaloupe-M/Mem2ActBench): memory must select a tool and
246
+ ground its arguments, not merely return a passage. The current adapter measures retrieval and
247
+ expected tool-argument context coverage, not generated tool-call success.
248
+
249
+ ```bash
250
+ python -m eval.agent_benchmarks --dataset memoryagentbench.json \
251
+ --format memoryagentbench
252
+ python -m eval.agent_benchmarks --dataset locomo_plus.json \
253
+ --format locomo_plus
254
+ python -m eval.agent_benchmarks --dataset qa_dataset.jsonl \
255
+ --conversations toolmem_conversation.jsonl --format mem2actbench \
256
+ --artifact artifacts/mem2actbench.json
257
+ ```
258
+
259
+ Use `--artifact` on any of these commands to write a redacted, immutable evidence envelope plus
260
+ an adjacent SHA256 file. The ordinary console/`--json` report is private run material and may
261
+ contain source questions for debugging.
262
+
263
+ ### Upstream-data diagnostic baseline (2026-07-30)
264
+
265
+ These runs use the dependency-free deterministic embedder on upstream data. They validate the
266
+ adapters and expose product gaps; they are noncanonical diagnostics, not leaderboard or marketing
267
+ claims. The artifact validator accepted every completed envelope.
268
+
269
+ | Upstream source | Executed scope | Result and boundary |
270
+ |---|---|---|
271
+ | LoCoMo-Plus commit `059f4e3d38f7f1f96765e8e2cb7de3097551bffb` | All 401 Cognitive cases, 40,270 source memories | Recall@10 **0.1259**, hit@10 **0.1272**, MRR@10 **0.0744**, answer-token context coverage **0.5095**. This is cue-evidence retrieval, not answer-judge accuracy. The low retrieval score is useful negative evidence: implicit-constraint recall remains a real product gap. |
272
+ | MemoryAgentBench commit `455306dcabc3842526eb83cd4e225e5d486c5c5d`, official Hugging Face `Accurate_Retrieval` first row | 100 questions | Recall@10 **0.5100**, hit@10 **0.8600**, answer-token context coverage **0.8500**. Gold evidence was derived only where an accepted answer occurred in a source chunk. |
273
+ | The same source, `Conflict_Resolution` first row | 100 questions | Recall@10 **0.4600**, hit@10 **0.6400**, answer-token context coverage **0.6800**. This plain-context export measures retrieval, not structured temporal invalidation. |
274
+ | The same source, `Long_Range_Understanding` first row | 1 question | Answer-token context coverage **0.2658**. The export supplied no evidence IDs and no accepted answer occurred verbatim in a source chunk, so retrieval was deliberately left unscored rather than reported as a false perfect score. |
275
+ | The same source, `Test_Time_Learning` first row | One 5.88 MB context | The no-resolution ingest did not complete within a five-minute local smoke ceiling. This is a measured large-ingest throughput gap, not a failed quality score; batch embedding and transaction work should precede a complete split run. |
276
+ | Mem2ActBench upstream smoke | 2 public rows | Recall@10, hit@10, MRR@10, and NDCG@10 **1.0000**; expected tool-call JSON token coverage **0.5714**. This is retrieval/context coverage, not generated action success. |
277
+
278
+ The MemoryAgentBench loader accepts both its aligned public JSON export and the Hugging Face
279
+ dataset-server `rows[].row` envelope. Rows without gold evidence remain useful for answer-token
280
+ coverage, but are excluded from retrieval aggregates and counted separately as
281
+ `retrieval_scored_questions`.
282
+
283
+ For paired code-agent runs, execute the same tasks with the same model, tools, machine, and
284
+ deterministic success oracle under `full_history` and `engraphis`. Then analyze the content-free
285
+ run records with:
286
+
287
+ ```bash
288
+ python -m eval.code_agent_ab --full-history full-history.jsonl \
289
+ --engraphis engraphis.jsonl --output paired-report.json
290
+ ```
291
+
292
+ The analyzer rejects unmatched task IDs and different success oracles, then reports paired
293
+ bootstrap intervals for task success, input/output/tool tokens, retries, latency, and optional
294
+ cost. Its aggregate output does not echo task IDs or oracle commands. It does not launch an agent
295
+ or invent a task-success oracle.
296
+
297
+ ## Optimization experiments to run before changing defaults
298
+
299
+ 1. **Budget-aware packing**: compare full source, safe summary, sentence-aligned safe summary
300
+ excerpt, and raw-source excerpt at fixed budgets. Gate on support/answer retention and
301
+ qualifier preservation, not token count alone.
302
+ 2. **Adaptive retrieval work**: `--candidate-depth adaptive` is now an opt-in performance
303
+ experiment. It keeps wider graph/code pools and reduces routine lexical/balanced pools while
304
+ reporting the requested and actual depth. Sample and CodeMem kept every offline quality metric
305
+ at 1.0 with balanced depth reduced from 50 to 15; CodeMem plus 1,000 fillers reduced local
306
+ median recall latency from 20.666 ms to 18.991 ms in a 260-recall comparison, an 8.1%
307
+ reduction. These are machine-specific regression results, not production latency claims. Keep
308
+ the default fixed until complete external categories meet predeclared quality margins.
309
+ 3. **Packing-pressure consolidation**: prioritize memory families that are frequently recalled,
310
+ repeatedly omitted, or costly per useful token. Count write/index/storage cost as well as later
311
+ reader-context savings.
312
+ 4. **Tokenizer-aware ingestion**: implemented behind the chunk extractor. The dependency-free
313
+ default remains `engraphis.chars4.v1`; an explicitly configured Hugging Face reader tokenizer
314
+ enforces prose chunk and overlap budgets and records its identity in chunk metadata. Continue
315
+ measuring tokens-to-evidence, recall, and storage/index growth together before recommending a
316
+ model-specific default.
317
+ 5. **Bulk ingestion**: add batch embedding plus a transaction-aware vector upsert path, then rerun
318
+ the 5.88 MB MemoryAgentBench Test-Time Learning row. Gate this on identical stored-memory,
319
+ provenance, graph-link, and temporal-resolution outcomes, not throughput alone.
320
+ 6. **Scoped caches**: benchmark query embeddings and repeat-recall results keyed by workspace,
321
+ repo, time anchors, profile, and corpus version. Test invalidation correctness before claiming
322
+ latency gains.
323
+ 7. **Privacy-safe real usage**: use `engraphis_context_savings` to let each workspace inspect
324
+ aggregate source/context/saved tokens already present in content-free receipts. Keep unlike
325
+ token counters separate and require a valid receipt chain before treating totals as auditable.
326
+
327
+ ## Evaluation question
328
+
329
+ The predeclared question is whether the full vector + lexical/BM25 + sparse PPR graph + calibrated
330
+ rerank pipeline, bi-temporal resolution, and grounded abstention produce higher evidence recall
331
+ per injected token than the registered baselines. The answer must come from a complete,
332
+ machine-readable artifact with paired confidence intervals; otherwise the release reports
333
+ “no demonstrated improvement.”
@@ -3,6 +3,96 @@
3
3
  All notable changes to Engraphis are documented here. Format loosely follows
4
4
  [Keep a Changelog](https://keepachangelog.com/); versions use SemVer.
5
5
 
6
+ ## [Unreleased]
7
+
8
+ ## [1.3.0] - 2026-08-01
9
+
10
+ ### Added
11
+
12
+ - The optional `hosted-eval` extra adds guarded hosted-Luna productivity evaluation with a
13
+ redacted public evidence exporter.
14
+ - Protected public benchmark workflows now support redacted hosted and retrieval evidence runs.
15
+
16
+ ### Security
17
+
18
+ - Untrusted ingress now fails closed: provenance and extractor metadata are allowlisted, suspicious
19
+ records are quarantined before embedding, linking, graph extraction, resolution, recall, or
20
+ grounding, and `scripts/rescan_poisoning.py` can retroactively label or quarantine old records.
21
+ - Trust is preserved across resolution, structured graph writes, consolidation, entity profiles,
22
+ and review paths. Untrusted records cannot mutate or promote trusted memory, and derived outputs
23
+ remain trusted only when every source is explicitly trusted.
24
+
25
+ ### Documentation
26
+
27
+ - README and release guidance now match the current install extras, public entry points, product
28
+ boundaries, and focused MCP/provider documentation.
29
+
30
+ ### Fixed
31
+
32
+ - Public server entry points now share the v2 service, keeping recall behavior consistent across
33
+ the dashboard, server, Compose, Classic, and MCP-over-HTTP.
34
+ - Keyed mutable-fact replacements now load their live predecessor directly, so reworded updates
35
+ preserve history without relying on vector top-K recall.
36
+ - Versioned deterministic embeddings now rebuild persisted vectors after a mapping change, keeping
37
+ existing databases searchable after an upgrade.
38
+ - Prompt-facing recall now widens candidate search when untrusted results crowd out trusted
39
+ evidence, while keeping expansion bounded. Title text now contributes to absolute support floors
40
+ for grounded and hosted recall.
41
+ - Hosted productivity evaluation now scores canonical, acceptable, or supporting-evidence answers
42
+ with strict natural-language framing instead of token containment or raw JSON text.
43
+ - Hosted-Luna workers on Windows now establish kill-on-close containment before sending input; a
44
+ failure refuses the request, and timeouts clean up the full worker tree.
45
+ - Poisoning rescans preserve existing temporal validity boundaries and invalidate affected edges
46
+ without overwriting governed history.
47
+
48
+ ### Changed
49
+
50
+ - CI and release/install metadata now cover Python 3.13 and 3.14.
51
+
52
+ ## [1.2.5] - 2026-07-31
53
+
54
+ ### Added
55
+
56
+ - `engraphis_context_savings` aggregates validated, content-free recall receipts by workspace,
57
+ repo, operation, and token-counter identity. The view is available through the service,
58
+ dashboard, and read-only APIs.
59
+ - Recall supports an explicit adaptive candidate-depth experiment while retaining the historical
60
+ fixed depth by default. Performance reports record requested and actual candidate depths.
61
+ - `MemoryEngine` and `MemoryService` now provide adaptive context routing: bypass retrieval when
62
+ prompt history fits, use compact recall when support is strong, and fall back to bounded recent
63
+ history when support is weak.
64
+ - `eval.productivity` measures task completion, corrections, agent turns, memory calls, latency,
65
+ and model-facing tokens.
66
+ - Chunk ingestion can enforce budgets with a configured Hugging Face tokenizer and records the
67
+ counter identity, target, and overlap in chunk metadata.
68
+ - Offline adapters now cover MemoryAgentBench, LoCoMo-Plus, and Mem2ActBench, with a paired
69
+ full-history versus Engraphis code-agent analyzer.
70
+ - Public benchmark evidence can carry source hashes, repository state, environment and model
71
+ provenance, secret-redacted commands and URLs, content digests, and adjacent immutable SHA-256
72
+ files.
73
+
74
+ ### Changed
75
+
76
+ - Context-economy evaluation now compares full history, a same-budget recency window, and hybrid
77
+ recall while accounting for indexing cost.
78
+ - Official LongMemEval-V2 output has a dedicated redacted evidence exporter that retains the
79
+ official QA, token, and latency measures without publishing prompts, answers, model output, or
80
+ retrieved context.
81
+ - Folder-sync dry runs no longer create a remote directory or persist a local device identity.
82
+
83
+ ### Fixed
84
+
85
+ - Sync rejects malformed scope/repo combinations and every peer-driven visibility change for an
86
+ existing memory, including malformed legacy rows. Scope promotion or repair remains a local,
87
+ explicit governance operation.
88
+ - Workspace consolidation excludes session-private memories and partitions digests and entity
89
+ profiles by their exact visibility owner, preventing cross-repo or cross-scope summaries.
90
+ - Tokenizer-aware chunk overlap can no longer exceed the configured prose budget or emit a
91
+ duplicate overlap-only record before an oversized paragraph. Invalid token counters fail
92
+ closed instead of silently producing mis-sized chunks.
93
+ - Ledger graph interactions preserve manually selected nodes during refreshes.
94
+ - The new evidence guide is included in wheel and source distributions.
95
+
6
96
  ## [1.2.2] - 2026-07-30
7
97
 
8
98
  ### Fixed
@@ -1,12 +1,10 @@
1
1
  # Engraphis — self-hosted AI memory engine. Local-first; you bring the LLM.
2
2
  FROM python:3.11-slim AS base
3
3
 
4
- # ENGRAPHIS_HOST is deliberately NOT set here: docker-entrypoint.sh picks the widest
5
- # workable bind at runtime — `::` (dual-stack: IPv6 AND IPv4) when the kernel has IPv6,
6
- # else 0.0.0.0. Railway healthchecks arrive over the IPv6 private network, so a baked-in
7
- # IPv4-only bind is exactly what caused the 2026-07-16 deploy outage; hard-coding `::`
8
- # instead would break rarer IPv6-disabled hosts. An explicit ENGRAPHIS_HOST env (e.g.
9
- # docker-compose.yml's 0.0.0.0) always wins over the entrypoint's default.
4
+ # ENGRAPHIS_HOST is deliberately NOT set here: docker-entrypoint.sh chooses IPv6 for a
5
+ # Railway deployment (which injects RAILWAY_SERVICE_NAME) and 0.0.0.0 for ordinary Docker.
6
+ # Uvicorn's IPv6 socket is not reliably dual-stack in containers. An explicit
7
+ # ENGRAPHIS_HOST always wins over the entrypoint's default.
10
8
  ENV PYTHONUNBUFFERED=1 \
11
9
  PYTHONDONTWRITEBYTECODE=1 \
12
10
  PIP_NO_CACHE_DIR=1 \
@@ -35,8 +33,13 @@ COPY pyproject.toml README.md LICENSE NOTICE ./
35
33
  COPY engraphis ./engraphis
36
34
  COPY scripts ./scripts
37
35
 
38
- # Full stack (REST + MCP + embeddings). Drop to .[server] or .[mcp] to slim the image.
39
- RUN pip install --upgrade pip "setuptools>=83" && pip install ".[all]"
36
+ # Railway runs CPU workloads. Install the CPU-only PyTorch wheel before the embedding
37
+ # stack so pip cannot select PyPI's multi-gigabyte CUDA dependency chain. The public
38
+ # customer image needs the dashboard/server surface plus its advertised local OCR path;
39
+ # MCP, transcription, PostgreSQL, and code graph remain opt-in deployment baggage.
40
+ RUN pip install --upgrade pip "setuptools>=83" \
41
+ && pip install --index-url https://download.pytorch.org/whl/cpu torch \
42
+ && pip install ".[server,documents,cloud-sync]"
40
43
 
41
44
  # Create the non-root app user and pre-own /data. NOTE: the container starts as root so
42
45
  # docker-entrypoint.sh can chown a freshly-mounted (root-owned) persistent volume, then
@@ -51,9 +54,8 @@ EXPOSE 8700
51
54
  # /api/ready verifies that the configured customer service can actually serve traffic;
52
55
  # Railway uses the same endpoint, so a process-only health signal cannot mask a bad mode.
53
56
  # start-period is generous: the first cold boot downloads the embedding model (cached to
54
- # the /data volume via HF_HOME thereafter). The entrypoint's default bind (`::` dual-stack
55
- # where available, else 0.0.0.0) answers loopback IPv4 probes like this one AND platform
56
- # IPv6 routing; the check also honors $PORT if the platform overrides it — matching
57
+ # the /data volume via HF_HOME thereafter). The entrypoint selects a bind address suited
58
+ # to Docker or Railway; the check also honors $PORT if the platform overrides it — matching
57
59
  # scripts/start_dashboard.py, which prefers $PORT over ENGRAPHIS_PORT for the bind.
58
60
  HEALTHCHECK --interval=30s --timeout=5s --start-period=300s --retries=3 \
59
61
  CMD python -c "import os,urllib.request,sys; p=os.environ.get('PORT') or os.environ.get('ENGRAPHIS_PORT','8700'); sys.exit(0 if urllib.request.urlopen('http://127.0.0.1:%s/api/ready' % p).status==200 else 1)"
@@ -67,13 +69,4 @@ ENTRYPOINT ["/usr/local/bin/docker-entrypoint.sh"]
67
69
  # public image. This entrypoint serves /api/auth/*, /api/license/*, and /api/bootstrap.
68
70
  # `--no-open`: never try to launch a browser in a container.
69
71
  #
70
- # The raw v1 single-user API server is still available — run `engraphis-server` directly
71
- # (see docker-compose.yml's opt-in "api" profile) — but it shares this image's exposed
72
- # port and root route (it serves the same static/index.html) while answering every
73
- # /api/* call with a blanket bearer-token 401, INCLUDING /api/auth/state and
74
- # /api/license/*. If this image is ever run as `engraphis-server` behind a team-mode
75
- # frontend, the UI will render normally but look permanently "signed out with no
76
- # features" no matter what the user does — that exact symptom cost real prod downtime
77
- # on 2026-07-13 when a host's start command silently fell back to this default. Do not
78
- # revert this without also fixing that ambiguity.
79
72
  CMD ["engraphis-dashboard", "--no-open"]
@@ -15,6 +15,7 @@ include docker-entrypoint.sh Dockerfile docker-compose.yml
15
15
  include railway.json
16
16
  recursive-include eval *.py
17
17
  include eval/BASELINES.md
18
+ include eval/EVIDENCE.md
18
19
  recursive-include eval/configs *.json
19
20
  recursive-include eval/datasets *.jsonl
20
21
  recursive-include tests *.py