engraphis 1.2.0__tar.gz → 1.2.5__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.
- {engraphis-1.2.0 → engraphis-1.2.5}/.env.example +4 -0
- engraphis-1.2.5/BENCHMARKS.md +291 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/CHANGELOG.md +99 -31
- {engraphis-1.2.0 → engraphis-1.2.5}/MANIFEST.in +1 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/PKG-INFO +215 -291
- {engraphis-1.2.0 → engraphis-1.2.5}/README.md +212 -290
- {engraphis-1.2.0 → engraphis-1.2.5}/docker-compose.yml +4 -2
- {engraphis-1.2.0 → engraphis-1.2.5}/engraphis/__init__.py +1 -1
- {engraphis-1.2.0 → engraphis-1.2.5}/engraphis/backends/extractor.py +141 -29
- {engraphis-1.2.0 → engraphis-1.2.5}/engraphis/backends/sync_folder.py +25 -14
- {engraphis-1.2.0 → engraphis-1.2.5}/engraphis/backends/sync_relay.py +148 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/engraphis/classic_assets/dashboard.js +6 -6
- {engraphis-1.2.0 → engraphis-1.2.5}/engraphis/commercial_manifest.json +2 -2
- {engraphis-1.2.0 → engraphis-1.2.5}/engraphis/config.py +3 -2
- {engraphis-1.2.0 → engraphis-1.2.5}/engraphis/core/consolidate.py +51 -25
- {engraphis-1.2.0 → engraphis-1.2.5}/engraphis/core/context.py +11 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/engraphis/core/engine.py +7 -3
- {engraphis-1.2.0 → engraphis-1.2.5}/engraphis/core/grounded.py +12 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/engraphis/core/interfaces.py +7 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/engraphis/core/recall.py +31 -1
- {engraphis-1.2.0 → engraphis-1.2.5}/engraphis/core/retrieval_policy.py +39 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/engraphis/core/store.py +140 -6
- {engraphis-1.2.0 → engraphis-1.2.5}/engraphis/core/sync.py +35 -1
- {engraphis-1.2.0 → engraphis-1.2.5}/engraphis/dashboard_assets/engraphis-graph.js +136 -11
- {engraphis-1.2.0 → engraphis-1.2.5}/engraphis/dashboard_assets/ledger.css +2 -2
- {engraphis-1.2.0 → engraphis-1.2.5}/engraphis/dashboard_assets/ledger.js +4 -4
- {engraphis-1.2.0 → engraphis-1.2.5}/engraphis/inspector/app.py +4 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/engraphis/mcp_server.py +34 -2
- {engraphis-1.2.0 → engraphis-1.2.5}/engraphis/read_only_api.py +8 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/engraphis/routes/v2_api.py +16 -1
- {engraphis-1.2.0 → engraphis-1.2.5}/engraphis/service.py +57 -11
- {engraphis-1.2.0 → engraphis-1.2.5}/engraphis/static/dashboard.js +6 -6
- {engraphis-1.2.0 → engraphis-1.2.5}/engraphis.egg-info/PKG-INFO +215 -291
- {engraphis-1.2.0 → engraphis-1.2.5}/engraphis.egg-info/SOURCES.txt +11 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/engraphis.egg-info/requires.txt +5 -0
- engraphis-1.2.5/eval/EVIDENCE.md +30 -0
- engraphis-1.2.5/eval/agent_benchmarks.py +630 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/eval/benchmark.py +359 -12
- {engraphis-1.2.0 → engraphis-1.2.5}/eval/chunking_eval.py +34 -6
- engraphis-1.2.5/eval/code_agent_ab.py +238 -0
- engraphis-1.2.5/eval/context_economy.py +438 -0
- engraphis-1.2.5/eval/longmemeval_v2_evidence.py +256 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/eval/performance.py +114 -4
- {engraphis-1.2.0 → engraphis-1.2.5}/pyproject.toml +7 -2
- {engraphis-1.2.0 → engraphis-1.2.5}/scripts/check_codeql_sarif.py +36 -5
- {engraphis-1.2.0 → engraphis-1.2.5}/scripts/check_commercial_manifest.py +0 -1
- {engraphis-1.2.0 → engraphis-1.2.5}/scripts/externalize_dashboard_assets.py +14 -1
- {engraphis-1.2.0 → engraphis-1.2.5}/scripts/install_shortcuts.py +71 -7
- {engraphis-1.2.0 → engraphis-1.2.5}/scripts/sync.py +15 -3
- {engraphis-1.2.0 → engraphis-1.2.5}/tests/test_benchmark_evidence.py +285 -7
- {engraphis-1.2.0 → engraphis-1.2.5}/tests/test_chunking_eval.py +27 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/tests/test_chunking_extractor.py +123 -2
- engraphis-1.2.5/tests/test_code_agent_ab.py +142 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/tests/test_codeql_sarif_gate.py +23 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/tests/test_commercial_hardening.py +7 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/tests/test_consolidate.py +111 -0
- engraphis-1.2.5/tests/test_context_economy.py +255 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/tests/test_context_packing.py +35 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/tests/test_dashboard_auth_placement.py +34 -10
- {engraphis-1.2.0 → engraphis-1.2.5}/tests/test_dashboard_v2.py +16 -3
- engraphis-1.2.5/tests/test_eval_agent_benchmarks.py +357 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/tests/test_eval_harness.py +4 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/tests/test_eval_performance.py +53 -1
- {engraphis-1.2.0 → engraphis-1.2.5}/tests/test_externalize_dashboard_assets.py +15 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/tests/test_graph_engine_asset.py +37 -3
- engraphis-1.2.5/tests/test_install_shortcuts.py +96 -0
- engraphis-1.2.5/tests/test_longmemeval_v2_evidence.py +157 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/tests/test_mcp_server.py +10 -5
- {engraphis-1.2.0 → engraphis-1.2.5}/tests/test_packaging.py +5 -1
- {engraphis-1.2.0 → engraphis-1.2.5}/tests/test_read_only_api.py +33 -2
- {engraphis-1.2.0 → engraphis-1.2.5}/tests/test_receipts.py +121 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/tests/test_release_infrastructure.py +8 -5
- {engraphis-1.2.0 → engraphis-1.2.5}/tests/test_retrieval_policy.py +56 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/tests/test_sync.py +175 -6
- {engraphis-1.2.0 → engraphis-1.2.5}/tests/test_sync_cli.py +40 -5
- engraphis-1.2.5/tests/test_sync_e2ee.py +153 -0
- engraphis-1.2.0/BENCHMARKS.md +0 -147
- {engraphis-1.2.0 → engraphis-1.2.5}/Dockerfile +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/LICENSE +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/NOTICE +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/docker-entrypoint.sh +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/engraphis/ai_context.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/engraphis/app.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/engraphis/backends/__init__.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/engraphis/backends/codegraph.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/engraphis/backends/embedder_api.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/engraphis/backends/embedder_deterministic.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/engraphis/backends/embedder_st.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/engraphis/backends/encrypted_db.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/engraphis/backends/graph_extractor.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/engraphis/backends/postgres_schema.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/engraphis/backends/reranker.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/engraphis/backends/resources.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/engraphis/backends/retention.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/engraphis/backends/vector_numpy.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/engraphis/backends/vector_sqlitevec.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/engraphis/classic_assets/__init__.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/engraphis/classic_assets/dashboard.css +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/engraphis/classic_assets/engraphis-graph.js +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/engraphis/classic_assets/engraphis-icon.png +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/engraphis/classic_assets/engraphis.ico +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/engraphis/classic_assets/favicon-32.png +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/engraphis/classic_assets/index.html +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/engraphis/classic_assets/vendor/d3.LICENSE +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/engraphis/classic_assets/vendor/d3.min.js +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/engraphis/classic_assets/vendor/force-graph.LICENSE +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/engraphis/classic_assets/vendor/force-graph.min.js +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/engraphis/classic_assets/vendor/marked.LICENSE +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/engraphis/classic_assets/vendor/marked.min.js +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/engraphis/classic_assets/vendor/purify.min.js +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/engraphis/cloud_features.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/engraphis/cloud_session.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/engraphis/commercial.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/engraphis/core/__init__.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/engraphis/core/codegraph_export.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/engraphis/core/conflicts.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/engraphis/core/graph_layers.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/engraphis/core/graph_scene.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/engraphis/core/graphrank.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/engraphis/core/ids.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/engraphis/core/resolve.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/engraphis/core/schema.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/engraphis/core/scoring.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/engraphis/core/textutil.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/engraphis/core/user_model.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/engraphis/dashboard_app.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/engraphis/dashboard_assets/__init__.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/engraphis/dashboard_assets/engraphis-graph-compat.js +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/engraphis/dashboard_assets/engraphis-icon.png +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/engraphis/dashboard_assets/engraphis.ico +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/engraphis/dashboard_assets/favicon-32.png +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/engraphis/dashboard_assets/index.html +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/engraphis/dashboard_assets/vendor/d3.LICENSE +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/engraphis/dashboard_assets/vendor/d3.min.js +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/engraphis/dashboard_assets/vendor/force-graph.LICENSE +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/engraphis/dashboard_assets/vendor/force-graph.min.js +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/engraphis/device_connect.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/engraphis/engines/__init__.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/engraphis/engines/embedder.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/engraphis/engines/ingest.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/engraphis/engines/intelligence.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/engraphis/engines/recall.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/engraphis/engines/reweight.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/engraphis/engines/thoughts.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/engraphis/graphdata.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/engraphis/hosted_client.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/engraphis/http_security.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/engraphis/inspector/__init__.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/engraphis/licensing.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/engraphis/llm/__init__.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/engraphis/llm/client.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/engraphis/local_auth.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/engraphis/logging_setup.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/engraphis/mcp_cli.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/engraphis/models.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/engraphis/netutil.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/engraphis/observability.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/engraphis/private_state.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/engraphis/redirector.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/engraphis/routes/__init__.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/engraphis/routes/memory.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/engraphis/routes/vault.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/engraphis/static/__init__.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/engraphis/static/dashboard.css +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/engraphis/static/engraphis-graph.js +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/engraphis/static/engraphis-icon.png +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/engraphis/static/engraphis.ico +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/engraphis/static/favicon-32.png +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/engraphis/static/index.html +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/engraphis/static/vendor/d3.LICENSE +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/engraphis/static/vendor/d3.min.js +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/engraphis/static/vendor/force-graph.LICENSE +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/engraphis/static/vendor/force-graph.min.js +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/engraphis/static/vendor/marked.LICENSE +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/engraphis/static/vendor/marked.min.js +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/engraphis/static/vendor/purify.min.js +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/engraphis/stores/__init__.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/engraphis/stores/graph.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/engraphis/stores/ledger.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/engraphis/stores/vaults.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/engraphis/stores/vectors.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/engraphis/update_check.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/engraphis.egg-info/dependency_links.txt +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/engraphis.egg-info/entry_points.txt +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/engraphis.egg-info/top_level.txt +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/eval/BASELINES.md +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/eval/__init__.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/eval/ablation.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/eval/configs/longmemeval_v2_engraphis.json +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/eval/datasets/adversarial.jsonl +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/eval/datasets/codemem.jsonl +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/eval/datasets/graph_multihop.jsonl +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/eval/datasets/longdoc.jsonl +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/eval/datasets/sample.jsonl +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/eval/external.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/eval/grounded.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/eval/harness.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/eval/longmemeval_v2.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/eval/metrics.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/eval/run_longmemeval_v2.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/railway.json +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/requirements.txt +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/scripts/__init__.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/scripts/backfill_graph.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/scripts/cli.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/scripts/connect.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/scripts/consolidate.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/scripts/entry.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/scripts/graph_cli.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/scripts/graph_server.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/scripts/init.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/scripts/inspector.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/scripts/mcp_server_http.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/scripts/migrate_to_v2.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/scripts/release_evidence.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/scripts/repair_embed_dim.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/scripts/sdk_compat.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/scripts/seed_from_obsidian.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/scripts/start_dashboard.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/scripts/start_server.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/scripts/test_routes.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/scripts/update.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/scripts/verify_distribution_contents.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/scripts/verify_release_artifacts.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/setup.cfg +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/setup.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/tests/__init__.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/tests/conftest.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/tests/test_agent_connect.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/tests/test_app_auth.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/tests/test_backends_factories.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/tests/test_benchmark_adversarial.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/tests/test_benchmark_longmemeval_v2.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/tests/test_bitemporal_recall.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/tests/test_canonical_export.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/tests/test_cli_entrypoints.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/tests/test_client_launch.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/tests/test_cloud_features.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/tests/test_cloud_session.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/tests/test_code_index_route_security.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/tests/test_code_recall_arm.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/tests/test_codegraph.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/tests/test_compact_recall.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/tests/test_config.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/tests/test_conflicts.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/tests/test_core_ids.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/tests/test_core_store.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/tests/test_cron_write_tools_workspace_default.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/tests/test_customer_node_hardening.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/tests/test_dashboard_button_regressions.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/tests/test_dashboard_dream_ui.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/tests/test_dashboard_security_headers_and_open_window.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/tests/test_db_path_default.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/tests/test_decay_idempotent.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/tests/test_device_connect.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/tests/test_embedder_threading.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/tests/test_encrypted_store.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/tests/test_encryption_dependency.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/tests/test_engine.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/tests/test_eval_ablation.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/tests/test_eval_external.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/tests/test_eval_grounded.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/tests/test_extractor.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/tests/test_graph_cli.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/tests/test_graph_explorer_v2.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/tests/test_graph_extractor.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/tests/test_graph_scene_contract.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/tests/test_graph_server.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/tests/test_graphdata.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/tests/test_graphrank.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/tests/test_grounded.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/tests/test_hosted_client.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/tests/test_hosted_plan_resolution.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/tests/test_http_security.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/tests/test_import_chunking.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/tests/test_import_error_redaction.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/tests/test_ingest_entities.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/tests/test_init.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/tests/test_inspector.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/tests/test_inspector_pro.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/tests/test_intent_paywall.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/tests/test_licensing_boundary_docs.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/tests/test_licensing_launch.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/tests/test_llm_config.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/tests/test_llm_dashboard.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/tests/test_local_auth_browser_session.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/tests/test_logging_setup.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/tests/test_mcp_annotation_idempotency.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/tests/test_memory_routes_fixes.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/tests/test_merge.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/tests/test_metadata_activity_forgery.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/tests/test_migration.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/tests/test_netutil.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/tests/test_observability.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/tests/test_personal_folders.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/tests/test_postgres_schema.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/tests/test_private_state_boundaries.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/tests/test_pro_cta.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/tests/test_proactive_context.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/tests/test_protocol_upgrades.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/tests/test_provenance_flags.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/tests/test_provider_error_redaction.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/tests/test_public_research_boundary.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/tests/test_ready.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/tests/test_recall.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/tests/test_recall_entity_workspace_widening.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/tests/test_relay_device_credentials.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/tests/test_release_artifacts.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/tests/test_release_evidence.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/tests/test_remember_atomicity.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/tests/test_resolve.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/tests/test_resources.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/tests/test_retention.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/tests/test_round17_fixes.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/tests/test_scoring.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/tests/test_security_fixes.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/tests/test_service.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/tests/test_service_graph.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/tests/test_service_isolation.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/tests/test_session_idempotent.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/tests/test_start_dashboard.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/tests/test_start_session_workspace_default.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/tests/test_store_v4_migration.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/tests/test_sync_dashboard.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/tests/test_update.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/tests/test_update_check.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/tests/test_user_model.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/tests/test_v1_auto_migrate.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/tests/test_v1_hardening.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/tests/test_v1_licensing.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/tests/test_vector_numpy.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/tests/test_vector_sqlitevec_backend.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/tests/test_workspace_isolation.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.5}/tests/test_workspace_ops.py +0 -0
|
@@ -255,6 +255,10 @@ ENGRAPHIS_LLM_API_KEY=sk-your-key-here
|
|
|
255
255
|
# ENGRAPHIS_CHUNK_TOKENS=512
|
|
256
256
|
# ENGRAPHIS_CHUNK_MAX=2048
|
|
257
257
|
# ENGRAPHIS_CHUNK_OVERLAP=64
|
|
258
|
+
# Optional reader-tokenizer parity for chunk sizes (requires transformers).
|
|
259
|
+
# Pin the revision when the resulting memories support reproducible evidence.
|
|
260
|
+
# ENGRAPHIS_CHUNK_TOKENIZER_MODEL=Qwen/Qwen3.5-9B
|
|
261
|
+
# ENGRAPHIS_CHUNK_TOKENIZER_REVISION=<immutable model commit>
|
|
258
262
|
# ENGRAPHIS_LOOP_INTERVAL=300
|
|
259
263
|
# ENGRAPHIS_LOOP_TOP_K=10
|
|
260
264
|
# ENGRAPHIS_RERANK_MODEL=cross-encoder/ms-marco-MiniLM-L-6-v2
|
|
@@ -0,0 +1,291 @@
|
|
|
1
|
+
# Benchmarks
|
|
2
|
+
|
|
3
|
+
This file is the honest status of what Engraphis measures today, how to reproduce it, and what
|
|
4
|
+
it does **not** yet claim. It exists because the README linked a `BENCHMARKS.md` that had never
|
|
5
|
+
been written; when this and the code disagree, the code wins (CLAUDE.md).
|
|
6
|
+
|
|
7
|
+
## What we measure today (all offline, no API key)
|
|
8
|
+
|
|
9
|
+
Engraphis's eval harness scores **retrieval**, not end-to-end QA. That distinction is deliberate
|
|
10
|
+
and stated everywhere the numbers appear (`eval/external.py`).
|
|
11
|
+
|
|
12
|
+
- **Correctness gate**: `eval/harness.py` over `eval/datasets/sample.jsonl` and
|
|
13
|
+
`codemem.jsonl` (conflict resolution) and `graph_multihop.jsonl` (multi-hop graph recall).
|
|
14
|
+
Runs on the deterministic embedder, so it is a plumbing/regression floor, not a public
|
|
15
|
+
performance claim. This is the gate CI enforces.
|
|
16
|
+
- **Ablation**: `eval/ablation.py`: vector-only vs. 1-hop graph vs. Personalized-PageRank arm,
|
|
17
|
+
to show the graph arm actually earns its place.
|
|
18
|
+
- **External benchmarks**: `eval/external.py` loads **LoCoMo** and **LongMemEval** and pushes
|
|
19
|
+
them through the *real* `MemoryEngine` write path (conflict resolution + evolution) and hybrid
|
|
20
|
+
recall with a real sentence-transformers embedder. It reports `recall_at_k` / `hit_at_k` /
|
|
21
|
+
`answer_token_recall`: i.e. *did the evidence come back*, not *did an LLM answer correctly*.
|
|
22
|
+
It retains source categories and abstention/no-evidence questions as explicit exclusions from
|
|
23
|
+
retrieval-only aggregates rather than silently dropping them. `eval.longmemeval_v2` is a local,
|
|
24
|
+
text-only adapter for the official LongMemEval-V2 `insert(trajectory)` / `query(query,
|
|
25
|
+
query_image=None)` memory interface; it does not download data or call a model.
|
|
26
|
+
- **Grounded**: `eval/grounded.py`: answerable → cite, off-topic → abstain.
|
|
27
|
+
- **Chunking (quality per token)**: `eval/chunking_eval.py` over `eval/datasets/longdoc.jsonl`
|
|
28
|
+
ingests a multi-topic corpus twice: once as one memory per document (`whole`) and once with
|
|
29
|
+
sub-file `ChunkingExtractor` (`chunked`), then queries both through the real recall pipeline. This is
|
|
30
|
+
the first cut of the context-reduction metric (item 3 below). On the deterministic embedder:
|
|
31
|
+
**recall@5 1.000 for both, at ~73% fewer context tokens (809 → 219) and ~4× smaller
|
|
32
|
+
tokens-to-evidence (162 → 42).** Pass `--embed-model sentence-transformers/all-MiniLM-L6-v2`
|
|
33
|
+
for a real retrieval number (recall should then favour chunked on larger corpora, not just
|
|
34
|
+
tie).
|
|
35
|
+
- **Full-pipeline latency + quality**: `eval/performance.py` times the shipped semantic +
|
|
36
|
+
lexical + graph + fusion + scoring + rerank + packing path after warmup, with reinforcement
|
|
37
|
+
disabled so repeated measurements do not mutate their corpus. It reports p50/p95/p99 latency,
|
|
38
|
+
retrieval quality, and packed context tokens in one JSON-safe schema. `--filler-memories`
|
|
39
|
+
provides deterministic corpus scaling, and every report records the runtime, architecture,
|
|
40
|
+
embedder, vector backend, corpus size, warmups, and iteration count. `--candidate-k` and
|
|
41
|
+
`--retrieval-profile` make adaptive-depth/routing experiments executable instead of changing
|
|
42
|
+
production defaults from an unmeasured hunch.
|
|
43
|
+
- **Workload context economy**: `eval/context_economy.py` compares three executable strategies
|
|
44
|
+
across every question in a workload: uncapped full-history replay, a contiguous recency window
|
|
45
|
+
at the same hard budget, and shipped Engraphis hybrid recall + packing. It reports evidence and
|
|
46
|
+
answer-token quality, cumulative reader-context tokens, a conservative total that charges one
|
|
47
|
+
complete source-token pass to indexing, and the query-count break-even point. The default is
|
|
48
|
+
deterministic/offline; `--embed-model` enables a real retrieval model, while
|
|
49
|
+
`--format locomo|longmemeval` reuses the established external loaders.
|
|
50
|
+
|
|
51
|
+
The workload benchmark is also allowed to say “this workload is too small for a memory layer.”
|
|
52
|
+
On the 44-memory / 26-question CodeMem regression fixture, every case already fits inside a
|
|
53
|
+
64-token recency window. Full-history and recency therefore use the same 1,180 cumulative reader
|
|
54
|
+
tokens at perfect evidence/answer-token quality, while Engraphis uses 1,375–1,377 reader tokens
|
|
55
|
+
plus a conservative 631-token indexing pass. That is an honest no-break-even boundary result:
|
|
56
|
+
the benefit being measured begins when history is long or reused enough to outweigh retrieval
|
|
57
|
+
framing and indexing.
|
|
58
|
+
|
|
59
|
+
The complementary real-model LoCoMo workload diagnostic covers 10 conversations and 1,986
|
|
60
|
+
questions with `all-MiniLM-L6-v2`, `k=10`, a 512-token reader budget, and conflict resolution
|
|
61
|
+
disabled. Engraphis used **891,857** cumulative reader-context tokens versus **49,915,394** for
|
|
62
|
+
uncapped full history, **98.2133% lower**. Charging one complete 246,539-token corpus pass to
|
|
63
|
+
indexing produces a conservative Engraphis total of **1,138,396**, still **97.7193% lower**, with
|
|
64
|
+
a calculated break-even at query 10. The quality tradeoff is explicit:
|
|
65
|
+
|
|
66
|
+
| LoCoMo workload method | Retrieval recall | Hit rate | Answer-token recall | Mean reader context |
|
|
67
|
+
|---|---:|---:|---:|---:|
|
|
68
|
+
| Engraphis hybrid recall | **0.600457** | **0.657417** | **0.679614** | **449.07** tokens |
|
|
69
|
+
| Same-budget recency window | 0.011289 | 0.012614 | 0.339941 | 487.87 tokens |
|
|
70
|
+
| Uncapped full history | 0.996997 | 0.997477 | 0.917247 | 25,133.63 tokens |
|
|
71
|
+
|
|
72
|
+
This diagnostic supports a precise statement: Engraphis recovered much more useful evidence than
|
|
73
|
+
a same-budget recency window while using a small fraction of full-history context. It does not
|
|
74
|
+
support “same quality as full history,” provider-billing, or end-to-end answer-accuracy claims.
|
|
75
|
+
The embedding model revision was not pinned in that run, so rerun it with an immutable revision
|
|
76
|
+
before treating the numbers as canonical release evidence.
|
|
77
|
+
|
|
78
|
+
### Reproduce
|
|
79
|
+
|
|
80
|
+
```bash
|
|
81
|
+
# Correctness gate (deterministic, no download)
|
|
82
|
+
python -m pytest tests/ -q
|
|
83
|
+
python -m eval.harness --dataset eval/datasets/sample.jsonl --k 5
|
|
84
|
+
python -m eval.harness --dataset eval/datasets/codemem.jsonl --k 5
|
|
85
|
+
python -m eval.harness --dataset eval/datasets/graph_multihop.jsonl --k 5
|
|
86
|
+
python -m eval.ablation
|
|
87
|
+
python -m eval.performance --dataset eval/datasets/codemem.jsonl --k 5 --iterations 10
|
|
88
|
+
python -m eval.performance --dataset eval/datasets/codemem.jsonl --k 5 \
|
|
89
|
+
--candidate-k 25 --candidate-depth adaptive --retrieval-profile auto --iterations 10
|
|
90
|
+
python -m eval.context_economy --dataset eval/datasets/codemem.jsonl \
|
|
91
|
+
--token-budget 512 --k 5
|
|
92
|
+
python -m eval.performance --dataset eval/datasets/codemem.jsonl --k 5 \
|
|
93
|
+
--iterations 5 --filler-memories 1000
|
|
94
|
+
# Canonical latency/resource protocol: requires >=1,000 queries and five processes.
|
|
95
|
+
python -m eval.performance --dataset fixed-1000-plus.jsonl --acceptance-matrix --processes 5
|
|
96
|
+
|
|
97
|
+
# Real retrieval numbers (downloads all-MiniLM-L6-v2)
|
|
98
|
+
python -m eval.external --dataset longmemeval_s.json --format longmemeval --k 10
|
|
99
|
+
python -m eval.external --dataset locomo10.json --format locomo --k 10
|
|
100
|
+
python -m eval.context_economy --dataset locomo10.json --format locomo \
|
|
101
|
+
--embed-model sentence-transformers/all-MiniLM-L6-v2 --token-budget 512 --k 10 --no-resolve
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
## What we do NOT yet claim
|
|
105
|
+
|
|
106
|
+
- **No end-to-end QA accuracy.** Official LoCoMo / LongMemEval QA scores depend on an answering model and evaluator. Engraphis isolates retrieval and does not present that result as end-to-end answer accuracy.
|
|
107
|
+
- **No hosted-service latency comparison.** The in-repo p50/p95/p99 benchmark covers the local
|
|
108
|
+
reference pipeline and records its environment; unlike environments are not compared.
|
|
109
|
+
- **No neutral third-party ranking.** We have not run an external eval platform.
|
|
110
|
+
- **No provider bill estimate.** Context-economy counts reader evidence under its named counter.
|
|
111
|
+
It excludes system/tool prompts, questions, completions, prompt caching, provider pricing,
|
|
112
|
+
compute, and storage. Its indexing-inclusive total is a conservative text-volume proxy.
|
|
113
|
+
|
|
114
|
+
Every publishable run should emit the `engraphis-benchmark/v2` envelope: dataset/config hashes,
|
|
115
|
+
per-question records, explicit exclusions, fixed-budget context curves, and deterministic
|
|
116
|
+
stratified or paired bootstrap confidence intervals. Every run names its token counter.
|
|
117
|
+
Noncanonical offline fixtures may identify a deterministic estimate; canonical public evidence
|
|
118
|
+
requires the exact pinned reader tokenizer and immutable model revision. The lightweight CI
|
|
119
|
+
fixtures validate that machinery; they are not a claim about external benchmark performance.
|
|
120
|
+
|
|
121
|
+
The benchmark context metric reads strict recall usage fields rather than inferring prompt size:
|
|
122
|
+
`budget_tokens`, `context_tokens`, `source_tokens`, `saved_tokens`, `savings_ratio`,
|
|
123
|
+
`packed_count`, `omitted_count`, and `token_counter`. Use `engraphis_recall_context` for a
|
|
124
|
+
hard-budget prompt packet; legacy `engraphis_recall` remains available in full or compact response
|
|
125
|
+
mode for compatibility.
|
|
126
|
+
|
|
127
|
+
### Canonical public artifacts
|
|
128
|
+
|
|
129
|
+
Use `python -m eval.benchmark --input report.json --output artifacts/run.json` to validate a
|
|
130
|
+
report and write sorted, immutable JSON plus `run.json.sha256`. The command permits an identical
|
|
131
|
+
retry but refuses to replace a different artifact at the same path. For an official
|
|
132
|
+
LongMemEval-V2 run, add `--canonical`: this requires a profile with an exact benchmark repository
|
|
133
|
+
revision, dataset revision, reader model revision, and embedding model revision. The checked-in
|
|
134
|
+
profile pins immutable upstream commits; replacing any revision with a mutable tag fails
|
|
135
|
+
validation. Canonical profiles label the baseline (`no_retrieval`, `lexical_only`, `dense_only`,
|
|
136
|
+
`dense_lexical_rrf`, `full_hybrid`, `full_history`, `no_graph`, `no_reranker`,
|
|
137
|
+
`no_temporal_resolution`, or `whole_document`) and declare the required fixed context-budget
|
|
138
|
+
matrix: 256, 512, 1024, 2048, and 4096 tokens. Canonical in-repo reports rerun every question at
|
|
139
|
+
all five budgets and validate each aggregate against its per-question evidence. The checked-in
|
|
140
|
+
LongMemEval-V2 memory-module configuration sets the official adapter's operating point to 1,024
|
|
141
|
+
tokens; that single official point must not be presented as a five-point curve.
|
|
142
|
+
|
|
143
|
+
`eval.external --canonical` refuses `--limit` and rejects a normalized output that omitted source
|
|
144
|
+
cases. Retrieval-only abstention/no-evidence records remain visible in the artifact's
|
|
145
|
+
`exclusions`; they are not counted as evidence-retrieval scores.
|
|
146
|
+
|
|
147
|
+
Official LongMemEval-V2 output can be converted into a public-safe QA artifact with
|
|
148
|
+
`python -m eval.longmemeval_v2_evidence`. The exporter keeps the official QA score, fixed-reader
|
|
149
|
+
context token count, latency, model revisions, source digests, repository state, and artifact
|
|
150
|
+
checksum. It removes raw questions, answers, prompts, reader output, and retrieved context before
|
|
151
|
+
the artifact can be written. See [`eval/EVIDENCE.md`](eval/EVIDENCE.md) for the exact command.
|
|
152
|
+
|
|
153
|
+
### LongMemEval-V2 memory-module adapter
|
|
154
|
+
|
|
155
|
+
`eval.longmemeval_v2.EngraphisLongMemEvalV2Memory` follows the official
|
|
156
|
+
`memory_modules.memory.Memory` interface at LongMemEval-V2 commit
|
|
157
|
+
`6f020ac2fc3275e46c706d3406e02c3ed79b7be2`. When imported in that environment, its
|
|
158
|
+
`@register_memory` decorator registers `memory_type="engraphis"`; use the checked-in
|
|
159
|
+
[`eval/configs/longmemeval_v2_engraphis.json`](eval/configs/longmemeval_v2_engraphis.json)
|
|
160
|
+
with the official harness. The config pins `Qwen/Qwen3-Embedding-8B` to revision
|
|
161
|
+
`1d8ad4ca9b3dd8059ad90a75d4983776a23d44af`; mutable embedding revisions are rejected, and a
|
|
162
|
+
canonical adapter run fails instead of relabeling the deterministic offline fallback as Qwen.
|
|
163
|
+
Run `python -m eval.run_longmemeval_v2` with the official harness arguments and the pinned
|
|
164
|
+
checkout on `PYTHONPATH`. This wrapper performs the upstream registry import in the required order
|
|
165
|
+
before delegating to `evaluation.harness`; a direct upstream invocation must otherwise import
|
|
166
|
+
`eval.longmemeval_v2` before calling `build_memory`.
|
|
167
|
+
|
|
168
|
+
The checked-in configuration is canonical only when the adapter resolves the pinned Qwen reader
|
|
169
|
+
processor at `c202236235762e1c871ad0ccb60c8ee5ba337b9a`. The wrapper also forces the audited
|
|
170
|
+
official harness's otherwise-unpinned `AutoProcessor` call to that same revision. It refuses to
|
|
171
|
+
start if the optional processor dependency or immutable revision is unavailable; the local regex
|
|
172
|
+
counter is never silently relabeled as a reader budget. The recorded budget counts each returned
|
|
173
|
+
context item's content with that reader tokenizer (without prompt framing or inter-item
|
|
174
|
+
separators), so it is a hard **evidence-item content** budget, not a claim about total chat-prompt
|
|
175
|
+
tokens. Packed sources are returned as separate context items, preserving the largest fitting
|
|
176
|
+
evidence prefix instead of dropping one oversized monolithic item. The adapter does not download
|
|
177
|
+
benchmark data or call the reader/evaluator; the official harness owns those steps.
|
|
178
|
+
|
|
179
|
+
## External evidence status and remaining executions
|
|
180
|
+
|
|
181
|
+
1. **Run the official LongMemEval-V2 reader and evaluator.** The adapter, pinned runner, and
|
|
182
|
+
redacted evidence exporter are implemented. The exact upstream commit boots in an isolated
|
|
183
|
+
Python 3.11 environment and the wrapper reaches the official harness CLI. Dataset revision
|
|
184
|
+
`f152293e235517d504809563c833d7190b8c713b` publishes 7,120,369,667 bytes before the pinned
|
|
185
|
+
Qwen reader and embedding model assets. A full official run therefore still requires those
|
|
186
|
+
resources, sufficient compute, and evaluator configuration; no canonical QA score is claimed
|
|
187
|
+
until that run completes.
|
|
188
|
+
2. **Publish production-backend latency.** Run `eval/performance.py` with the real embedder and
|
|
189
|
+
sqlite-vec/backend configuration on a fixed machine class and corpus scale.
|
|
190
|
+
3. **Run the fixed-budget curve on the complete official datasets.** The v2 harness now measures
|
|
191
|
+
every question at 256, 512, 1,024, 2,048, and 4,096 evidence tokens and validates the
|
|
192
|
+
per-question records, aggregates, and pinned reader-tokenizer identity. Publish the curve only
|
|
193
|
+
after complete official runs produce immutable artifacts for every point.
|
|
194
|
+
4. **Run an external evaluation platform** once (1)–(3) exist.
|
|
195
|
+
|
|
196
|
+
Do not make all evidence lanes variants of explicit factual recall. Executable offline adapters
|
|
197
|
+
now cover:
|
|
198
|
+
|
|
199
|
+
- [MemoryAgentBench](https://github.com/HUST-AI-HYZ/MemoryAgentBench): incremental multi-turn
|
|
200
|
+
learning, long-range understanding, and conflict/consolidation inputs.
|
|
201
|
+
- [LoCoMo-Plus](https://github.com/xjtuleeyf/Locomo-Plus): an old implicit constraint must affect
|
|
202
|
+
a later response even when the later cue does not restate the remembered fact.
|
|
203
|
+
- [Mem2ActBench](https://github.com/Cantaloupe-M/Mem2ActBench): memory must select a tool and
|
|
204
|
+
ground its arguments, not merely return a passage. The current adapter measures retrieval and
|
|
205
|
+
expected tool-argument context coverage, not generated tool-call success.
|
|
206
|
+
|
|
207
|
+
```bash
|
|
208
|
+
python -m eval.agent_benchmarks --dataset memoryagentbench.json \
|
|
209
|
+
--format memoryagentbench
|
|
210
|
+
python -m eval.agent_benchmarks --dataset locomo_plus.json \
|
|
211
|
+
--format locomo_plus
|
|
212
|
+
python -m eval.agent_benchmarks --dataset qa_dataset.jsonl \
|
|
213
|
+
--conversations toolmem_conversation.jsonl --format mem2actbench \
|
|
214
|
+
--artifact artifacts/mem2actbench.json
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
Use `--artifact` on any of these commands to write a redacted, immutable evidence envelope plus
|
|
218
|
+
an adjacent SHA256 file. The ordinary console/`--json` report is private run material and may
|
|
219
|
+
contain source questions for debugging.
|
|
220
|
+
|
|
221
|
+
### Upstream-data diagnostic baseline (2026-07-30)
|
|
222
|
+
|
|
223
|
+
These runs use the dependency-free deterministic embedder on upstream data. They validate the
|
|
224
|
+
adapters and expose product gaps; they are noncanonical diagnostics, not leaderboard or marketing
|
|
225
|
+
claims. The artifact validator accepted every completed envelope.
|
|
226
|
+
|
|
227
|
+
| Upstream source | Executed scope | Result and boundary |
|
|
228
|
+
|---|---|---|
|
|
229
|
+
| 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. |
|
|
230
|
+
| 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. |
|
|
231
|
+
| 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. |
|
|
232
|
+
| 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. |
|
|
233
|
+
| 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. |
|
|
234
|
+
| 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. |
|
|
235
|
+
|
|
236
|
+
The MemoryAgentBench loader accepts both its aligned public JSON export and the Hugging Face
|
|
237
|
+
dataset-server `rows[].row` envelope. Rows without gold evidence remain useful for answer-token
|
|
238
|
+
coverage, but are excluded from retrieval aggregates and counted separately as
|
|
239
|
+
`retrieval_scored_questions`.
|
|
240
|
+
|
|
241
|
+
For paired code-agent runs, execute the same tasks with the same model, tools, machine, and
|
|
242
|
+
deterministic success oracle under `full_history` and `engraphis`. Then analyze the content-free
|
|
243
|
+
run records with:
|
|
244
|
+
|
|
245
|
+
```bash
|
|
246
|
+
python -m eval.code_agent_ab --full-history full-history.jsonl \
|
|
247
|
+
--engraphis engraphis.jsonl --output paired-report.json
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
The analyzer rejects unmatched task IDs and different success oracles, then reports paired
|
|
251
|
+
bootstrap intervals for task success, input/output/tool tokens, retries, latency, and optional
|
|
252
|
+
cost. Its aggregate output does not echo task IDs or oracle commands. It does not launch an agent
|
|
253
|
+
or invent a task-success oracle.
|
|
254
|
+
|
|
255
|
+
## Optimization experiments to run before changing defaults
|
|
256
|
+
|
|
257
|
+
1. **Budget-aware packing**: compare full source, safe summary, sentence-aligned safe summary
|
|
258
|
+
excerpt, and raw-source excerpt at fixed budgets. Gate on support/answer retention and
|
|
259
|
+
qualifier preservation, not token count alone.
|
|
260
|
+
2. **Adaptive retrieval work**: `--candidate-depth adaptive` is now an opt-in performance
|
|
261
|
+
experiment. It keeps wider graph/code pools and reduces routine lexical/balanced pools while
|
|
262
|
+
reporting the requested and actual depth. Sample and CodeMem kept every offline quality metric
|
|
263
|
+
at 1.0 with balanced depth reduced from 50 to 15; CodeMem plus 1,000 fillers reduced local
|
|
264
|
+
median recall latency from 20.666 ms to 18.991 ms in a 260-recall comparison, an 8.1%
|
|
265
|
+
reduction. These are machine-specific regression results, not production latency claims. Keep
|
|
266
|
+
the default fixed until complete external categories meet predeclared quality margins.
|
|
267
|
+
3. **Packing-pressure consolidation**: prioritize memory families that are frequently recalled,
|
|
268
|
+
repeatedly omitted, or costly per useful token. Count write/index/storage cost as well as later
|
|
269
|
+
reader-context savings.
|
|
270
|
+
4. **Tokenizer-aware ingestion**: implemented behind the chunk extractor. The dependency-free
|
|
271
|
+
default remains `engraphis.chars4.v1`; an explicitly configured Hugging Face reader tokenizer
|
|
272
|
+
enforces prose chunk and overlap budgets and records its identity in chunk metadata. Continue
|
|
273
|
+
measuring tokens-to-evidence, recall, and storage/index growth together before recommending a
|
|
274
|
+
model-specific default.
|
|
275
|
+
5. **Bulk ingestion**: add batch embedding plus a transaction-aware vector upsert path, then rerun
|
|
276
|
+
the 5.88 MB MemoryAgentBench Test-Time Learning row. Gate this on identical stored-memory,
|
|
277
|
+
provenance, graph-link, and temporal-resolution outcomes, not throughput alone.
|
|
278
|
+
6. **Scoped caches**: benchmark query embeddings and repeat-recall results keyed by workspace,
|
|
279
|
+
repo, time anchors, profile, and corpus version. Test invalidation correctness before claiming
|
|
280
|
+
latency gains.
|
|
281
|
+
7. **Privacy-safe real usage**: use `engraphis_context_savings` to let each workspace inspect
|
|
282
|
+
aggregate source/context/saved tokens already present in content-free receipts. Keep unlike
|
|
283
|
+
token counters separate and require a valid receipt chain before treating totals as auditable.
|
|
284
|
+
|
|
285
|
+
## Evaluation question
|
|
286
|
+
|
|
287
|
+
The predeclared question is whether the full vector + lexical/BM25 + sparse PPR graph + calibrated
|
|
288
|
+
rerank pipeline, bi-temporal resolution, and grounded abstention produce higher evidence recall
|
|
289
|
+
per injected token than the registered baselines. The answer must come from a complete,
|
|
290
|
+
machine-readable artifact with paired confidence intervals; otherwise the release reports
|
|
291
|
+
“no demonstrated improvement.”
|
|
@@ -3,6 +3,74 @@
|
|
|
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.2.5] - 2026-07-31
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
|
|
12
|
+
- `engraphis_context_savings` aggregates validated, content-free recall receipts by workspace,
|
|
13
|
+
repo, operation, and token-counter identity. The same read-only view is available through the
|
|
14
|
+
service, Inspector, v2/read-only APIs, and dashboard receipt panel.
|
|
15
|
+
- Recall supports an explicit adaptive candidate-depth experiment while retaining the historical
|
|
16
|
+
fixed depth by default. Performance reports record requested and actual candidate depths.
|
|
17
|
+
- Chunk ingestion can enforce budgets with an injected or explicitly configured Hugging Face
|
|
18
|
+
tokenizer and records the counter identity, target, and overlap in each chunk's metadata.
|
|
19
|
+
- Offline adapters now cover MemoryAgentBench, LoCoMo-Plus, and Mem2ActBench. A paired code-agent
|
|
20
|
+
analyzer compares full-history and Engraphis runs using identical tasks and success oracles.
|
|
21
|
+
- Public benchmark evidence can carry source hashes, repository state, environment and model
|
|
22
|
+
provenance, secret-redacted commands, content digests, and adjacent immutable SHA-256 files.
|
|
23
|
+
|
|
24
|
+
### Changed
|
|
25
|
+
|
|
26
|
+
- Context-economy evaluation now compares uncapped full history, a same-budget recency window,
|
|
27
|
+
and shipped hybrid recall while charging an explicit one-time indexing token proxy.
|
|
28
|
+
- Official LongMemEval-V2 output has a dedicated redacted evidence exporter that retains the
|
|
29
|
+
official QA/token/latency measures without publishing prompts, answers, model output, or
|
|
30
|
+
retrieved context.
|
|
31
|
+
- Folder-sync dry runs no longer create a remote directory or persist a local device identity.
|
|
32
|
+
|
|
33
|
+
### Fixed
|
|
34
|
+
|
|
35
|
+
- Sync rejects malformed scope/repo combinations and every peer-driven visibility change for an
|
|
36
|
+
existing memory, including malformed legacy rows. Scope promotion or repair remains a local,
|
|
37
|
+
explicit governance operation.
|
|
38
|
+
- Workspace consolidation excludes session-private memories and partitions digests and entity
|
|
39
|
+
profiles by their exact visibility owner, preventing cross-repo or cross-scope summaries.
|
|
40
|
+
- Tokenizer-aware chunk overlap can no longer exceed the configured prose budget or emit a
|
|
41
|
+
duplicate overlap-only record before an oversized paragraph. Invalid token counters fail
|
|
42
|
+
closed instead of silently producing mis-sized chunks.
|
|
43
|
+
- The new evidence guide is included in wheel and source distributions.
|
|
44
|
+
|
|
45
|
+
## [1.2.2] - 2026-07-30
|
|
46
|
+
|
|
47
|
+
### Fixed
|
|
48
|
+
|
|
49
|
+
- Cloud Sync now continues past legacy plaintext, malformed, and tampered relay objects while
|
|
50
|
+
still failing closed for each object. Later authenticated peer bundles apply, and the affected
|
|
51
|
+
sync round is explicitly reported as incomplete rather than successful.
|
|
52
|
+
- Security and sync documentation now consistently distinguish end-to-end encrypted Cloud Sync
|
|
53
|
+
from the separately readable managed-compute snapshot service.
|
|
54
|
+
- README visual PNG exports now use their SVG canvas dimensions without hidden screenshot padding.
|
|
55
|
+
|
|
56
|
+
## [1.2.1] - 2026-07-30
|
|
57
|
+
|
|
58
|
+
### Security
|
|
59
|
+
|
|
60
|
+
- Cloud Sync now encrypts every eligible shared-workspace bundle on the client with
|
|
61
|
+
ChaCha20-Poly1305 before upload. The relay receives opaque deterministic bundle names and
|
|
62
|
+
ciphertext only; tampered, renamed, cross-workspace, wrong-key, and legacy plaintext bundles
|
|
63
|
+
are rejected before the merge engine.
|
|
64
|
+
- Cloud Sync requires a client-held 32-byte workspace key and the `cloud-sync` optional runtime.
|
|
65
|
+
Missing or malformed encryption configuration stops sync rather than falling back to plaintext.
|
|
66
|
+
|
|
67
|
+
### Changed
|
|
68
|
+
|
|
69
|
+
- Cloud Sync privacy copy now states that eligible shared-workspace changes are encrypted
|
|
70
|
+
end-to-end before leaving the device and cannot be read by Engraphis Cloud. Product and
|
|
71
|
+
security documentation separately identifies managed compute as the readable, bounded-snapshot
|
|
72
|
+
service it is.
|
|
73
|
+
|
|
6
74
|
## [1.2.0] - 2026-07-30
|
|
7
75
|
|
|
8
76
|
### Added
|
|
@@ -116,21 +184,21 @@ Public 1.1.0 hosted-connect and graph-experience release.
|
|
|
116
184
|
|
|
117
185
|
### Added
|
|
118
186
|
|
|
119
|
-
- **`engraphis connect --token engr_ct_
|
|
187
|
+
- **`engraphis connect --token engr_ct_…`**: the missing client half of device connect.
|
|
120
188
|
`cloud_session.save_bootstrap()` is the only writer of `~/.engraphis/cloud_session.json`,
|
|
121
189
|
and it had no production caller: the docs told paying customers to prefer a file nothing
|
|
122
190
|
created, so a purchased installation could not be connected without hand-writing state.
|
|
123
191
|
The new command redeems the one-time connect token from the account portal against
|
|
124
192
|
`POST /v1/devices/connect`, saves the returned session with owner-only permissions, and
|
|
125
193
|
verifies `cloud_session.configured()` before reporting success. The token is sent in the
|
|
126
|
-
request body and nowhere else
|
|
194
|
+
request body and nowhere else; it is never printed, logged, or written to disk, and every
|
|
127
195
|
refusal maps to fixed, actionable copy (an expired or already-used token is not confused
|
|
128
196
|
with a lapsed subscription). Session storage is pre-flighted before the exchange, so an
|
|
129
197
|
unwritable state directory or a `cloud_session.json` replaced by a link fails the command
|
|
130
|
-
*without* spending the single-use token
|
|
198
|
+
*without* spending the single-use token; the customer fixes the path and retries with the
|
|
131
199
|
same token instead of returning to the portal for a new one. Faults that can only happen
|
|
132
|
-
*after* the exchange
|
|
133
|
-
endpoint that stops resolving before the session is written (`CloudUrlUnresolved`)
|
|
200
|
+
*after* the exchange: a reply truncated mid-body (`http.client.IncompleteRead`), or an
|
|
201
|
+
endpoint that stops resolving before the session is written (`CloudUrlUnresolved`) are
|
|
134
202
|
reported as errors that say the token was already used, rather than escaping as tracebacks
|
|
135
203
|
that leave the customer unable to tell whether to retry. Also installed as
|
|
136
204
|
`engraphis-connect`.
|
|
@@ -328,7 +396,7 @@ and safe hosted deployment.
|
|
|
328
396
|
|
|
329
397
|
### Security
|
|
330
398
|
|
|
331
|
-
- Every entrypoint sends baseline response headers
|
|
399
|
+
- Every entrypoint sends baseline response headers: CSP, `X-Frame-Options: DENY`,
|
|
332
400
|
`X-Content-Type-Options`, `Referrer-Policy`, `Permissions-Policy`, and HSTS over HTTPS
|
|
333
401
|
only. Override with `ENGRAPHIS_CSP` / `ENGRAPHIS_HSTS`; set either to an empty string to
|
|
334
402
|
omit that header where a fronting proxy supplies its own.
|
|
@@ -422,10 +490,10 @@ and safe hosted deployment.
|
|
|
422
490
|
insert sequence (engine-level write lock): concurrent near-duplicate writes can no
|
|
423
491
|
longer both resolve ADD and store duplicates instead of NOOP/INVALIDATE.
|
|
424
492
|
- The Inspector's `/api/auth/login`/`setup` no longer run PBKDF2 (600k iterations)
|
|
425
|
-
on the asyncio event loop
|
|
493
|
+
on the asyncio event loop; password hashing moved to a worker thread, so a burst
|
|
426
494
|
of logins can't stall every other request.
|
|
427
495
|
- A failed vector-index upsert on the write path is now logged and audited
|
|
428
|
-
(`index_upsert_failed`) instead of silently swallowed
|
|
496
|
+
(`index_upsert_failed`) instead of silently swallowed. Previously, the memory
|
|
429
497
|
stayed invisible to semantic recall with no trace.
|
|
430
498
|
- URLs built from a bind host are now IPv6-safe and connectable (`engraphis.netutil`):
|
|
431
499
|
`ENGRAPHIS_HOST=::` no longer yields the malformed `http://:::8700` in the printed
|
|
@@ -468,7 +536,7 @@ and safe hosted deployment.
|
|
|
468
536
|
|
|
469
537
|
### Fixed
|
|
470
538
|
- 1-hop graph recall (and the PPR large-graph fallback) now honors `graph_layers`, matching
|
|
471
|
-
the PPR arm
|
|
539
|
+
the PPR arm: `Store.neighbors()` gained a `layers` filter.
|
|
472
540
|
- `FolderTransport.push()` no longer follows peer-planted symlinks in the shared sync folder
|
|
473
541
|
(unpredictable temp name + `O_CREAT|O_EXCL|O_NOFOLLOW`), closing an arbitrary-file-write
|
|
474
542
|
vector that mirrored the already-hardened read side.
|
|
@@ -477,7 +545,7 @@ and safe hosted deployment.
|
|
|
477
545
|
- Caller-supplied `metadata.retention_supervision` is stripped at the service boundary; only
|
|
478
546
|
the validated `retention_class` presets can influence importance/stability.
|
|
479
547
|
- `merge_workspaces()` no longer duplicates symbols/code edges when both workspaces indexed
|
|
480
|
-
the same file in a same-named repo
|
|
548
|
+
the same file in a same-named repo: the losing snapshot's rows are cleared, and its
|
|
481
549
|
memory↔code links are re-pointed at the surviving same-fqname symbols.
|
|
482
550
|
- `engraphis-graph impact/prs` reject leading-dash git revisions (git option injection), and
|
|
483
551
|
graph exports refuse a symlinked output directory and are written atomically without
|
|
@@ -486,7 +554,7 @@ and safe hosted deployment.
|
|
|
486
554
|
(`limit`-derived cap) so a large workspace graph or indexed repo can't produce unbounded
|
|
487
555
|
viewer-role responses.
|
|
488
556
|
- Relay sync fails closed when a workspace's settings are unreadable rather than treating a
|
|
489
|
-
possibly-personal folder as shared
|
|
557
|
+
possibly-personal folder as shared: in the sync CLI and in the dashboard/background
|
|
490
558
|
`_sync_all` path; resource extraction enforces its own raw-size cap.
|
|
491
559
|
|
|
492
560
|
## [0.9.6] - 2026-07-16
|
|
@@ -574,10 +642,10 @@ and safe hosted deployment.
|
|
|
574
642
|
### Changed
|
|
575
643
|
- **Team mode is now ON by default (opt-out).** `ENGRAPHIS_TEAM_MODE` defaults to on;
|
|
576
644
|
set `ENGRAPHIS_TEAM_MODE=0` (or false/no/off) to disable. The per-user login wall is
|
|
577
|
-
no longer raised just because the mode flag is on
|
|
645
|
+
no longer raised just because the mode flag is on. It now requires a *live* `team`
|
|
578
646
|
feature entitlement (`licensing.has_feature("team")`), checked at request time in
|
|
579
647
|
`dashboard_app.py` and reflected in `/api/auth/state`. Solo / no-license installs stay
|
|
580
|
-
fully open, and the wall appears the moment a team license key is added
|
|
648
|
+
fully open, and the wall appears the moment a team license key is added, even via the
|
|
581
649
|
dashboard UI at runtime. A `team` license is still required to *add seats* beyond the
|
|
582
650
|
first admin (bootstrap admin is created unconditionally). Docs (`.env.example`,
|
|
583
651
|
`AGENTS.md`, `README.md`, `SECURITY.md`, `scripts/init.py`) and team-mode test fixtures
|
|
@@ -585,11 +653,11 @@ and safe hosted deployment.
|
|
|
585
653
|
- **Team-invite email rewritten to separate "join" from "activate a key".** The old
|
|
586
654
|
invite conflated the two, so members pasted the shared team key into the hosted/Railway
|
|
587
655
|
dashboard, saw it "work" (it just re-activated a license already active there), and
|
|
588
|
-
thought they'd joined
|
|
656
|
+
thought they'd joined, when joining means signing in with email + password. The email
|
|
589
657
|
now frames two distinct options: **Option 1** (required to join) sign in to the team
|
|
590
|
-
dashboard with email + the admin-set password
|
|
658
|
+
dashboard with email + the admin-set password, with explicitly *no license key needed here,
|
|
591
659
|
don't paste one*; **Option 2** (optional) run Engraphis on your own machine and access
|
|
592
|
-
the team's memories locally
|
|
660
|
+
the team's memories locally; that is what the shared team key is for (LOCAL
|
|
593
661
|
`http://127.0.0.1:8700` → Settings → License, then Settings → Cloud Sync to pull the
|
|
594
662
|
converged team store down to a local offline copy). Invites now always carry a
|
|
595
663
|
clickable sign-in link: `dashboard_url` resolves explicit arg → `ENGRAPHIS_DASHBOARD_URL`
|
|
@@ -625,7 +693,7 @@ and safe hosted deployment.
|
|
|
625
693
|
- **The dashboard (`engraphis-dashboard` / `http://127.0.0.1:8700`) would not start.**
|
|
626
694
|
`scripts/start_dashboard.py` runs uvicorn against `engraphis.dashboard_app:app`, but
|
|
627
695
|
`dashboard_app.py` only defined the `create_app()` factory and never built a module-level
|
|
628
|
-
`app` instance
|
|
696
|
+
`app` instance, so uvicorn aborted with `Attribute "app" not found` and nothing bound
|
|
629
697
|
port 8700. The missing `app = create_app()` (present in `engraphis/app.py` and
|
|
630
698
|
`engraphis/redirector.py`, but dropped from `dashboard_app.py`) is now restored. The
|
|
631
699
|
background autosync/dreaming/revalidation loops inside `create_app()` are pytest-guarded,
|
|
@@ -649,7 +717,7 @@ and safe hosted deployment.
|
|
|
649
717
|
`tests/test_online_only_enforcement.py`.
|
|
650
718
|
- **Deterministic, offline sub-file chunking on the write path (`ENGRAPHIS_EXTRACTOR=chunk`).**
|
|
651
719
|
A third `Extractor` alongside passthrough/LLM: `ChunkingExtractor` splits a document into
|
|
652
|
-
retrieval-sized `ExtractedFact` chunks that preserve meaning
|
|
720
|
+
retrieval-sized `ExtractedFact` chunks that preserve meaning: markdown headings start new
|
|
653
721
|
chunks and become the title, fenced code blocks stay intact, prose is packed to a token
|
|
654
722
|
budget (`ENGRAPHIS_CHUNK_TOKENS`, default 256) with a sentence-level overlap
|
|
655
723
|
(`ENGRAPHIS_CHUNK_OVERLAP`, default 32); a hard per-document cap
|
|
@@ -667,7 +735,7 @@ and safe hosted deployment.
|
|
|
667
735
|
- **Chunking eval + `longdoc` dataset.** `eval/chunking_eval.py` +
|
|
668
736
|
`eval/datasets/longdoc.jsonl` compare whole-file vs chunked ingestion through the real
|
|
669
737
|
recall pipeline. On the offline embedder: identical recall@5 (1.000) at **~73% fewer
|
|
670
|
-
context tokens** (809 → 219) and ~4× smaller tokens-to-evidence (162 → 42)
|
|
738
|
+
context tokens** (809 → 219) and ~4× smaller tokens-to-evidence (162 → 42); the "quality per token"
|
|
671
739
|
number `BENCHMARKS.md` calls for. `tests/test_chunking_eval.py`.
|
|
672
740
|
- **"Dreaming" trigger for automated maintenance.** `automation.should_dream` / `dream_due`
|
|
673
741
|
run a consolidation sweep *before* the cadence when enough new episodic memories have
|
|
@@ -676,7 +744,7 @@ and safe hosted deployment.
|
|
|
676
744
|
cron behaviour is unchanged; still Pro-gated. `tests/test_dreaming_trigger.py`.
|
|
677
745
|
- **Associative cross-cluster inference (dream pass 4).** `consolidate.infer_links` /
|
|
678
746
|
`consolidate(infer=True)` proposes evidence-only links between memories in *different,
|
|
679
|
-
dissimilar* subject clusters that share a bridging entity
|
|
747
|
+
dissimilar* subject clusters that share a bridging entity: the "connect distant dots" step
|
|
680
748
|
same-subject distillation never reaches. **Off by default** (`infer=False`); the pass
|
|
681
749
|
follows the sweep's own `dry_run` flag, so a dry-run proposes into the report and a real
|
|
682
750
|
run applies. Applied inferences are low-salience (`importance=0.25`), `trusted:false`,
|
|
@@ -686,13 +754,13 @@ and safe hosted deployment.
|
|
|
686
754
|
`rediscovered`) and the per-sweep text scan is computed once, not per entity.
|
|
687
755
|
`tests/test_inference.py`.
|
|
688
756
|
- **Inference is reachable from the maintenance path.** A new `infer` policy knob (off
|
|
689
|
-
by default) runs the inference pass inside `run_maintenance
|
|
690
|
-
|
|
757
|
+
by default) runs the inference pass inside `run_maintenance`, whether manual or from the dream loop,
|
|
758
|
+
following the sweep's `dry_run`. `/api/consolidate` takes `infer` (`false` by default);
|
|
691
759
|
`/api/automation` round-trips `infer`; the dashboard Automation tab has an Inference
|
|
692
760
|
toggle. `tests/test_dashboard_v2.py` (policy round-trip + `/maintenance/run` proposes the
|
|
693
761
|
Redis bridge), `tests/test_dashboard_dream_ui.py`.
|
|
694
762
|
- **Dreaming runs without cron.** A dashboard background loop (`_maybe_start_dreaming`,
|
|
695
|
-
mirroring auto-sync) runs a maintenance sweep whenever `automation.dream_due` fires
|
|
763
|
+
mirroring auto-sync) runs a maintenance sweep whenever `automation.dream_due` fires. It is opt-in,
|
|
696
764
|
Pro-gated, fault-isolated, with an `ENGRAPHIS_DREAM_LOOP=0` kill switch. The `/api/automation`
|
|
697
765
|
policy round-trips the `dream` / `dream_min_new` / `dream_idle_minutes` knobs, and the
|
|
698
766
|
dashboard's Automation tab surfaces them as form controls (toggle + thresholds). The
|
|
@@ -710,7 +778,7 @@ and safe hosted deployment.
|
|
|
710
778
|
instance no longer deadlocks on the team-feature gate with no way to proceed.
|
|
711
779
|
No backend change; frontend-only.
|
|
712
780
|
- `MemoryService.create` now defaults `extractor` from `settings.extractor`
|
|
713
|
-
(`ENGRAPHIS_EXTRACTOR`) when unset
|
|
781
|
+
(`ENGRAPHIS_EXTRACTOR`) when unset, mirroring the existing `graph_extractor` fallback so
|
|
714
782
|
the dashboard and automated-maintenance front ends honor the config knob, not just the MCP
|
|
715
783
|
server and CLI. An explicit `extractor="none"` still overrides the environment.
|
|
716
784
|
|
|
@@ -733,12 +801,12 @@ and safe hosted deployment.
|
|
|
733
801
|
### Added
|
|
734
802
|
- **Personal vs. shared folders + a redesigned Team dashboard.** A folder can now be
|
|
735
803
|
created `visibility='personal'` (owned by, and visible/usable only to, the creating
|
|
736
|
-
dashboard user) or `shared` (the whole team
|
|
804
|
+
dashboard user) or `shared` (the whole team, the previous, still-default behaviour).
|
|
737
805
|
Enforcement runs through a single workspace-authorization chokepoint, so every scoped
|
|
738
806
|
read/write inherits it and a non-owner cannot access another user's personal folder.
|
|
739
807
|
Personal folders are excluded from relay sync so they stay on-device. The **Team
|
|
740
808
|
dashboard** gains a team overview (seat usage + activity), a Folders panel that creates
|
|
741
|
-
and manages shared/personal folders (folder creation now lives here
|
|
809
|
+
and manages shared/personal folders (folder creation now lives here: the Workspaces
|
|
742
810
|
tab is selection-only in team mode), members with last-active, and a team audit log with
|
|
743
811
|
CSV export. New/updated: `service.py`, `routes/v2_api.py`, `dashboard_app.py`,
|
|
744
812
|
`static/index.html`; tests in `tests/test_personal_folders.py`,
|
|
@@ -761,7 +829,7 @@ and safe hosted deployment.
|
|
|
761
829
|
with auth/license/trial routes instead of a permanently signed-out UI.
|
|
762
830
|
`engraphis-server` remains available as an explicit override for single-user
|
|
763
831
|
deployments.
|
|
764
|
-
- **CI**: ruff lint errors and core-floor (numpy-only) test collection
|
|
832
|
+
- **CI**: ruff lint errors and core-floor (numpy-only) test collection.
|
|
765
833
|
fastapi-dependent tests now skip cleanly on the minimal core floor. `loads_strict`
|
|
766
834
|
now rejects pathologically deep JSON on every Python version (3.12's JSON scanner
|
|
767
835
|
no longer raises RecursionError for ~1000-deep input, which had broken the
|
|
@@ -825,14 +893,14 @@ and safe hosted deployment.
|
|
|
825
893
|
### Fixed
|
|
826
894
|
- Static package discovery: `engraphis/static/__init__.py` added
|
|
827
895
|
- Vendor glob: recursive pattern so `static/vendor/` bundles ship in wheel
|
|
828
|
-
- Dashboard 500 on `GET
|
|
829
|
-
- Dashboard 500 on fresh install
|
|
896
|
+
- Dashboard 500 on `GET /`: `static/index.html` was missing from wheel (packaging bug)
|
|
897
|
+
- Dashboard 500 on fresh install: `GET /api/memories` crashed on empty workspace
|
|
830
898
|
|
|
831
899
|
---
|
|
832
900
|
|
|
833
901
|
## Earlier versions (condensed)
|
|
834
902
|
|
|
835
|
-
### 0.5.x
|
|
903
|
+
### Versions 0.5.x to 0.7.x
|
|
836
904
|
- MCP server with 18 tools
|
|
837
905
|
- Memory Inspector product UI (`engraphis-inspector`, port 8710)
|
|
838
906
|
- Dashboard rebuilt on v2 engine with recall, governance, consolidate, analytics
|
|
@@ -846,7 +914,7 @@ and safe hosted deployment.
|
|
|
846
914
|
- Docker + docker-compose deployment
|
|
847
915
|
- 300+ tests, eval harness, ablation suite
|
|
848
916
|
|
|
849
|
-
### 0.1.0
|
|
917
|
+
### [0.1.0] - 2026-07-09
|
|
850
918
|
- Initial public release: local-first AI memory engine for agents
|
|
851
919
|
- Ebbinghaus decay, interaction-aware recall, bi-temporal facts
|
|
852
920
|
- Background consolidation; you bring the LLM
|
|
@@ -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
|