engraphis 1.2.0__tar.gz → 1.2.2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {engraphis-1.2.0 → engraphis-1.2.2}/BENCHMARKS.md +9 -9
- {engraphis-1.2.0 → engraphis-1.2.2}/CHANGELOG.md +60 -31
- {engraphis-1.2.0 → engraphis-1.2.2}/PKG-INFO +153 -95
- {engraphis-1.2.0 → engraphis-1.2.2}/README.md +150 -94
- {engraphis-1.2.0 → engraphis-1.2.2}/engraphis/__init__.py +1 -1
- {engraphis-1.2.0 → engraphis-1.2.2}/engraphis/backends/sync_folder.py +15 -8
- {engraphis-1.2.0 → engraphis-1.2.2}/engraphis/backends/sync_relay.py +148 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/engraphis/classic_assets/dashboard.js +5 -4
- {engraphis-1.2.0 → engraphis-1.2.2}/engraphis/commercial_manifest.json +2 -2
- {engraphis-1.2.0 → engraphis-1.2.2}/engraphis/dashboard_assets/ledger.css +2 -2
- {engraphis-1.2.0 → engraphis-1.2.2}/engraphis/dashboard_assets/ledger.js +4 -3
- {engraphis-1.2.0 → engraphis-1.2.2}/engraphis/static/dashboard.js +5 -4
- {engraphis-1.2.0 → engraphis-1.2.2}/engraphis.egg-info/PKG-INFO +153 -95
- {engraphis-1.2.0 → engraphis-1.2.2}/engraphis.egg-info/SOURCES.txt +1 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/engraphis.egg-info/requires.txt +5 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/pyproject.toml +6 -1
- {engraphis-1.2.0 → engraphis-1.2.2}/scripts/check_commercial_manifest.py +0 -1
- {engraphis-1.2.0 → engraphis-1.2.2}/scripts/sync.py +5 -1
- {engraphis-1.2.0 → engraphis-1.2.2}/tests/test_benchmark_evidence.py +96 -3
- {engraphis-1.2.0 → engraphis-1.2.2}/tests/test_commercial_hardening.py +7 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/tests/test_dashboard_auth_placement.py +31 -7
- {engraphis-1.2.0 → engraphis-1.2.2}/tests/test_sync_cli.py +23 -5
- engraphis-1.2.2/tests/test_sync_e2ee.py +153 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/.env.example +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/Dockerfile +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/LICENSE +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/MANIFEST.in +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/NOTICE +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/docker-compose.yml +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/docker-entrypoint.sh +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/engraphis/ai_context.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/engraphis/app.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/engraphis/backends/__init__.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/engraphis/backends/codegraph.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/engraphis/backends/embedder_api.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/engraphis/backends/embedder_deterministic.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/engraphis/backends/embedder_st.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/engraphis/backends/encrypted_db.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/engraphis/backends/extractor.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/engraphis/backends/graph_extractor.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/engraphis/backends/postgres_schema.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/engraphis/backends/reranker.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/engraphis/backends/resources.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/engraphis/backends/retention.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/engraphis/backends/vector_numpy.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/engraphis/backends/vector_sqlitevec.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/engraphis/classic_assets/__init__.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/engraphis/classic_assets/dashboard.css +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/engraphis/classic_assets/engraphis-graph.js +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/engraphis/classic_assets/engraphis-icon.png +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/engraphis/classic_assets/engraphis.ico +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/engraphis/classic_assets/favicon-32.png +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/engraphis/classic_assets/index.html +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/engraphis/classic_assets/vendor/d3.LICENSE +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/engraphis/classic_assets/vendor/d3.min.js +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/engraphis/classic_assets/vendor/force-graph.LICENSE +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/engraphis/classic_assets/vendor/force-graph.min.js +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/engraphis/classic_assets/vendor/marked.LICENSE +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/engraphis/classic_assets/vendor/marked.min.js +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/engraphis/classic_assets/vendor/purify.min.js +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/engraphis/cloud_features.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/engraphis/cloud_session.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/engraphis/commercial.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/engraphis/config.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/engraphis/core/__init__.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/engraphis/core/codegraph_export.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/engraphis/core/conflicts.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/engraphis/core/consolidate.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/engraphis/core/context.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/engraphis/core/engine.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/engraphis/core/graph_layers.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/engraphis/core/graph_scene.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/engraphis/core/graphrank.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/engraphis/core/grounded.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/engraphis/core/ids.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/engraphis/core/interfaces.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/engraphis/core/recall.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/engraphis/core/resolve.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/engraphis/core/retrieval_policy.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/engraphis/core/schema.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/engraphis/core/scoring.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/engraphis/core/store.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/engraphis/core/sync.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/engraphis/core/textutil.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/engraphis/core/user_model.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/engraphis/dashboard_app.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/engraphis/dashboard_assets/__init__.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/engraphis/dashboard_assets/engraphis-graph-compat.js +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/engraphis/dashboard_assets/engraphis-graph.js +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/engraphis/dashboard_assets/engraphis-icon.png +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/engraphis/dashboard_assets/engraphis.ico +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/engraphis/dashboard_assets/favicon-32.png +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/engraphis/dashboard_assets/index.html +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/engraphis/dashboard_assets/vendor/d3.LICENSE +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/engraphis/dashboard_assets/vendor/d3.min.js +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/engraphis/dashboard_assets/vendor/force-graph.LICENSE +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/engraphis/dashboard_assets/vendor/force-graph.min.js +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/engraphis/device_connect.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/engraphis/engines/__init__.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/engraphis/engines/embedder.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/engraphis/engines/ingest.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/engraphis/engines/intelligence.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/engraphis/engines/recall.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/engraphis/engines/reweight.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/engraphis/engines/thoughts.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/engraphis/graphdata.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/engraphis/hosted_client.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/engraphis/http_security.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/engraphis/inspector/__init__.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/engraphis/inspector/app.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/engraphis/licensing.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/engraphis/llm/__init__.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/engraphis/llm/client.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/engraphis/local_auth.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/engraphis/logging_setup.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/engraphis/mcp_cli.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/engraphis/mcp_server.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/engraphis/models.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/engraphis/netutil.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/engraphis/observability.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/engraphis/private_state.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/engraphis/read_only_api.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/engraphis/redirector.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/engraphis/routes/__init__.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/engraphis/routes/memory.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/engraphis/routes/v2_api.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/engraphis/routes/vault.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/engraphis/service.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/engraphis/static/__init__.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/engraphis/static/dashboard.css +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/engraphis/static/engraphis-graph.js +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/engraphis/static/engraphis-icon.png +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/engraphis/static/engraphis.ico +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/engraphis/static/favicon-32.png +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/engraphis/static/index.html +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/engraphis/static/vendor/d3.LICENSE +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/engraphis/static/vendor/d3.min.js +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/engraphis/static/vendor/force-graph.LICENSE +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/engraphis/static/vendor/force-graph.min.js +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/engraphis/static/vendor/marked.LICENSE +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/engraphis/static/vendor/marked.min.js +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/engraphis/static/vendor/purify.min.js +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/engraphis/stores/__init__.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/engraphis/stores/graph.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/engraphis/stores/ledger.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/engraphis/stores/vaults.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/engraphis/stores/vectors.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/engraphis/update_check.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/engraphis.egg-info/dependency_links.txt +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/engraphis.egg-info/entry_points.txt +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/engraphis.egg-info/top_level.txt +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/eval/BASELINES.md +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/eval/__init__.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/eval/ablation.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/eval/benchmark.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/eval/chunking_eval.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/eval/configs/longmemeval_v2_engraphis.json +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/eval/datasets/adversarial.jsonl +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/eval/datasets/codemem.jsonl +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/eval/datasets/graph_multihop.jsonl +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/eval/datasets/longdoc.jsonl +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/eval/datasets/sample.jsonl +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/eval/external.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/eval/grounded.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/eval/harness.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/eval/longmemeval_v2.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/eval/metrics.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/eval/performance.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/eval/run_longmemeval_v2.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/railway.json +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/requirements.txt +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/scripts/__init__.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/scripts/backfill_graph.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/scripts/check_codeql_sarif.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/scripts/cli.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/scripts/connect.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/scripts/consolidate.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/scripts/entry.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/scripts/externalize_dashboard_assets.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/scripts/graph_cli.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/scripts/graph_server.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/scripts/init.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/scripts/inspector.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/scripts/install_shortcuts.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/scripts/mcp_server_http.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/scripts/migrate_to_v2.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/scripts/release_evidence.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/scripts/repair_embed_dim.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/scripts/sdk_compat.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/scripts/seed_from_obsidian.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/scripts/start_dashboard.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/scripts/start_server.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/scripts/test_routes.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/scripts/update.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/scripts/verify_distribution_contents.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/scripts/verify_release_artifacts.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/setup.cfg +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/setup.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/tests/__init__.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/tests/conftest.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/tests/test_agent_connect.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/tests/test_app_auth.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/tests/test_backends_factories.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/tests/test_benchmark_adversarial.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/tests/test_benchmark_longmemeval_v2.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/tests/test_bitemporal_recall.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/tests/test_canonical_export.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/tests/test_chunking_eval.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/tests/test_chunking_extractor.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/tests/test_cli_entrypoints.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/tests/test_client_launch.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/tests/test_cloud_features.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/tests/test_cloud_session.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/tests/test_code_index_route_security.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/tests/test_code_recall_arm.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/tests/test_codegraph.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/tests/test_codeql_sarif_gate.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/tests/test_compact_recall.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/tests/test_config.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/tests/test_conflicts.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/tests/test_consolidate.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/tests/test_context_packing.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/tests/test_core_ids.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/tests/test_core_store.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/tests/test_cron_write_tools_workspace_default.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/tests/test_customer_node_hardening.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/tests/test_dashboard_button_regressions.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/tests/test_dashboard_dream_ui.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/tests/test_dashboard_security_headers_and_open_window.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/tests/test_dashboard_v2.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/tests/test_db_path_default.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/tests/test_decay_idempotent.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/tests/test_device_connect.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/tests/test_embedder_threading.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/tests/test_encrypted_store.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/tests/test_encryption_dependency.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/tests/test_engine.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/tests/test_eval_ablation.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/tests/test_eval_external.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/tests/test_eval_grounded.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/tests/test_eval_harness.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/tests/test_eval_performance.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/tests/test_externalize_dashboard_assets.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/tests/test_extractor.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/tests/test_graph_cli.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/tests/test_graph_engine_asset.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/tests/test_graph_explorer_v2.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/tests/test_graph_extractor.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/tests/test_graph_scene_contract.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/tests/test_graph_server.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/tests/test_graphdata.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/tests/test_graphrank.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/tests/test_grounded.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/tests/test_hosted_client.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/tests/test_hosted_plan_resolution.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/tests/test_http_security.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/tests/test_import_chunking.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/tests/test_import_error_redaction.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/tests/test_ingest_entities.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/tests/test_init.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/tests/test_inspector.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/tests/test_inspector_pro.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/tests/test_intent_paywall.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/tests/test_licensing_boundary_docs.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/tests/test_licensing_launch.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/tests/test_llm_config.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/tests/test_llm_dashboard.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/tests/test_local_auth_browser_session.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/tests/test_logging_setup.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/tests/test_mcp_annotation_idempotency.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/tests/test_mcp_server.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/tests/test_memory_routes_fixes.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/tests/test_merge.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/tests/test_metadata_activity_forgery.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/tests/test_migration.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/tests/test_netutil.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/tests/test_observability.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/tests/test_packaging.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/tests/test_personal_folders.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/tests/test_postgres_schema.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/tests/test_private_state_boundaries.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/tests/test_pro_cta.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/tests/test_proactive_context.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/tests/test_protocol_upgrades.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/tests/test_provenance_flags.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/tests/test_provider_error_redaction.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/tests/test_public_research_boundary.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/tests/test_read_only_api.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/tests/test_ready.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/tests/test_recall.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/tests/test_recall_entity_workspace_widening.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/tests/test_receipts.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/tests/test_relay_device_credentials.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/tests/test_release_artifacts.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/tests/test_release_evidence.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/tests/test_release_infrastructure.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/tests/test_remember_atomicity.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/tests/test_resolve.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/tests/test_resources.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/tests/test_retention.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/tests/test_retrieval_policy.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/tests/test_round17_fixes.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/tests/test_scoring.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/tests/test_security_fixes.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/tests/test_service.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/tests/test_service_graph.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/tests/test_service_isolation.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/tests/test_session_idempotent.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/tests/test_start_dashboard.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/tests/test_start_session_workspace_default.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/tests/test_store_v4_migration.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/tests/test_sync.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/tests/test_sync_dashboard.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/tests/test_update.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/tests/test_update_check.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/tests/test_user_model.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/tests/test_v1_auto_migrate.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/tests/test_v1_hardening.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/tests/test_v1_licensing.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/tests/test_vector_numpy.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/tests/test_vector_sqlitevec_backend.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/tests/test_workspace_isolation.py +0 -0
- {engraphis-1.2.0 → engraphis-1.2.2}/tests/test_workspace_ops.py +0 -0
|
@@ -9,30 +9,30 @@ been written; when this and the code disagree, the code wins (CLAUDE.md).
|
|
|
9
9
|
Engraphis's eval harness scores **retrieval**, not end-to-end QA. That distinction is deliberate
|
|
10
10
|
and stated everywhere the numbers appear (`eval/external.py`).
|
|
11
11
|
|
|
12
|
-
- **Correctness gate
|
|
12
|
+
- **Correctness gate**: `eval/harness.py` over `eval/datasets/sample.jsonl` and
|
|
13
13
|
`codemem.jsonl` (conflict resolution) and `graph_multihop.jsonl` (multi-hop graph recall).
|
|
14
14
|
Runs on the deterministic embedder, so it is a plumbing/regression floor, not a public
|
|
15
15
|
performance claim. This is the gate CI enforces.
|
|
16
|
-
- **Ablation
|
|
16
|
+
- **Ablation**: `eval/ablation.py`: vector-only vs. 1-hop graph vs. Personalized-PageRank arm,
|
|
17
17
|
to show the graph arm actually earns its place.
|
|
18
|
-
- **External benchmarks
|
|
18
|
+
- **External benchmarks**: `eval/external.py` loads **LoCoMo** and **LongMemEval** and pushes
|
|
19
19
|
them through the *real* `MemoryEngine` write path (conflict resolution + evolution) and hybrid
|
|
20
20
|
recall with a real sentence-transformers embedder. It reports `recall_at_k` / `hit_at_k` /
|
|
21
|
-
`answer_token_recall
|
|
21
|
+
`answer_token_recall`: i.e. *did the evidence come back*, not *did an LLM answer correctly*.
|
|
22
22
|
It retains source categories and abstention/no-evidence questions as explicit exclusions from
|
|
23
23
|
retrieval-only aggregates rather than silently dropping them. `eval.longmemeval_v2` is a local,
|
|
24
24
|
text-only adapter for the official LongMemEval-V2 `insert(trajectory)` / `query(query,
|
|
25
25
|
query_image=None)` memory interface; it does not download data or call a model.
|
|
26
|
-
- **Grounded
|
|
27
|
-
- **Chunking (quality per token)
|
|
28
|
-
ingests a multi-topic corpus twice
|
|
29
|
-
`ChunkingExtractor` (`chunked`)
|
|
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
30
|
the first cut of the context-reduction metric (item 3 below). On the deterministic embedder:
|
|
31
31
|
**recall@5 1.000 for both, at ~73% fewer context tokens (809 → 219) and ~4× smaller
|
|
32
32
|
tokens-to-evidence (162 → 42).** Pass `--embed-model sentence-transformers/all-MiniLM-L6-v2`
|
|
33
33
|
for a real retrieval number (recall should then favour chunked on larger corpora, not just
|
|
34
34
|
tie).
|
|
35
|
-
- **Full-pipeline latency + quality
|
|
35
|
+
- **Full-pipeline latency + quality**: `eval/performance.py` times the shipped semantic +
|
|
36
36
|
lexical + graph + fusion + scoring + rerank + packing path after warmup, with reinforcement
|
|
37
37
|
disabled so repeated measurements do not mutate their corpus. It reports p50/p95/p99 latency,
|
|
38
38
|
retrieval quality, and packed context tokens in one JSON-safe schema. `--filler-memories`
|
|
@@ -3,6 +3,35 @@
|
|
|
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
|
+
## [1.2.2] - 2026-07-30
|
|
7
|
+
|
|
8
|
+
### Fixed
|
|
9
|
+
|
|
10
|
+
- Cloud Sync now continues past legacy plaintext, malformed, and tampered relay objects while
|
|
11
|
+
still failing closed for each object. Later authenticated peer bundles apply, and the affected
|
|
12
|
+
sync round is explicitly reported as incomplete rather than successful.
|
|
13
|
+
- Security and sync documentation now consistently distinguish end-to-end encrypted Cloud Sync
|
|
14
|
+
from the separately readable managed-compute snapshot service.
|
|
15
|
+
- README visual PNG exports now use their SVG canvas dimensions without hidden screenshot padding.
|
|
16
|
+
|
|
17
|
+
## [1.2.1] - 2026-07-30
|
|
18
|
+
|
|
19
|
+
### Security
|
|
20
|
+
|
|
21
|
+
- Cloud Sync now encrypts every eligible shared-workspace bundle on the client with
|
|
22
|
+
ChaCha20-Poly1305 before upload. The relay receives opaque deterministic bundle names and
|
|
23
|
+
ciphertext only; tampered, renamed, cross-workspace, wrong-key, and legacy plaintext bundles
|
|
24
|
+
are rejected before the merge engine.
|
|
25
|
+
- Cloud Sync requires a client-held 32-byte workspace key and the `cloud-sync` optional runtime.
|
|
26
|
+
Missing or malformed encryption configuration stops sync rather than falling back to plaintext.
|
|
27
|
+
|
|
28
|
+
### Changed
|
|
29
|
+
|
|
30
|
+
- Cloud Sync privacy copy now states that eligible shared-workspace changes are encrypted
|
|
31
|
+
end-to-end before leaving the device and cannot be read by Engraphis Cloud. Product and
|
|
32
|
+
security documentation separately identifies managed compute as the readable, bounded-snapshot
|
|
33
|
+
service it is.
|
|
34
|
+
|
|
6
35
|
## [1.2.0] - 2026-07-30
|
|
7
36
|
|
|
8
37
|
### Added
|
|
@@ -116,21 +145,21 @@ Public 1.1.0 hosted-connect and graph-experience release.
|
|
|
116
145
|
|
|
117
146
|
### Added
|
|
118
147
|
|
|
119
|
-
- **`engraphis connect --token engr_ct_
|
|
148
|
+
- **`engraphis connect --token engr_ct_…`**: the missing client half of device connect.
|
|
120
149
|
`cloud_session.save_bootstrap()` is the only writer of `~/.engraphis/cloud_session.json`,
|
|
121
150
|
and it had no production caller: the docs told paying customers to prefer a file nothing
|
|
122
151
|
created, so a purchased installation could not be connected without hand-writing state.
|
|
123
152
|
The new command redeems the one-time connect token from the account portal against
|
|
124
153
|
`POST /v1/devices/connect`, saves the returned session with owner-only permissions, and
|
|
125
154
|
verifies `cloud_session.configured()` before reporting success. The token is sent in the
|
|
126
|
-
request body and nowhere else
|
|
155
|
+
request body and nowhere else; it is never printed, logged, or written to disk, and every
|
|
127
156
|
refusal maps to fixed, actionable copy (an expired or already-used token is not confused
|
|
128
157
|
with a lapsed subscription). Session storage is pre-flighted before the exchange, so an
|
|
129
158
|
unwritable state directory or a `cloud_session.json` replaced by a link fails the command
|
|
130
|
-
*without* spending the single-use token
|
|
159
|
+
*without* spending the single-use token; the customer fixes the path and retries with the
|
|
131
160
|
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`)
|
|
161
|
+
*after* the exchange: a reply truncated mid-body (`http.client.IncompleteRead`), or an
|
|
162
|
+
endpoint that stops resolving before the session is written (`CloudUrlUnresolved`) are
|
|
134
163
|
reported as errors that say the token was already used, rather than escaping as tracebacks
|
|
135
164
|
that leave the customer unable to tell whether to retry. Also installed as
|
|
136
165
|
`engraphis-connect`.
|
|
@@ -328,7 +357,7 @@ and safe hosted deployment.
|
|
|
328
357
|
|
|
329
358
|
### Security
|
|
330
359
|
|
|
331
|
-
- Every entrypoint sends baseline response headers
|
|
360
|
+
- Every entrypoint sends baseline response headers: CSP, `X-Frame-Options: DENY`,
|
|
332
361
|
`X-Content-Type-Options`, `Referrer-Policy`, `Permissions-Policy`, and HSTS over HTTPS
|
|
333
362
|
only. Override with `ENGRAPHIS_CSP` / `ENGRAPHIS_HSTS`; set either to an empty string to
|
|
334
363
|
omit that header where a fronting proxy supplies its own.
|
|
@@ -422,10 +451,10 @@ and safe hosted deployment.
|
|
|
422
451
|
insert sequence (engine-level write lock): concurrent near-duplicate writes can no
|
|
423
452
|
longer both resolve ADD and store duplicates instead of NOOP/INVALIDATE.
|
|
424
453
|
- The Inspector's `/api/auth/login`/`setup` no longer run PBKDF2 (600k iterations)
|
|
425
|
-
on the asyncio event loop
|
|
454
|
+
on the asyncio event loop; password hashing moved to a worker thread, so a burst
|
|
426
455
|
of logins can't stall every other request.
|
|
427
456
|
- A failed vector-index upsert on the write path is now logged and audited
|
|
428
|
-
(`index_upsert_failed`) instead of silently swallowed
|
|
457
|
+
(`index_upsert_failed`) instead of silently swallowed. Previously, the memory
|
|
429
458
|
stayed invisible to semantic recall with no trace.
|
|
430
459
|
- URLs built from a bind host are now IPv6-safe and connectable (`engraphis.netutil`):
|
|
431
460
|
`ENGRAPHIS_HOST=::` no longer yields the malformed `http://:::8700` in the printed
|
|
@@ -468,7 +497,7 @@ and safe hosted deployment.
|
|
|
468
497
|
|
|
469
498
|
### Fixed
|
|
470
499
|
- 1-hop graph recall (and the PPR large-graph fallback) now honors `graph_layers`, matching
|
|
471
|
-
the PPR arm
|
|
500
|
+
the PPR arm: `Store.neighbors()` gained a `layers` filter.
|
|
472
501
|
- `FolderTransport.push()` no longer follows peer-planted symlinks in the shared sync folder
|
|
473
502
|
(unpredictable temp name + `O_CREAT|O_EXCL|O_NOFOLLOW`), closing an arbitrary-file-write
|
|
474
503
|
vector that mirrored the already-hardened read side.
|
|
@@ -477,7 +506,7 @@ and safe hosted deployment.
|
|
|
477
506
|
- Caller-supplied `metadata.retention_supervision` is stripped at the service boundary; only
|
|
478
507
|
the validated `retention_class` presets can influence importance/stability.
|
|
479
508
|
- `merge_workspaces()` no longer duplicates symbols/code edges when both workspaces indexed
|
|
480
|
-
the same file in a same-named repo
|
|
509
|
+
the same file in a same-named repo: the losing snapshot's rows are cleared, and its
|
|
481
510
|
memory↔code links are re-pointed at the surviving same-fqname symbols.
|
|
482
511
|
- `engraphis-graph impact/prs` reject leading-dash git revisions (git option injection), and
|
|
483
512
|
graph exports refuse a symlinked output directory and are written atomically without
|
|
@@ -486,7 +515,7 @@ and safe hosted deployment.
|
|
|
486
515
|
(`limit`-derived cap) so a large workspace graph or indexed repo can't produce unbounded
|
|
487
516
|
viewer-role responses.
|
|
488
517
|
- Relay sync fails closed when a workspace's settings are unreadable rather than treating a
|
|
489
|
-
possibly-personal folder as shared
|
|
518
|
+
possibly-personal folder as shared: in the sync CLI and in the dashboard/background
|
|
490
519
|
`_sync_all` path; resource extraction enforces its own raw-size cap.
|
|
491
520
|
|
|
492
521
|
## [0.9.6] - 2026-07-16
|
|
@@ -574,10 +603,10 @@ and safe hosted deployment.
|
|
|
574
603
|
### Changed
|
|
575
604
|
- **Team mode is now ON by default (opt-out).** `ENGRAPHIS_TEAM_MODE` defaults to on;
|
|
576
605
|
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
|
|
606
|
+
no longer raised just because the mode flag is on. It now requires a *live* `team`
|
|
578
607
|
feature entitlement (`licensing.has_feature("team")`), checked at request time in
|
|
579
608
|
`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
|
|
609
|
+
fully open, and the wall appears the moment a team license key is added, even via the
|
|
581
610
|
dashboard UI at runtime. A `team` license is still required to *add seats* beyond the
|
|
582
611
|
first admin (bootstrap admin is created unconditionally). Docs (`.env.example`,
|
|
583
612
|
`AGENTS.md`, `README.md`, `SECURITY.md`, `scripts/init.py`) and team-mode test fixtures
|
|
@@ -585,11 +614,11 @@ and safe hosted deployment.
|
|
|
585
614
|
- **Team-invite email rewritten to separate "join" from "activate a key".** The old
|
|
586
615
|
invite conflated the two, so members pasted the shared team key into the hosted/Railway
|
|
587
616
|
dashboard, saw it "work" (it just re-activated a license already active there), and
|
|
588
|
-
thought they'd joined
|
|
617
|
+
thought they'd joined, when joining means signing in with email + password. The email
|
|
589
618
|
now frames two distinct options: **Option 1** (required to join) sign in to the team
|
|
590
|
-
dashboard with email + the admin-set password
|
|
619
|
+
dashboard with email + the admin-set password, with explicitly *no license key needed here,
|
|
591
620
|
don't paste one*; **Option 2** (optional) run Engraphis on your own machine and access
|
|
592
|
-
the team's memories locally
|
|
621
|
+
the team's memories locally; that is what the shared team key is for (LOCAL
|
|
593
622
|
`http://127.0.0.1:8700` → Settings → License, then Settings → Cloud Sync to pull the
|
|
594
623
|
converged team store down to a local offline copy). Invites now always carry a
|
|
595
624
|
clickable sign-in link: `dashboard_url` resolves explicit arg → `ENGRAPHIS_DASHBOARD_URL`
|
|
@@ -625,7 +654,7 @@ and safe hosted deployment.
|
|
|
625
654
|
- **The dashboard (`engraphis-dashboard` / `http://127.0.0.1:8700`) would not start.**
|
|
626
655
|
`scripts/start_dashboard.py` runs uvicorn against `engraphis.dashboard_app:app`, but
|
|
627
656
|
`dashboard_app.py` only defined the `create_app()` factory and never built a module-level
|
|
628
|
-
`app` instance
|
|
657
|
+
`app` instance, so uvicorn aborted with `Attribute "app" not found` and nothing bound
|
|
629
658
|
port 8700. The missing `app = create_app()` (present in `engraphis/app.py` and
|
|
630
659
|
`engraphis/redirector.py`, but dropped from `dashboard_app.py`) is now restored. The
|
|
631
660
|
background autosync/dreaming/revalidation loops inside `create_app()` are pytest-guarded,
|
|
@@ -649,7 +678,7 @@ and safe hosted deployment.
|
|
|
649
678
|
`tests/test_online_only_enforcement.py`.
|
|
650
679
|
- **Deterministic, offline sub-file chunking on the write path (`ENGRAPHIS_EXTRACTOR=chunk`).**
|
|
651
680
|
A third `Extractor` alongside passthrough/LLM: `ChunkingExtractor` splits a document into
|
|
652
|
-
retrieval-sized `ExtractedFact` chunks that preserve meaning
|
|
681
|
+
retrieval-sized `ExtractedFact` chunks that preserve meaning: markdown headings start new
|
|
653
682
|
chunks and become the title, fenced code blocks stay intact, prose is packed to a token
|
|
654
683
|
budget (`ENGRAPHIS_CHUNK_TOKENS`, default 256) with a sentence-level overlap
|
|
655
684
|
(`ENGRAPHIS_CHUNK_OVERLAP`, default 32); a hard per-document cap
|
|
@@ -667,7 +696,7 @@ and safe hosted deployment.
|
|
|
667
696
|
- **Chunking eval + `longdoc` dataset.** `eval/chunking_eval.py` +
|
|
668
697
|
`eval/datasets/longdoc.jsonl` compare whole-file vs chunked ingestion through the real
|
|
669
698
|
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)
|
|
699
|
+
context tokens** (809 → 219) and ~4× smaller tokens-to-evidence (162 → 42); the "quality per token"
|
|
671
700
|
number `BENCHMARKS.md` calls for. `tests/test_chunking_eval.py`.
|
|
672
701
|
- **"Dreaming" trigger for automated maintenance.** `automation.should_dream` / `dream_due`
|
|
673
702
|
run a consolidation sweep *before* the cadence when enough new episodic memories have
|
|
@@ -676,7 +705,7 @@ and safe hosted deployment.
|
|
|
676
705
|
cron behaviour is unchanged; still Pro-gated. `tests/test_dreaming_trigger.py`.
|
|
677
706
|
- **Associative cross-cluster inference (dream pass 4).** `consolidate.infer_links` /
|
|
678
707
|
`consolidate(infer=True)` proposes evidence-only links between memories in *different,
|
|
679
|
-
dissimilar* subject clusters that share a bridging entity
|
|
708
|
+
dissimilar* subject clusters that share a bridging entity: the "connect distant dots" step
|
|
680
709
|
same-subject distillation never reaches. **Off by default** (`infer=False`); the pass
|
|
681
710
|
follows the sweep's own `dry_run` flag, so a dry-run proposes into the report and a real
|
|
682
711
|
run applies. Applied inferences are low-salience (`importance=0.25`), `trusted:false`,
|
|
@@ -686,13 +715,13 @@ and safe hosted deployment.
|
|
|
686
715
|
`rediscovered`) and the per-sweep text scan is computed once, not per entity.
|
|
687
716
|
`tests/test_inference.py`.
|
|
688
717
|
- **Inference is reachable from the maintenance path.** A new `infer` policy knob (off
|
|
689
|
-
by default) runs the inference pass inside `run_maintenance
|
|
690
|
-
|
|
718
|
+
by default) runs the inference pass inside `run_maintenance`, whether manual or from the dream loop,
|
|
719
|
+
following the sweep's `dry_run`. `/api/consolidate` takes `infer` (`false` by default);
|
|
691
720
|
`/api/automation` round-trips `infer`; the dashboard Automation tab has an Inference
|
|
692
721
|
toggle. `tests/test_dashboard_v2.py` (policy round-trip + `/maintenance/run` proposes the
|
|
693
722
|
Redis bridge), `tests/test_dashboard_dream_ui.py`.
|
|
694
723
|
- **Dreaming runs without cron.** A dashboard background loop (`_maybe_start_dreaming`,
|
|
695
|
-
mirroring auto-sync) runs a maintenance sweep whenever `automation.dream_due` fires
|
|
724
|
+
mirroring auto-sync) runs a maintenance sweep whenever `automation.dream_due` fires. It is opt-in,
|
|
696
725
|
Pro-gated, fault-isolated, with an `ENGRAPHIS_DREAM_LOOP=0` kill switch. The `/api/automation`
|
|
697
726
|
policy round-trips the `dream` / `dream_min_new` / `dream_idle_minutes` knobs, and the
|
|
698
727
|
dashboard's Automation tab surfaces them as form controls (toggle + thresholds). The
|
|
@@ -710,7 +739,7 @@ and safe hosted deployment.
|
|
|
710
739
|
instance no longer deadlocks on the team-feature gate with no way to proceed.
|
|
711
740
|
No backend change; frontend-only.
|
|
712
741
|
- `MemoryService.create` now defaults `extractor` from `settings.extractor`
|
|
713
|
-
(`ENGRAPHIS_EXTRACTOR`) when unset
|
|
742
|
+
(`ENGRAPHIS_EXTRACTOR`) when unset, mirroring the existing `graph_extractor` fallback so
|
|
714
743
|
the dashboard and automated-maintenance front ends honor the config knob, not just the MCP
|
|
715
744
|
server and CLI. An explicit `extractor="none"` still overrides the environment.
|
|
716
745
|
|
|
@@ -733,12 +762,12 @@ and safe hosted deployment.
|
|
|
733
762
|
### Added
|
|
734
763
|
- **Personal vs. shared folders + a redesigned Team dashboard.** A folder can now be
|
|
735
764
|
created `visibility='personal'` (owned by, and visible/usable only to, the creating
|
|
736
|
-
dashboard user) or `shared` (the whole team
|
|
765
|
+
dashboard user) or `shared` (the whole team, the previous, still-default behaviour).
|
|
737
766
|
Enforcement runs through a single workspace-authorization chokepoint, so every scoped
|
|
738
767
|
read/write inherits it and a non-owner cannot access another user's personal folder.
|
|
739
768
|
Personal folders are excluded from relay sync so they stay on-device. The **Team
|
|
740
769
|
dashboard** gains a team overview (seat usage + activity), a Folders panel that creates
|
|
741
|
-
and manages shared/personal folders (folder creation now lives here
|
|
770
|
+
and manages shared/personal folders (folder creation now lives here: the Workspaces
|
|
742
771
|
tab is selection-only in team mode), members with last-active, and a team audit log with
|
|
743
772
|
CSV export. New/updated: `service.py`, `routes/v2_api.py`, `dashboard_app.py`,
|
|
744
773
|
`static/index.html`; tests in `tests/test_personal_folders.py`,
|
|
@@ -761,7 +790,7 @@ and safe hosted deployment.
|
|
|
761
790
|
with auth/license/trial routes instead of a permanently signed-out UI.
|
|
762
791
|
`engraphis-server` remains available as an explicit override for single-user
|
|
763
792
|
deployments.
|
|
764
|
-
- **CI**: ruff lint errors and core-floor (numpy-only) test collection
|
|
793
|
+
- **CI**: ruff lint errors and core-floor (numpy-only) test collection.
|
|
765
794
|
fastapi-dependent tests now skip cleanly on the minimal core floor. `loads_strict`
|
|
766
795
|
now rejects pathologically deep JSON on every Python version (3.12's JSON scanner
|
|
767
796
|
no longer raises RecursionError for ~1000-deep input, which had broken the
|
|
@@ -825,14 +854,14 @@ and safe hosted deployment.
|
|
|
825
854
|
### Fixed
|
|
826
855
|
- Static package discovery: `engraphis/static/__init__.py` added
|
|
827
856
|
- Vendor glob: recursive pattern so `static/vendor/` bundles ship in wheel
|
|
828
|
-
- Dashboard 500 on `GET
|
|
829
|
-
- Dashboard 500 on fresh install
|
|
857
|
+
- Dashboard 500 on `GET /`: `static/index.html` was missing from wheel (packaging bug)
|
|
858
|
+
- Dashboard 500 on fresh install: `GET /api/memories` crashed on empty workspace
|
|
830
859
|
|
|
831
860
|
---
|
|
832
861
|
|
|
833
862
|
## Earlier versions (condensed)
|
|
834
863
|
|
|
835
|
-
### 0.5.x
|
|
864
|
+
### Versions 0.5.x to 0.7.x
|
|
836
865
|
- MCP server with 18 tools
|
|
837
866
|
- Memory Inspector product UI (`engraphis-inspector`, port 8710)
|
|
838
867
|
- Dashboard rebuilt on v2 engine with recall, governance, consolidate, analytics
|
|
@@ -846,7 +875,7 @@ and safe hosted deployment.
|
|
|
846
875
|
- Docker + docker-compose deployment
|
|
847
876
|
- 300+ tests, eval harness, ablation suite
|
|
848
877
|
|
|
849
|
-
### 0.1.0
|
|
878
|
+
### [0.1.0] - 2026-07-09
|
|
850
879
|
- Initial public release: local-first AI memory engine for agents
|
|
851
880
|
- Ebbinghaus decay, interaction-aware recall, bi-temporal facts
|
|
852
881
|
- Background consolidation; you bring the LLM
|