diff --git a/.claude-plugin/marketplace.json b/.claude-plugin/marketplace.json index 7f67a2c6..f41c79d5 100644 --- a/.claude-plugin/marketplace.json +++ b/.claude-plugin/marketplace.json @@ -9,7 +9,7 @@ "name": "engraphis-memory", "source": "./", "description": "Discipline for giving agents durable, scoped, explainable memory across sessions and repos with the Engraphis MCP tools.", - "version": "1.7.3" + "version": "1.7.4" } ] } diff --git a/.claude-plugin/plugin.json b/.claude-plugin/plugin.json index 11115ed7..45267f96 100644 --- a/.claude-plugin/plugin.json +++ b/.claude-plugin/plugin.json @@ -1,6 +1,6 @@ { "name": "engraphis-memory", - "version": "1.7.3", + "version": "1.7.4", "description": "Give agents durable, scoped, explainable memory across sessions and repos via the Engraphis MCP tools. Use when you learn something worth keeping, need prior context before acting, or ask why/how a fact changed. Covers remember/recall, why/timeline, forget/pin/correct, sessions, and code search.", "author": { "name": "The Engraphis Authors", diff --git a/.claude-plugin/skill-assets.sha256 b/.claude-plugin/skill-assets.sha256 index bb3cda87..566eda6b 100644 --- a/.claude-plugin/skill-assets.sha256 +++ b/.claude-plugin/skill-assets.sha256 @@ -1,5 +1,5 @@ -1731b35c796e5ac26d7e4c7c9b77b2640d6e7478006d2c67a155f66df70bb50a .claude-plugin/marketplace.json -4b2453788ff35f0c46eb8d0cd4c2491ca9352fc4bae96ee81a4c330f2709ac77 .claude-plugin/plugin.json +e2e08499a70d8d62ef22797cda0bb07d46cd1c6a79e5e18c1103b6c3c755b6d5 .claude-plugin/marketplace.json +36c560916ba42634cc50dc4f81b49955cc49b72152452eef67b49b6b2a2957d5 .claude-plugin/plugin.json 4bc8979b9ffeb97190960e551dbf4ddc6f7aeeb7b86894fd2298a59ff0001efa skills/engraphis-memory/SKILL.md 055655db84af07561d002f0c69744313d8413c39f3e873f941f0fa0b1e76dc66 skills/engraphis-memory/references/CONVENTIONS.md 62019760766ff472a76a0f81437898f39e3c1fe2631732b7b7733e50c1ad837f skills/engraphis-memory/references/SCOPING.md diff --git a/BENCHMARKS.md b/BENCHMARKS.md index efe7fe88..3548b1b0 100644 --- a/BENCHMARKS.md +++ b/BENCHMARKS.md @@ -9,14 +9,14 @@ For the locked operator sequence for a public canonical run, see ### Public numeric evidence registry Every exact public aggregate retained below comes from the checked-in, public-safe -[`offline-fixtures-v3.json`](docs/benchmark-evidence/offline-fixtures-v3.json) artifact. Its +[`offline-fixtures-v9.json`](docs/benchmark-evidence/offline-fixtures-v9.json) artifact. Its SHA-256 is -`2d6b4fab9e75edc91d105d49877f9225f28ffe4d366e40a44e931f19cb13f498`, also recorded in the +`455fc9d32a236e582a49aaaf9b84f30cae2573dc6ed982f4dd7dd845afcaf24c`, also recorded in the adjacent `.sha256` file. The artifact contains no raw questions, answers, prompts, customer data, or per-record content fingerprints. The fixture-suite digest is -`95c233e3fb79a1618bf40f0daefb36d3d1772b1f332d281d6f4c5d6cc902455b`. The artifact defines +`c8976cf0989e82f57810b99bf19f2ee3f860d07726bcb28479a319a19f00f94f`. The artifact defines the digest algorithm and records the SHA-256 of every suite and dataset file. Each evidence ID also binds its exact command through `sha256(UTF-8 exact command)`: diff --git a/CHANGELOG.md b/CHANGELOG.md index 2f415976..a2a2aed1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,8 @@ All notable changes to Engraphis are documented here. Format loosely follows ## [Unreleased] +## [1.7.4] - 2026-09-13 + - Writable SQLite files now default to WAL plus FULL synchronization, with an explicit balanced option and effective-policy diagnostics. Disposable fault tests cover abrupt process exit and database-full rollback; hardware power loss remains unverified. @@ -36,9 +38,8 @@ All notable changes to Engraphis are documented here. Format loosely follows - Added content-free diagnostics and build/capability information, strict coding acceptance validation and a file-backed independent-process capacity harness. These provide measurement infrastructure, not verified 100k capacity claims. -- Preload the optional `sentence-transformers` dependency before Windows stdio MCP - accepts JSON-RPC, avoiding the observed native import/thread startup stall while - preserving deterministic fallback and exact-backend policy. +- MCP stdio startup accepts the JSON-RPC handshake before optional semantic-model + warmup, while retaining deterministic fallback and exact-backend policy. ## [1.7.3] - 2026-09-07 diff --git a/README.md b/README.md index ab4dc3f3..d5640772 100644 --- a/README.md +++ b/README.md @@ -77,9 +77,9 @@ its counting boundary explicit. | Packed prompt-context usage in the same 26-question CodeMem sample pass | Hard budget: **1,500** tokens; observed mean: **85.38**; observed maximum: **108** | A hard cap prevents a recall from exceeding its configured context budget | This is usage accounting, not a before/after savings comparison | These values are evidence IDs `offline-chunking` and `offline-performance` in -[`offline-fixtures-v3.json`](https://github.com/Coding-Dev-Tools/engraphis/blob/main/docs/benchmark-evidence/offline-fixtures-v3.json), +[`offline-fixtures-v9.json`](https://github.com/Coding-Dev-Tools/engraphis/blob/main/docs/benchmark-evidence/offline-fixtures-v9.json), SHA-256 -`2d6b4fab9e75edc91d105d49877f9225f28ffe4d366e40a44e931f19cb13f498`. +`455fc9d32a236e582a49aaaf9b84f30cae2573dc6ed982f4dd7dd845afcaf24c`. [`BENCHMARKS.md`](https://github.com/Coding-Dev-Tools/engraphis/blob/main/BENCHMARKS.md#public-numeric-evidence-registry) records the matching suite digest, exact commands, and per-command config digests. External, model-dependent, consolidation, productivity, and latency results remain unpublished until the diff --git a/docs/REWORK_EXECUTION.md b/docs/REWORK_EXECUTION.md index 5240fecd..47e69fa4 100644 --- a/docs/REWORK_EXECUTION.md +++ b/docs/REWORK_EXECUTION.md @@ -161,7 +161,7 @@ scope/time regression coverage. Original user edits were not rewritten. | Capacity acceptance | Lifecycle RSS includes startup, backlog is sampled and recomputed, and the complete matrix validator enforces prebound hosts, WAL/FULL, all scheduled outcomes, RAM and the required 100k latency limits. | No primary 48-cell matrix was executed. The separate 16 GiB reference host remains necessary. | | Installed journeys | A packaged stdlib runner performs actual MCP/HTTP writes, restart recall, correction and historical reads. PR CI and release jobs cover Windows, macOS and Linux, with artifact/dependency identities retained. | Cached Windows source semantic startup passed in four fresh processes, taking 20-23 seconds. This is not semantic qualification of all installed platforms. | | Evidence and publication | Candidate ledger validation checks identities, hashes, dependencies, outcomes and selected evaluation booleans. All four publication/repair writes require [owner qualification](RELEASE_QUALIFICATION.md). | Owner-protected environment/authority setup, final approval and all missing mandatory evidence remain open. | -| Public claims | Fresh [offline fixture evidence](benchmark-evidence/offline-fixtures-v3.json) reproduces retained public aggregates and binds the current engine/eval source. Historical v1 evidence is preserved. | Planner variants still require successful promotion gates; no retrieval default or leadership claim is promoted. | +| Public claims | Fresh [offline fixture evidence](benchmark-evidence/offline-fixtures-v9.json) reproduces retained public aggregates and binds the current engine/eval source. Historical v1 evidence is preserved. | Planner variants still require successful promotion gates; no retrieval default or leadership claim is promoted. | | Website contract | Active commercial/MCP/install guidance is generated and checked against a selected shipped public contract in the website candidate. | The live portal, authenticated provider journeys and combined deployed identities require attended acceptance. | Final commits, distributions, dependency inventories, raw execution results and gate @@ -203,7 +203,7 @@ ignore until compatibility is demonstrated. Patched Pi Hono remains in place. Private Cloud/Team PR #74 is the integrated application delivery; the independent R2 backup addition remains PR #72. Website PR #15 incorporates the useful older -measurement, offer and artifact checks while retaining the shipped v1.7.3 contract. +measurement, offer and artifact checks while retaining the shipped v1.7.4 contract. Final source identities and new CI results must be recorded separately from the earlier release package. Consolidation and passing source checks do not complete the outstanding capacity, recovery, hosted, human-acceptance or pilot gates. diff --git a/docs/benchmark-evidence/offline-fixtures-v4.json b/docs/benchmark-evidence/offline-fixtures-v4.json new file mode 100644 index 00000000..c43d8e21 --- /dev/null +++ b/docs/benchmark-evidence/offline-fixtures-v4.json @@ -0,0 +1,257 @@ +{ + "environment": { + "embedding": "deterministic", + "numpy": "2.4.5", + "platform": "win32", + "python": "3.12.10", + "vector_backend": "numpy" + }, + "generated_on": "2026-09-13", + "privacy": { + "contains_answers": false, + "contains_customer_data": false, + "contains_per_record_fingerprints": false, + "contains_prompts": false, + "contains_raw_questions": false + }, + "runs": [ + { + "boundary": "Deterministic offline retrieval fixture; normalized-character token estimator; not external QA or provider billing.", + "command": "python -m eval.chunking_eval --dataset eval/datasets/longdoc.jsonl --k 5", + "config_digest": "c1c8196aa7e1568ef3844a9fb2d76b87f342c39108e32d6ad144b885a76143b8", + "config_digest_method": "sha256(UTF-8 exact command)", + "id": "offline-chunking", + "result": { + "chunked": { + "max_stored_tokens": 59, + "mean_context_tokens": 214.3, + "mean_evidence_tokens": 42.4, + "memories": 24, + "recall_at_k": 1.0 + }, + "context_reduction_pct": 71.1, + "documents": 6, + "k": 5, + "questions": 18, + "token_counter": "engraphis.chars4.v1", + "whole": { + "max_stored_tokens": 213, + "mean_context_tokens": 740.3, + "mean_evidence_tokens": 162.2, + "memories": 6, + "recall_at_k": 1.0 + } + } + }, + { + "boundary": "Deterministic offline CodeMem fixture; serialized JSON-shape payload proxies, not MCP transport responses, provider billing, or latency claims.", + "command": "python -m eval.performance --dataset eval/datasets/codemem.jsonl --k 5 --iterations 10 --json", + "config_digest": "bbe4aca81e58d4830e50a8fc7729a1d15b71d97a6299bccd79432b7f119677d7", + "config_digest_method": "sha256(UTF-8 exact command)", + "id": "offline-performance", + "result": { + "answer_token_recall": 1.0, + "compact_serialized_payload_tokens": 10982, + "dataset_cases": 14, + "full_serialized_payload_tokens": 23810, + "hit_at_k": 1.0, + "k": 5, + "max_context_tokens": 108, + "mean_context_tokens": 85.38, + "memories": 44, + "questions": 26, + "recall_at_k": 1.0, + "saved_serialized_payload_tokens": 12828, + "serialized_payload_savings_ratio": 0.5388, + "timed_recalls": 260, + "token_budget": 1500, + "token_counter": "engraphis.regex.v1" + } + }, + { + "boundary": "Deterministic offline support/abstention fixture; not a frontier-model answer-quality score.", + "command": "python -m eval.grounded", + "config_digest": "590442e51e3642c10489165759919dc86ffac62c182937330c153e7f8d5fc26f", + "config_digest_method": "sha256(UTF-8 exact command)", + "id": "offline-grounded", + "result": { + "abstained": 6, + "answerable": 5, + "decision_accuracy": 1.0, + "grounded": 5, + "off_topic": 6, + "quarantine_hits": 1, + "quarantined": 1 + } + } + ], + "schema": "engraphis-public-offline-fixtures/v1", + "suite": { + "digest": "06bfa81307dac71ef82ac4c30c782426498ab8ff4699a990d22720d30fc2e563", + "digest_method": "sha256(canonical compact JSON mapping each sorted path to its file SHA-256)", + "files": { + "engraphis/__init__.py": "7efb24616f3a1c5181bf83bb4b60dd97122372b2f5c15db9a89f685ea39cbcbb", + "engraphis/ai_context.py": "4dfd5d39eb95d05c591d1981e9e855eced73232f53efd9fe9966e0e08957d030", + "engraphis/app.py": "44d68ad8c0ff46baed01978c9b04e40b8be5031609d5a69e205b7f05da3777fb", + "engraphis/backends/__init__.py": "a9f22b9278362904166614081f1df78469d453601b298ce4e8afdba8a3722b25", + "engraphis/backends/codegraph.py": "83e723a91068d23694092fbe00157fcb2597061d453eb36f955bf55bc5b4d35e", + "engraphis/backends/embedder_api.py": "56a6bceea4f757325dcea987b0339e41d3875634b1ae5103f0537a358cf5878b", + "engraphis/backends/embedder_deterministic.py": "ec8b23de7e7e8273416125f5876ca96f55e4ae7881841bae55783ab0ba9130ad", + "engraphis/backends/embedder_st.py": "e1c20fd980e07060387e3f9fa37fe02a916959fc8abce4e6067a62699c726de1", + "engraphis/backends/encrypted_db.py": "25f6c1480d296a88f317213700a8b3c81e2732399bfac464b0d893465b25e846", + "engraphis/backends/extractor.py": "f2e3455ab7f14caee1d5b5c4ef071e498e90118f1b0ddcb8510c969583b0fc57", + "engraphis/backends/graph_extractor.py": "88561efa0d3fabc447a0a005b10e36261379d46218cf62d905e6928cd2fda676", + "engraphis/backends/model_source.py": "8c3c7681f95214a2bbabd8de222e5ee11f42fe13402d27365654ae75fb363d4e", + "engraphis/backends/postgres_schema.py": "8468578c3add701d30d5eaa36d768ded2375d116e55f1836e09f6107a07a267e", + "engraphis/backends/query_planner.py": "bbdd77afc9b5523421b85b2ae63c8da7f5a7b777265450e0d21708a83e7bb23c", + "engraphis/backends/reranker.py": "747761d6cbfa421388974bcfd98d844f92391d80f4bf6a4feca00b0c7a6908ca", + "engraphis/backends/resources.py": "47cc867c3aecc8bd95fa284bc5bb04715f3339c19a0a11512973ef6171c95944", + "engraphis/backends/retention.py": "381d9371e3951d762f8b55eb54711de5697642acb39de99a714f246c059ecbd0", + "engraphis/backends/sync_folder.py": "e4f70a92a17f6a365910670df041e6e3ca421d44ada2827917cd66b4dc067bfa", + "engraphis/backends/sync_relay.py": "b8b9ad265453aba17ba7c27a355e12a793469b3e44cb217943c6fad9382a3006", + "engraphis/backends/vector_numpy.py": "c598831bea547824cfe08844816fa79857d3617cb0631238f95dad955a424f72", + "engraphis/backends/vector_sqlitevec.py": "6148e14ceaacc19239b64c642a3fba0e98797c78cec356210157afadf475a08b", + "engraphis/build_info.py": "624c22471e56d4c4047160808c4245488292af611564d1a63ca437605bbb414f", + "engraphis/classic_assets/__init__.py": "a7c1d52b285e3faa670ce231814b5758754aa0fbd05e1428e74c20c3ec51a4f1", + "engraphis/cloud_authz.py": "e80500579cb3a1d5fbf30814dc94e3e3967e50b311e8ed2fa56afcc13f7eb565", + "engraphis/cloud_features.py": "a1bec76216d4f1276a3313dabc1d29a1666378e11863d05d1a02e695cf6d7293", + "engraphis/cloud_session.py": "7c83d7b85665c05aa4da2597a6b4ad2b951f1f8f4af20105d9d1750b9b123c2d", + "engraphis/commercial.py": "184f312066a9e682e51a0abeff042f1c0e8eed2d47470157b23930b5a17633aa", + "engraphis/config.py": "a46f3a335fad343e7df32942be91c04094fbafaf14b8b11f5fc433ef74743226", + "engraphis/core/__init__.py": "dd5143729c3939237f04636f437032b1f2d3a5f7d82c91bbc2a5a283c3f0ebaa", + "engraphis/core/adaptive_context.py": "cc5ce48109bb0d5230a5b2b8424b829c853feec5b5d5b82596413f2279b0c9f9", + "engraphis/core/browsing.py": "cfae752d52ef51b17c4ffbe44dde62d5b0e1ed0ca34ec0e1788f3991d94bf05f", + "engraphis/core/codegraph_export.py": "4641074258d7b23498f92dd45053a0fbb111863eaad2001c08e5e3c2dc2fd54f", + "engraphis/core/conflicts.py": "28530be25a4af0bffd8f609b965b33ca7f93199a70887789b2148fda8a61a486", + "engraphis/core/consolidate.py": "4bd366da5fded1d38bc2ce6fccb1ec478e45cbdca00a712f40057cf0a3222aa3", + "engraphis/core/context.py": "9fb55c9b2fbbb1b85c16418cd2f7fe5fffe35c28cd6d1baf4f3a2ae709804f33", + "engraphis/core/diagnostics.py": "7d563cbbb204ed2fdaa880c4912acd47df946f91652eb2d1a9444c420b724889", + "engraphis/core/documents.py": "84385db39ba44e06b58b4b26dbf954228ff4abed7230f28a7280166fa6457861", + "engraphis/core/engine.py": "8d88554237ff9768b4268ed052a1268451bbeeb4b6c2600b6bd6fddd3dac478e", + "engraphis/core/fsutil.py": "6db770fa8bd3e1a57dfa70eb8e8bc46d48c2dc53ead1b0b43eeecf085ef58cfc", + "engraphis/core/graph_layers.py": "64d74ab01c77119f6343ba6f1d6a84f9653f1a5d34d47ce7966f3ac31b29d2ea", + "engraphis/core/graph_policy.py": "ec5b373d01adb2de87df31d9f543130018e9a73faaaed239a184f14a32646615", + "engraphis/core/graph_scene.py": "cab0aef9ce464620d1ee9ff88fab13fd89707c831212e1d8f1ae2c603c8b6010", + "engraphis/core/graphrank.py": "1279a58396104d3f906bfd5ec75b32efedfefe52201467bf19d80be3517017a5", + "engraphis/core/grounded.py": "ac40057dc37aa907e09c68e6b8cd54a989525fb310097df2970858708870ba3e", + "engraphis/core/ids.py": "80c2c0a0635af86ada33b46e5743f28001ff1004b727bbb790aa2393c234d86b", + "engraphis/core/interfaces.py": "93544dcb75d8373c594babc439baf2641ac46b195c89aacfcd4d252cdd3f5e1f", + "engraphis/core/mutations.py": "dbb46a97686994e1652b2698e50c3309ff428d7258d6e8e53cbad7bb55b459aa", + "engraphis/core/obsidian.py": "991267c153cb7c4c40f7fe8f50aa71688892e250aaaf383b22c9e5910dc263b7", + "engraphis/core/poisoning.py": "5bc67169ee8032f3777f2d3969dcf71821437bd473ce4f917c4b41a50e845fb6", + "engraphis/core/query_planner.py": "249062d67392ab7c203cc71e9040e99bee91bf570604e90949149a93cb652120", + "engraphis/core/read_snapshots.py": "be08e63a88bd38ed91d61b28657a65201c38994856db2798b209a73151dd202a", + "engraphis/core/recall.py": "529f6518783b9a5e6ea35660d55f472467458a7f1f031b8dd37011142384a5a9", + "engraphis/core/resolve.py": "f01a6f55e44320ab04b97e516342f20155668863b2fc4765305e066d87586524", + "engraphis/core/retention_policy.py": "864c03bdb6e743cd0002c706de471e920f1fa1f1a9918ab343ef4c2042b47429", + "engraphis/core/retrieval_policy.py": "7e970ac57762a1e55091bac46314c3d60aba0bf2cbb11405ce0f7e032448866e", + "engraphis/core/savings.py": "cfbcfc7e476f4e28028555cd519696e23099f6210cf0b733225832aeaa0bc7dc", + "engraphis/core/schema.py": "ac273d3f0383995be815bbd866f2a36ea1398f30833aed57b8d4459afc87096b", + "engraphis/core/scoring.py": "f5b6ac291edf0968b3de83cb1951a97d5bfd8a8d079199cb2ef95bba0884c89a", + "engraphis/core/secrets.py": "a4835ba06e2616156528df6365ca1aba6cba0c97cdf834a709d2797a371099d2", + "engraphis/core/store.py": "ff4522a9861fabbaba762161e18fa20a5e39196ac850f7db06617cb8a4efdd1c", + "engraphis/core/sync.py": "69f75b50fdb1ec9352f92460c89efeec8d72ca642bd10beb29474a8c62b4f58a", + "engraphis/core/textutil.py": "acd65031729fa5d91d09527b8eb52518b83cfce77a55e6b7ae2d94686e35c1a6", + "engraphis/core/user_model.py": "3147ec8ee7cfd855783f639874b63f331cdc822bd8bd9298cfb326dd18666026", + "engraphis/core/vector_repair.py": "a8c1812de4e3ed288eda3e54a505e136d6ebd3ec296788bcbb8804b11e13cfc8", + "engraphis/core/vector_search.py": "75800052e573e9af01c6fd098eaf8647c3c45cd7eb2601dae05d42359e19b234", + "engraphis/dashboard_app.py": "9305c9c72c43027b2b79c0ce559d398fc232929968d6ea03c37065e3227c8d51", + "engraphis/dashboard_assets/__init__.py": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "engraphis/device_connect.py": "c8cd0a22e9fd2d92a65bd74047cc3a8b7159bfc9a297cb639c1c7f1699f8802e", + "engraphis/document_import.py": "94fa0ca340ad0ebd060b143f46657798a81c440a11b82aa46fefa83fb65295dc", + "engraphis/engines/__init__.py": "111232af583889195c5f5a60298e32484348608e81d2bdd822fd3ecd2a33c1e4", + "engraphis/engines/embedder.py": "998b65dd566966bb6581fd9f09cdf46c58a3923ef5df3073ccdaa541153a3581", + "engraphis/engines/ingest.py": "1a5d4b52c13e533864329f9fff11c0f6ebc299ff7093a9d9275e5c9626a39ce2", + "engraphis/engines/intelligence.py": "b561589b98deb98271f104dfec6276aeba13c4815e627259be5f8769f2e7ad82", + "engraphis/engines/recall.py": "f979580d065599c07acbc3add59f71e52d9a186a2104b0e257daa7959ea88d26", + "engraphis/engines/reweight.py": "91ec5815f5d356a7068c36133d24405334450f361f902f99275bed3ccebffd49", + "engraphis/engines/thoughts.py": "4adb9c8a9bcfe736cb42fff9b5ce24631da6ec473d178e83f1c176fde3b8b814", + "engraphis/factory.py": "3b8765834cb04b052b89a9964b357b4ffb9c41a0f769bf1261768033653f708d", + "engraphis/graphdata.py": "195e583a4d4aefe97d8cff635cabea1ff9cd3f11c54ad392d951765d89910863", + "engraphis/hosted_client.py": "9c67aff6881c29704498f4ca99f836009be4ea58a248d74459c536dac7341a88", + "engraphis/http_security.py": "596981e96741fd47064d03db409605bbb435f062c0c6ef69b040aacdd8763a20", + "engraphis/inspector/__init__.py": "720cac28b8a6019d0a0c53809d5905b7d6eb9d4ecbac767505904c6ec3c39071", + "engraphis/inspector/app.py": "8a1b540de82ab3d1a6381630bc48056ba62e708118ba738092831c729959ffb4", + "engraphis/licensing.py": "7e73c28b0e1c3536e2080a129af614f838d2cae3ec3a48a3d8ed7e5153c9e935", + "engraphis/llm/__init__.py": "f3096d2ddd652b99e6fc0b4c5a8786d9bbaba41b259df0b44ce93b57bde3a8b1", + "engraphis/llm/client.py": "304330bf7a45b0eef8f5beabee419b971d205c55f686de86c26d91fea69d172e", + "engraphis/local_auth.py": "b0ad3a1926d417a2aaa6c44a7dbf6e51f575290ddfa27875b78a03db176623c3", + "engraphis/logging_setup.py": "f7d2edc756458a852e0401453e9c71b785aba08fa7859aacbdc23fb30dc7982a", + "engraphis/managed_processing.py": "6d33cdfd10800d9552fcfae3c2b071d2b39fe10fb69d1a8e5d9ed6026882197e", + "engraphis/mcp_classic_cli.py": "fd75e83300e08fe6eb655edfc4cd1a296bd7fa060c6c62d73f4ea3e15e9c7b65", + "engraphis/mcp_cli.py": "ed2d997438d727180842dc5fb3f6776f5a5d97974f690ee7229264be1ff61957", + "engraphis/mcp_http_cli.py": "f6ac8bb04a0cb179e840502fdd543b8f55d0f1bf0045fc7900e06ae002cf422d", + "engraphis/mcp_server.py": "2a27eebe23055b7e01bd320342f528e0655b29266bb495edac98850e86a6b204", + "engraphis/models.py": "6e76e97db0aca3805c6f582ea78cc6e1c0ccd2665e16fd8ab81eb91b94141b51", + "engraphis/netutil.py": "2e0f8a9095f6f31dcb5b96d323f023b9214369d59e1c488125a7d443a55972ff", + "engraphis/observability.py": "a3a6945bf33a0d8e216da56ca7efec0031b82dc64a66cff36f0b2161f5db4981", + "engraphis/obsidian_import.py": "f5afc4a2deddf0eab92d9d9eb81540de89738df3223ddcb22c04b583be0de2a1", + "engraphis/private_state.py": "7485570efcaee8a1dc00b64ebfdc23178517235ae17609aa78db8bdda7e45fe3", + "engraphis/read_only_api.py": "478c7efa4e462e349d758143d3d44d18b9152656067c0171904bfe675a2dedbe", + "engraphis/redirector.py": "5ba964b81f09008c9369180cb49d247519000763274aabc5e046215b12fa641d", + "engraphis/routes/__init__.py": "f0d59080212cfa0d9b50877bca28e5832d1ae917899500d52c68b1c8821231af", + "engraphis/routes/memory.py": "9ca066e1762eeeaafd9790ed57d730efcaceb57742dbe0c830ad8764500ff9e5", + "engraphis/routes/v2_api.py": "9ff441c08f3f6f082646735026c03f3a4b59655f25a0a651c11131d04f7b0404", + "engraphis/routes/vault.py": "1a7eee7c1a7c7aa11091042756aa2739a3eb963647020f40584a6a38da1988af", + "engraphis/service.py": "347291d289b9f9919ca0a6c65a6318e35d41eca8df48bfb9f5e5424c1669ce5e", + "engraphis/service_context.py": "3de9289f49a977cdc206285ac42a9953a104eb1d1b1bc8ea77febd75c7cd82ab", + "engraphis/static/__init__.py": "1fff4c4e2554e7f5fcf3eace269feba09827524917193a4dd65df95bae64ad1f", + "engraphis/stores/__init__.py": "48ee4326c8f28eecf46f558b7aea21adb779226a7038299017ab90196d5d84be", + "engraphis/stores/graph.py": "ebf603b54cf8450e7c9a7319bd05db2f39fcda8491f5969d6af3e8da61571bc2", + "engraphis/stores/ledger.py": "df5cbb30d977decc0a9c3a2365c9c115cfbb5fe951bae48446436661c80e5d30", + "engraphis/stores/vaults.py": "2c986129b9d1e7aab33e18a3b9a278eb5ad2236895587f69b5816a5d96796bc3", + "engraphis/stores/vectors.py": "45a1baca381fc647548cc89424eb36d5853f7562c275b191b35b99339a190b7d", + "engraphis/update_check.py": "ffbf5ef682fb15177915073ebc0b5eab4dee9092bbf0f58d36a8a54c6605ccf4", + "eval/__init__.py": "639f0c6d9d6aac8ff6dc605a34a0a301058905cc53bff4eaed5912247f0e7c56", + "eval/ablation.py": "16f159dee75d2f96cc42f230c2403fa19ea0bda7091c4823660da553463a194a", + "eval/adversarial_memory_security.py": "35dd8d981bcbad50e9815465be420b05b62a9dea28a78eb6cc1e09ec51c320c4", + "eval/agent_benchmarks.py": "91c157b1d3d445fe0daa236edf21decb7e3713ad9bbaacbf0a46c0d8a5d1f2ee", + "eval/benchmark.py": "ed828e3548e8fb05ffafe9479791e545e56504421ff88676e4bf4466d6beaf91", + "eval/capacity_matrix.py": "38c269c3eac8196ba90eea9b602b836f99b4e353732eb86cf76c58256c526622", + "eval/chunking_eval.py": "a16544353940c0a8c40cea3b9932d3399b35ea5994b809b78f5dbe4a952c467f", + "eval/code_agent_ab.py": "d98bba6b77700ff6bf86ff0d2cf518a67e5a2676ef51bbddabbb2ff26e1f3aaa", + "eval/code_arm.py": "d211166fce1b8a4173848e1617873b7e84aadeff43746effe7483c54bbdb6f1d", + "eval/coding_acceptance.py": "4b39cbcb60d7fba503cca597399cf9d04ad9567a43cdb950015ccf552e6a2773", + "eval/consolidation_ranking.py": "917b578d4e0bcb929bf1a1a37611acf7716a520c076abf4ade0d8d12a1c455de", + "eval/context_economy.py": "709ac7cc866855f96d7717ab2bea12e8b0d3a140d15fb978a2a929ad085931f2", + "eval/context_efficiency_guardrails.py": "22afd1a6fe17219e74701dc587ec35f569a5bf22bea270944525f51746723f14", + "eval/datasets/codemem.jsonl": "341313023c22850a2e14f02742b571ad1deca824f886a1654a59541304c01f3c", + "eval/datasets/longdoc.jsonl": "7f5ade95e1f283d0db8cf78e53ed8995d3534f847e616d2c0005fd8da37ac790", + "eval/engine_capacity.py": "3030485afafd4735283195ec8188ac815a2e8eeefa76b255aacd3a01925e3f2d", + "eval/external.py": "d93cc071e555c31f4c5521ab0b2aeb370df24656e5ee7b60904113d97b1416ae", + "eval/extractor_quality.py": "50820fe7f821d111e17e4e77a3d1159e7d6979d110b052c4f254a5b309c2652a", + "eval/fts_insert_scaling.py": "a8ecfbe19695f6d4659c3edf389b007c965b214b64fdd58d5ee86635fa766144", + "eval/graph_every_bench.py": "79da573c5edf315f71bfab412d3ea283b8da45d1fdabc78ddd19302ead09e4f0", + "eval/graph_traversal.py": "b094f75c3a1d75ba3cf19e372187d692d3c595a1d9bde19bbe95ae0c79a5175f", + "eval/grounded.py": "053d5193b716a2c3e507fcd44057d392de910a4442b46bd7cc1f30ac0ba68541", + "eval/handoff_quality.py": "7daf635510764e236f48ca7e2537a85d8ebc1ad995513144329c1f0236405937", + "eval/harness.py": "d9c5f960e891a3d0912e519eec554a970c973b3b8893df861f0258aa16342310", + "eval/hosted_evidence.py": "7946cd8c1e3aa291268271b2aa11210d5f09c9b05ba635aa0b64bef07bdcee45", + "eval/hosted_ledger.py": "a53036d12ff671371c148910a816fb20c7e7f3346250a303722352f47b06c476", + "eval/hosted_luna.py": "4dbf02a65eec38bcde92d82952a0b372abbac1f68378d11a04528f4a31a835dc", + "eval/longmemeval_v2.py": "defb4d47f453aa4615a8f101b82df3fadf64f0f9eae0ce1021d86d3750dad437", + "eval/longmemeval_v2_evidence.py": "8562d32590e4267e033cb1da2a7fda626bdc2630ebbf8547df282896f34abf8b", + "eval/longmemeval_v2_matrix.py": "ca085cd59481813cce5dbdfbc94f40f67173ac3a1bc3dce6f6d3e09eb7b08153", + "eval/metrics.py": "16857e2cf6ed339cb57a26c9bfa1879444b4d279bd972e5a9fa644ed1308afe0", + "eval/native_coverage_scaling.py": "0c7c3f5c80570c7ab02310f14927eb82399d1a624d65df895e937ed87339fe9c", + "eval/performance.py": "6b63a87f9fa8104bb9a3e7242fef0bceb8510da73fd5b0523f025b9654b4c63f", + "eval/performance_engine.py": "3d37cf0a5989c8fa6e8b6ab7ae0b2e0d5410a8b922d2f3130c1a7794d93dcbb1", + "eval/planned_recall.py": "f9a87291ecb181045b98ca65fe55db820bf7cee4ae4f4d087ca3458afdd7837e", + "eval/proactive_ranking.py": "8610541f1d547f9c0eb46d078dbcaa670c0a97157acc37f96ec08b482cb7a6ab", + "eval/productivity.py": "6d4644ebdc44472aeb3879963774fab276bfa269b781139c46ded48774a22717", + "eval/public_readiness.py": "5ce8a18d0bfe09e75e88548a589b8fc6d2cbf04c0f8cd1ce51cd9519136a2751", + "eval/redteam_poisoning.py": "fce120cc3adf2ee966b59cd3ea7f20d242a0af49b52492143543130fe14c0cc8", + "eval/reinforcement.py": "72ed766775a2658eaa728afec51c0ac22d97a90e813111954df66a6ec50f2bef", + "eval/repair_discovery.py": "db05496fbbcb0df86c5cdc2f0c85fb6b6605b0cace6cb44ae2add10b72784b5f", + "eval/resolver_reworded_corrections.py": "a9054778a37b2175b46f04b674b4779e358931eee5d2ae52bbc5f953d234fb9e", + "eval/resource_hierarchy.py": "5ab6c989bb143c4386749c45a33c190447e829c1b5657e8c0aca30f34bd69461", + "eval/rework_statistics.py": "e12c14288797c5cf2dd93d51f606244287bc2f4ff8bd401f1d1b072efd1f9529", + "eval/run_longmemeval_v2.py": "2e003d8ecf4f44ac5a3f80bd3ba8fe18bc74e769298fefe63fde8bb2a98f3a04", + "eval/task_pairs.py": "fddc54804e8837ec0731813297fb55825458317f898e29176e16f3f5a2f527fd", + "eval/vector_scale.py": "3f9c327d9eca1a857512ddc208e972933be1a7d4fa7fa0017aca0cbf8fe7bb6d", + "eval/vector_scale_storage.py": "bda0c1139596eb9232cd75c826fc941101b6116bae32ad7895525d43f9d35484", + "eval/vector_scan_plan.py": "92de2f3b41aa457dcfee11998936ce35e023fe61596ed98f3836c998a6e9a1cd", + "scripts/export_offline_evidence.py": "6e32efbf4448cb4bdbdf7ac6d52293f5996e2acb78ae89dd9a1bd92c00fcf2ee" + } + } +} diff --git a/docs/benchmark-evidence/offline-fixtures-v4.json.sha256 b/docs/benchmark-evidence/offline-fixtures-v4.json.sha256 new file mode 100644 index 00000000..7c111ef7 --- /dev/null +++ b/docs/benchmark-evidence/offline-fixtures-v4.json.sha256 @@ -0,0 +1 @@ +530c2620297de6fadd5e8256fe33c7fb15f6d53e3d1353569e56ddb77532e3cf offline-fixtures-v4.json diff --git a/docs/benchmark-evidence/offline-fixtures-v8.json b/docs/benchmark-evidence/offline-fixtures-v8.json new file mode 100644 index 00000000..5a60fb7d --- /dev/null +++ b/docs/benchmark-evidence/offline-fixtures-v8.json @@ -0,0 +1,257 @@ +{ + "environment": { + "embedding": "deterministic", + "numpy": "2.4.5", + "platform": "win32", + "python": "3.12.10", + "vector_backend": "numpy" + }, + "generated_on": "2026-09-13", + "privacy": { + "contains_answers": false, + "contains_customer_data": false, + "contains_per_record_fingerprints": false, + "contains_prompts": false, + "contains_raw_questions": false + }, + "runs": [ + { + "boundary": "Deterministic offline retrieval fixture; normalized-character token estimator; not external QA or provider billing.", + "command": "python -m eval.chunking_eval --dataset eval/datasets/longdoc.jsonl --k 5", + "config_digest": "c1c8196aa7e1568ef3844a9fb2d76b87f342c39108e32d6ad144b885a76143b8", + "config_digest_method": "sha256(UTF-8 exact command)", + "id": "offline-chunking", + "result": { + "chunked": { + "max_stored_tokens": 59, + "mean_context_tokens": 214.3, + "mean_evidence_tokens": 42.4, + "memories": 24, + "recall_at_k": 1.0 + }, + "context_reduction_pct": 71.1, + "documents": 6, + "k": 5, + "questions": 18, + "token_counter": "engraphis.chars4.v1", + "whole": { + "max_stored_tokens": 213, + "mean_context_tokens": 740.3, + "mean_evidence_tokens": 162.2, + "memories": 6, + "recall_at_k": 1.0 + } + } + }, + { + "boundary": "Deterministic offline CodeMem fixture; serialized JSON-shape payload proxies, not MCP transport responses, provider billing, or latency claims.", + "command": "python -m eval.performance --dataset eval/datasets/codemem.jsonl --k 5 --iterations 10 --json", + "config_digest": "bbe4aca81e58d4830e50a8fc7729a1d15b71d97a6299bccd79432b7f119677d7", + "config_digest_method": "sha256(UTF-8 exact command)", + "id": "offline-performance", + "result": { + "answer_token_recall": 1.0, + "compact_serialized_payload_tokens": 10982, + "dataset_cases": 14, + "full_serialized_payload_tokens": 23810, + "hit_at_k": 1.0, + "k": 5, + "max_context_tokens": 108, + "mean_context_tokens": 85.38, + "memories": 44, + "questions": 26, + "recall_at_k": 1.0, + "saved_serialized_payload_tokens": 12828, + "serialized_payload_savings_ratio": 0.5388, + "timed_recalls": 260, + "token_budget": 1500, + "token_counter": "engraphis.regex.v1" + } + }, + { + "boundary": "Deterministic offline support/abstention fixture; not a frontier-model answer-quality score.", + "command": "python -m eval.grounded", + "config_digest": "590442e51e3642c10489165759919dc86ffac62c182937330c153e7f8d5fc26f", + "config_digest_method": "sha256(UTF-8 exact command)", + "id": "offline-grounded", + "result": { + "abstained": 6, + "answerable": 5, + "decision_accuracy": 1.0, + "grounded": 5, + "off_topic": 6, + "quarantine_hits": 1, + "quarantined": 1 + } + } + ], + "schema": "engraphis-public-offline-fixtures/v1", + "suite": { + "digest": "34312952681809212ada5fd5f1fa608ff8723491d770c8482fd1b0a9e8e87942", + "digest_method": "sha256(canonical compact JSON mapping each sorted path to its file SHA-256)", + "files": { + "engraphis/__init__.py": "7efb24616f3a1c5181bf83bb4b60dd97122372b2f5c15db9a89f685ea39cbcbb", + "engraphis/ai_context.py": "4dfd5d39eb95d05c591d1981e9e855eced73232f53efd9fe9966e0e08957d030", + "engraphis/app.py": "44d68ad8c0ff46baed01978c9b04e40b8be5031609d5a69e205b7f05da3777fb", + "engraphis/backends/__init__.py": "a9f22b9278362904166614081f1df78469d453601b298ce4e8afdba8a3722b25", + "engraphis/backends/codegraph.py": "83e723a91068d23694092fbe00157fcb2597061d453eb36f955bf55bc5b4d35e", + "engraphis/backends/embedder_api.py": "56a6bceea4f757325dcea987b0339e41d3875634b1ae5103f0537a358cf5878b", + "engraphis/backends/embedder_deterministic.py": "ec8b23de7e7e8273416125f5876ca96f55e4ae7881841bae55783ab0ba9130ad", + "engraphis/backends/embedder_st.py": "e1c20fd980e07060387e3f9fa37fe02a916959fc8abce4e6067a62699c726de1", + "engraphis/backends/encrypted_db.py": "25f6c1480d296a88f317213700a8b3c81e2732399bfac464b0d893465b25e846", + "engraphis/backends/extractor.py": "f2e3455ab7f14caee1d5b5c4ef071e498e90118f1b0ddcb8510c969583b0fc57", + "engraphis/backends/graph_extractor.py": "88561efa0d3fabc447a0a005b10e36261379d46218cf62d905e6928cd2fda676", + "engraphis/backends/model_source.py": "8c3c7681f95214a2bbabd8de222e5ee11f42fe13402d27365654ae75fb363d4e", + "engraphis/backends/postgres_schema.py": "8468578c3add701d30d5eaa36d768ded2375d116e55f1836e09f6107a07a267e", + "engraphis/backends/query_planner.py": "bbdd77afc9b5523421b85b2ae63c8da7f5a7b777265450e0d21708a83e7bb23c", + "engraphis/backends/reranker.py": "747761d6cbfa421388974bcfd98d844f92391d80f4bf6a4feca00b0c7a6908ca", + "engraphis/backends/resources.py": "47cc867c3aecc8bd95fa284bc5bb04715f3339c19a0a11512973ef6171c95944", + "engraphis/backends/retention.py": "381d9371e3951d762f8b55eb54711de5697642acb39de99a714f246c059ecbd0", + "engraphis/backends/sync_folder.py": "e4f70a92a17f6a365910670df041e6e3ca421d44ada2827917cd66b4dc067bfa", + "engraphis/backends/sync_relay.py": "b8b9ad265453aba17ba7c27a355e12a793469b3e44cb217943c6fad9382a3006", + "engraphis/backends/vector_numpy.py": "c598831bea547824cfe08844816fa79857d3617cb0631238f95dad955a424f72", + "engraphis/backends/vector_sqlitevec.py": "6148e14ceaacc19239b64c642a3fba0e98797c78cec356210157afadf475a08b", + "engraphis/build_info.py": "624c22471e56d4c4047160808c4245488292af611564d1a63ca437605bbb414f", + "engraphis/classic_assets/__init__.py": "a7c1d52b285e3faa670ce231814b5758754aa0fbd05e1428e74c20c3ec51a4f1", + "engraphis/cloud_authz.py": "e80500579cb3a1d5fbf30814dc94e3e3967e50b311e8ed2fa56afcc13f7eb565", + "engraphis/cloud_features.py": "a1bec76216d4f1276a3313dabc1d29a1666378e11863d05d1a02e695cf6d7293", + "engraphis/cloud_session.py": "7c83d7b85665c05aa4da2597a6b4ad2b951f1f8f4af20105d9d1750b9b123c2d", + "engraphis/commercial.py": "184f312066a9e682e51a0abeff042f1c0e8eed2d47470157b23930b5a17633aa", + "engraphis/config.py": "a46f3a335fad343e7df32942be91c04094fbafaf14b8b11f5fc433ef74743226", + "engraphis/core/__init__.py": "dd5143729c3939237f04636f437032b1f2d3a5f7d82c91bbc2a5a283c3f0ebaa", + "engraphis/core/adaptive_context.py": "cc5ce48109bb0d5230a5b2b8424b829c853feec5b5d5b82596413f2279b0c9f9", + "engraphis/core/browsing.py": "cfae752d52ef51b17c4ffbe44dde62d5b0e1ed0ca34ec0e1788f3991d94bf05f", + "engraphis/core/codegraph_export.py": "4641074258d7b23498f92dd45053a0fbb111863eaad2001c08e5e3c2dc2fd54f", + "engraphis/core/conflicts.py": "28530be25a4af0bffd8f609b965b33ca7f93199a70887789b2148fda8a61a486", + "engraphis/core/consolidate.py": "f66eedfe08319a64b761261ccf1c99b163eba564d6d4060534bf8c575aecf232", + "engraphis/core/context.py": "9fb55c9b2fbbb1b85c16418cd2f7fe5fffe35c28cd6d1baf4f3a2ae709804f33", + "engraphis/core/diagnostics.py": "7d563cbbb204ed2fdaa880c4912acd47df946f91652eb2d1a9444c420b724889", + "engraphis/core/documents.py": "84385db39ba44e06b58b4b26dbf954228ff4abed7230f28a7280166fa6457861", + "engraphis/core/engine.py": "8d88554237ff9768b4268ed052a1268451bbeeb4b6c2600b6bd6fddd3dac478e", + "engraphis/core/fsutil.py": "6db770fa8bd3e1a57dfa70eb8e8bc46d48c2dc53ead1b0b43eeecf085ef58cfc", + "engraphis/core/graph_layers.py": "64d74ab01c77119f6343ba6f1d6a84f9653f1a5d34d47ce7966f3ac31b29d2ea", + "engraphis/core/graph_policy.py": "ec5b373d01adb2de87df31d9f543130018e9a73faaaed239a184f14a32646615", + "engraphis/core/graph_scene.py": "cab0aef9ce464620d1ee9ff88fab13fd89707c831212e1d8f1ae2c603c8b6010", + "engraphis/core/graphrank.py": "1279a58396104d3f906bfd5ec75b32efedfefe52201467bf19d80be3517017a5", + "engraphis/core/grounded.py": "ac40057dc37aa907e09c68e6b8cd54a989525fb310097df2970858708870ba3e", + "engraphis/core/ids.py": "19ba2e715056f7afcc4d4ab05cee3659bd1600a090b21d8a71ecb2a11711e348", + "engraphis/core/interfaces.py": "93544dcb75d8373c594babc439baf2641ac46b195c89aacfcd4d252cdd3f5e1f", + "engraphis/core/mutations.py": "dbb46a97686994e1652b2698e50c3309ff428d7258d6e8e53cbad7bb55b459aa", + "engraphis/core/obsidian.py": "991267c153cb7c4c40f7fe8f50aa71688892e250aaaf383b22c9e5910dc263b7", + "engraphis/core/poisoning.py": "5bc67169ee8032f3777f2d3969dcf71821437bd473ce4f917c4b41a50e845fb6", + "engraphis/core/query_planner.py": "249062d67392ab7c203cc71e9040e99bee91bf570604e90949149a93cb652120", + "engraphis/core/read_snapshots.py": "be08e63a88bd38ed91d61b28657a65201c38994856db2798b209a73151dd202a", + "engraphis/core/recall.py": "529f6518783b9a5e6ea35660d55f472467458a7f1f031b8dd37011142384a5a9", + "engraphis/core/resolve.py": "f01a6f55e44320ab04b97e516342f20155668863b2fc4765305e066d87586524", + "engraphis/core/retention_policy.py": "864c03bdb6e743cd0002c706de471e920f1fa1f1a9918ab343ef4c2042b47429", + "engraphis/core/retrieval_policy.py": "7e970ac57762a1e55091bac46314c3d60aba0bf2cbb11405ce0f7e032448866e", + "engraphis/core/savings.py": "cfbcfc7e476f4e28028555cd519696e23099f6210cf0b733225832aeaa0bc7dc", + "engraphis/core/schema.py": "ac273d3f0383995be815bbd866f2a36ea1398f30833aed57b8d4459afc87096b", + "engraphis/core/scoring.py": "f5b6ac291edf0968b3de83cb1951a97d5bfd8a8d079199cb2ef95bba0884c89a", + "engraphis/core/secrets.py": "a4835ba06e2616156528df6365ca1aba6cba0c97cdf834a709d2797a371099d2", + "engraphis/core/store.py": "ff4522a9861fabbaba762161e18fa20a5e39196ac850f7db06617cb8a4efdd1c", + "engraphis/core/sync.py": "69f75b50fdb1ec9352f92460c89efeec8d72ca642bd10beb29474a8c62b4f58a", + "engraphis/core/textutil.py": "acd65031729fa5d91d09527b8eb52518b83cfce77a55e6b7ae2d94686e35c1a6", + "engraphis/core/user_model.py": "3147ec8ee7cfd855783f639874b63f331cdc822bd8bd9298cfb326dd18666026", + "engraphis/core/vector_repair.py": "a8c1812de4e3ed288eda3e54a505e136d6ebd3ec296788bcbb8804b11e13cfc8", + "engraphis/core/vector_search.py": "75800052e573e9af01c6fd098eaf8647c3c45cd7eb2601dae05d42359e19b234", + "engraphis/dashboard_app.py": "9305c9c72c43027b2b79c0ce559d398fc232929968d6ea03c37065e3227c8d51", + "engraphis/dashboard_assets/__init__.py": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "engraphis/device_connect.py": "c8cd0a22e9fd2d92a65bd74047cc3a8b7159bfc9a297cb639c1c7f1699f8802e", + "engraphis/document_import.py": "94fa0ca340ad0ebd060b143f46657798a81c440a11b82aa46fefa83fb65295dc", + "engraphis/engines/__init__.py": "111232af583889195c5f5a60298e32484348608e81d2bdd822fd3ecd2a33c1e4", + "engraphis/engines/embedder.py": "998b65dd566966bb6581fd9f09cdf46c58a3923ef5df3073ccdaa541153a3581", + "engraphis/engines/ingest.py": "1a5d4b52c13e533864329f9fff11c0f6ebc299ff7093a9d9275e5c9626a39ce2", + "engraphis/engines/intelligence.py": "b561589b98deb98271f104dfec6276aeba13c4815e627259be5f8769f2e7ad82", + "engraphis/engines/recall.py": "f979580d065599c07acbc3add59f71e52d9a186a2104b0e257daa7959ea88d26", + "engraphis/engines/reweight.py": "91ec5815f5d356a7068c36133d24405334450f361f902f99275bed3ccebffd49", + "engraphis/engines/thoughts.py": "4adb9c8a9bcfe736cb42fff9b5ce24631da6ec473d178e83f1c176fde3b8b814", + "engraphis/factory.py": "3b8765834cb04b052b89a9964b357b4ffb9c41a0f769bf1261768033653f708d", + "engraphis/graphdata.py": "195e583a4d4aefe97d8cff635cabea1ff9cd3f11c54ad392d951765d89910863", + "engraphis/hosted_client.py": "9c67aff6881c29704498f4ca99f836009be4ea58a248d74459c536dac7341a88", + "engraphis/http_security.py": "596981e96741fd47064d03db409605bbb435f062c0c6ef69b040aacdd8763a20", + "engraphis/inspector/__init__.py": "720cac28b8a6019d0a0c53809d5905b7d6eb9d4ecbac767505904c6ec3c39071", + "engraphis/inspector/app.py": "8a1b540de82ab3d1a6381630bc48056ba62e708118ba738092831c729959ffb4", + "engraphis/licensing.py": "7e73c28b0e1c3536e2080a129af614f838d2cae3ec3a48a3d8ed7e5153c9e935", + "engraphis/llm/__init__.py": "f3096d2ddd652b99e6fc0b4c5a8786d9bbaba41b259df0b44ce93b57bde3a8b1", + "engraphis/llm/client.py": "304330bf7a45b0eef8f5beabee419b971d205c55f686de86c26d91fea69d172e", + "engraphis/local_auth.py": "b0ad3a1926d417a2aaa6c44a7dbf6e51f575290ddfa27875b78a03db176623c3", + "engraphis/logging_setup.py": "f7d2edc756458a852e0401453e9c71b785aba08fa7859aacbdc23fb30dc7982a", + "engraphis/managed_processing.py": "6d33cdfd10800d9552fcfae3c2b071d2b39fe10fb69d1a8e5d9ed6026882197e", + "engraphis/mcp_classic_cli.py": "778122b121a1c654b8f85810fad05d9c8d7799cf13903d7dc274938b51008da0", + "engraphis/mcp_cli.py": "ed2d997438d727180842dc5fb3f6776f5a5d97974f690ee7229264be1ff61957", + "engraphis/mcp_http_cli.py": "f6ac8bb04a0cb179e840502fdd543b8f55d0f1bf0045fc7900e06ae002cf422d", + "engraphis/mcp_server.py": "bc293747112af2b4de5b0fd5bacc437fca9b2c1357b0e6fef3fc6fbbfdff5b9b", + "engraphis/models.py": "6e76e97db0aca3805c6f582ea78cc6e1c0ccd2665e16fd8ab81eb91b94141b51", + "engraphis/netutil.py": "2e0f8a9095f6f31dcb5b96d323f023b9214369d59e1c488125a7d443a55972ff", + "engraphis/observability.py": "a3a6945bf33a0d8e216da56ca7efec0031b82dc64a66cff36f0b2161f5db4981", + "engraphis/obsidian_import.py": "f5afc4a2deddf0eab92d9d9eb81540de89738df3223ddcb22c04b583be0de2a1", + "engraphis/private_state.py": "7485570efcaee8a1dc00b64ebfdc23178517235ae17609aa78db8bdda7e45fe3", + "engraphis/read_only_api.py": "478c7efa4e462e349d758143d3d44d18b9152656067c0171904bfe675a2dedbe", + "engraphis/redirector.py": "5ba964b81f09008c9369180cb49d247519000763274aabc5e046215b12fa641d", + "engraphis/routes/__init__.py": "f0d59080212cfa0d9b50877bca28e5832d1ae917899500d52c68b1c8821231af", + "engraphis/routes/memory.py": "9ca066e1762eeeaafd9790ed57d730efcaceb57742dbe0c830ad8764500ff9e5", + "engraphis/routes/v2_api.py": "9ff441c08f3f6f082646735026c03f3a4b59655f25a0a651c11131d04f7b0404", + "engraphis/routes/vault.py": "1a7eee7c1a7c7aa11091042756aa2739a3eb963647020f40584a6a38da1988af", + "engraphis/service.py": "347291d289b9f9919ca0a6c65a6318e35d41eca8df48bfb9f5e5424c1669ce5e", + "engraphis/service_context.py": "3de9289f49a977cdc206285ac42a9953a104eb1d1b1bc8ea77febd75c7cd82ab", + "engraphis/static/__init__.py": "1fff4c4e2554e7f5fcf3eace269feba09827524917193a4dd65df95bae64ad1f", + "engraphis/stores/__init__.py": "48ee4326c8f28eecf46f558b7aea21adb779226a7038299017ab90196d5d84be", + "engraphis/stores/graph.py": "ebf603b54cf8450e7c9a7319bd05db2f39fcda8491f5969d6af3e8da61571bc2", + "engraphis/stores/ledger.py": "df5cbb30d977decc0a9c3a2365c9c115cfbb5fe951bae48446436661c80e5d30", + "engraphis/stores/vaults.py": "2c986129b9d1e7aab33e18a3b9a278eb5ad2236895587f69b5816a5d96796bc3", + "engraphis/stores/vectors.py": "45a1baca381fc647548cc89424eb36d5853f7562c275b191b35b99339a190b7d", + "engraphis/update_check.py": "ffbf5ef682fb15177915073ebc0b5eab4dee9092bbf0f58d36a8a54c6605ccf4", + "eval/__init__.py": "639f0c6d9d6aac8ff6dc605a34a0a301058905cc53bff4eaed5912247f0e7c56", + "eval/ablation.py": "16f159dee75d2f96cc42f230c2403fa19ea0bda7091c4823660da553463a194a", + "eval/adversarial_memory_security.py": "35dd8d981bcbad50e9815465be420b05b62a9dea28a78eb6cc1e09ec51c320c4", + "eval/agent_benchmarks.py": "91c157b1d3d445fe0daa236edf21decb7e3713ad9bbaacbf0a46c0d8a5d1f2ee", + "eval/benchmark.py": "ed828e3548e8fb05ffafe9479791e545e56504421ff88676e4bf4466d6beaf91", + "eval/capacity_matrix.py": "38c269c3eac8196ba90eea9b602b836f99b4e353732eb86cf76c58256c526622", + "eval/chunking_eval.py": "a16544353940c0a8c40cea3b9932d3399b35ea5994b809b78f5dbe4a952c467f", + "eval/code_agent_ab.py": "d98bba6b77700ff6bf86ff0d2cf518a67e5a2676ef51bbddabbb2ff26e1f3aaa", + "eval/code_arm.py": "d211166fce1b8a4173848e1617873b7e84aadeff43746effe7483c54bbdb6f1d", + "eval/coding_acceptance.py": "4b39cbcb60d7fba503cca597399cf9d04ad9567a43cdb950015ccf552e6a2773", + "eval/consolidation_ranking.py": "917b578d4e0bcb929bf1a1a37611acf7716a520c076abf4ade0d8d12a1c455de", + "eval/context_economy.py": "709ac7cc866855f96d7717ab2bea12e8b0d3a140d15fb978a2a929ad085931f2", + "eval/context_efficiency_guardrails.py": "22afd1a6fe17219e74701dc587ec35f569a5bf22bea270944525f51746723f14", + "eval/datasets/codemem.jsonl": "341313023c22850a2e14f02742b571ad1deca824f886a1654a59541304c01f3c", + "eval/datasets/longdoc.jsonl": "7f5ade95e1f283d0db8cf78e53ed8995d3534f847e616d2c0005fd8da37ac790", + "eval/engine_capacity.py": "3030485afafd4735283195ec8188ac815a2e8eeefa76b255aacd3a01925e3f2d", + "eval/external.py": "d93cc071e555c31f4c5521ab0b2aeb370df24656e5ee7b60904113d97b1416ae", + "eval/extractor_quality.py": "50820fe7f821d111e17e4e77a3d1159e7d6979d110b052c4f254a5b309c2652a", + "eval/fts_insert_scaling.py": "a8ecfbe19695f6d4659c3edf389b007c965b214b64fdd58d5ee86635fa766144", + "eval/graph_every_bench.py": "79da573c5edf315f71bfab412d3ea283b8da45d1fdabc78ddd19302ead09e4f0", + "eval/graph_traversal.py": "b094f75c3a1d75ba3cf19e372187d692d3c595a1d9bde19bbe95ae0c79a5175f", + "eval/grounded.py": "053d5193b716a2c3e507fcd44057d392de910a4442b46bd7cc1f30ac0ba68541", + "eval/handoff_quality.py": "7daf635510764e236f48ca7e2537a85d8ebc1ad995513144329c1f0236405937", + "eval/harness.py": "d9c5f960e891a3d0912e519eec554a970c973b3b8893df861f0258aa16342310", + "eval/hosted_evidence.py": "7946cd8c1e3aa291268271b2aa11210d5f09c9b05ba635aa0b64bef07bdcee45", + "eval/hosted_ledger.py": "a53036d12ff671371c148910a816fb20c7e7f3346250a303722352f47b06c476", + "eval/hosted_luna.py": "4dbf02a65eec38bcde92d82952a0b372abbac1f68378d11a04528f4a31a835dc", + "eval/longmemeval_v2.py": "defb4d47f453aa4615a8f101b82df3fadf64f0f9eae0ce1021d86d3750dad437", + "eval/longmemeval_v2_evidence.py": "8562d32590e4267e033cb1da2a7fda626bdc2630ebbf8547df282896f34abf8b", + "eval/longmemeval_v2_matrix.py": "ca085cd59481813cce5dbdfbc94f40f67173ac3a1bc3dce6f6d3e09eb7b08153", + "eval/metrics.py": "16857e2cf6ed339cb57a26c9bfa1879444b4d279bd972e5a9fa644ed1308afe0", + "eval/native_coverage_scaling.py": "0c7c3f5c80570c7ab02310f14927eb82399d1a624d65df895e937ed87339fe9c", + "eval/performance.py": "6b63a87f9fa8104bb9a3e7242fef0bceb8510da73fd5b0523f025b9654b4c63f", + "eval/performance_engine.py": "3d37cf0a5989c8fa6e8b6ab7ae0b2e0d5410a8b922d2f3130c1a7794d93dcbb1", + "eval/planned_recall.py": "f9a87291ecb181045b98ca65fe55db820bf7cee4ae4f4d087ca3458afdd7837e", + "eval/proactive_ranking.py": "8610541f1d547f9c0eb46d078dbcaa670c0a97157acc37f96ec08b482cb7a6ab", + "eval/productivity.py": "6d4644ebdc44472aeb3879963774fab276bfa269b781139c46ded48774a22717", + "eval/public_readiness.py": "5ce8a18d0bfe09e75e88548a589b8fc6d2cbf04c0f8cd1ce51cd9519136a2751", + "eval/redteam_poisoning.py": "fce120cc3adf2ee966b59cd3ea7f20d242a0af49b52492143543130fe14c0cc8", + "eval/reinforcement.py": "72ed766775a2658eaa728afec51c0ac22d97a90e813111954df66a6ec50f2bef", + "eval/repair_discovery.py": "db05496fbbcb0df86c5cdc2f0c85fb6b6605b0cace6cb44ae2add10b72784b5f", + "eval/resolver_reworded_corrections.py": "a9054778a37b2175b46f04b674b4779e358931eee5d2ae52bbc5f953d234fb9e", + "eval/resource_hierarchy.py": "5ab6c989bb143c4386749c45a33c190447e829c1b5657e8c0aca30f34bd69461", + "eval/rework_statistics.py": "e12c14288797c5cf2dd93d51f606244287bc2f4ff8bd401f1d1b072efd1f9529", + "eval/run_longmemeval_v2.py": "2e003d8ecf4f44ac5a3f80bd3ba8fe18bc74e769298fefe63fde8bb2a98f3a04", + "eval/task_pairs.py": "fddc54804e8837ec0731813297fb55825458317f898e29176e16f3f5a2f527fd", + "eval/vector_scale.py": "3f9c327d9eca1a857512ddc208e972933be1a7d4fa7fa0017aca0cbf8fe7bb6d", + "eval/vector_scale_storage.py": "bda0c1139596eb9232cd75c826fc941101b6116bae32ad7895525d43f9d35484", + "eval/vector_scan_plan.py": "92de2f3b41aa457dcfee11998936ce35e023fe61596ed98f3836c998a6e9a1cd", + "scripts/export_offline_evidence.py": "6e32efbf4448cb4bdbdf7ac6d52293f5996e2acb78ae89dd9a1bd92c00fcf2ee" + } + } +} diff --git a/docs/benchmark-evidence/offline-fixtures-v8.json.sha256 b/docs/benchmark-evidence/offline-fixtures-v8.json.sha256 new file mode 100644 index 00000000..0ec5e4c8 --- /dev/null +++ b/docs/benchmark-evidence/offline-fixtures-v8.json.sha256 @@ -0,0 +1 @@ +f48f4aa3b4bde802c1b2f008820ee1fc45faee1901e876e0725a4b77964e44c2 offline-fixtures-v8.json diff --git a/docs/benchmark-evidence/offline-fixtures-v9.json b/docs/benchmark-evidence/offline-fixtures-v9.json new file mode 100644 index 00000000..2424799b --- /dev/null +++ b/docs/benchmark-evidence/offline-fixtures-v9.json @@ -0,0 +1,257 @@ +{ + "environment": { + "embedding": "deterministic", + "numpy": "2.4.5", + "platform": "win32", + "python": "3.12.10", + "vector_backend": "numpy" + }, + "generated_on": "2026-09-13", + "privacy": { + "contains_answers": false, + "contains_customer_data": false, + "contains_per_record_fingerprints": false, + "contains_prompts": false, + "contains_raw_questions": false + }, + "runs": [ + { + "boundary": "Deterministic offline retrieval fixture; normalized-character token estimator; not external QA or provider billing.", + "command": "python -m eval.chunking_eval --dataset eval/datasets/longdoc.jsonl --k 5", + "config_digest": "c1c8196aa7e1568ef3844a9fb2d76b87f342c39108e32d6ad144b885a76143b8", + "config_digest_method": "sha256(UTF-8 exact command)", + "id": "offline-chunking", + "result": { + "chunked": { + "max_stored_tokens": 59, + "mean_context_tokens": 214.3, + "mean_evidence_tokens": 42.4, + "memories": 24, + "recall_at_k": 1.0 + }, + "context_reduction_pct": 71.1, + "documents": 6, + "k": 5, + "questions": 18, + "token_counter": "engraphis.chars4.v1", + "whole": { + "max_stored_tokens": 213, + "mean_context_tokens": 740.3, + "mean_evidence_tokens": 162.2, + "memories": 6, + "recall_at_k": 1.0 + } + } + }, + { + "boundary": "Deterministic offline CodeMem fixture; serialized JSON-shape payload proxies, not MCP transport responses, provider billing, or latency claims.", + "command": "python -m eval.performance --dataset eval/datasets/codemem.jsonl --k 5 --iterations 10 --json", + "config_digest": "bbe4aca81e58d4830e50a8fc7729a1d15b71d97a6299bccd79432b7f119677d7", + "config_digest_method": "sha256(UTF-8 exact command)", + "id": "offline-performance", + "result": { + "answer_token_recall": 1.0, + "compact_serialized_payload_tokens": 10982, + "dataset_cases": 14, + "full_serialized_payload_tokens": 23810, + "hit_at_k": 1.0, + "k": 5, + "max_context_tokens": 108, + "mean_context_tokens": 85.38, + "memories": 44, + "questions": 26, + "recall_at_k": 1.0, + "saved_serialized_payload_tokens": 12828, + "serialized_payload_savings_ratio": 0.5388, + "timed_recalls": 260, + "token_budget": 1500, + "token_counter": "engraphis.regex.v1" + } + }, + { + "boundary": "Deterministic offline support/abstention fixture; not a frontier-model answer-quality score.", + "command": "python -m eval.grounded", + "config_digest": "590442e51e3642c10489165759919dc86ffac62c182937330c153e7f8d5fc26f", + "config_digest_method": "sha256(UTF-8 exact command)", + "id": "offline-grounded", + "result": { + "abstained": 6, + "answerable": 5, + "decision_accuracy": 1.0, + "grounded": 5, + "off_topic": 6, + "quarantine_hits": 1, + "quarantined": 1 + } + } + ], + "schema": "engraphis-public-offline-fixtures/v1", + "suite": { + "digest": "c8976cf0989e82f57810b99bf19f2ee3f860d07726bcb28479a319a19f00f94f", + "digest_method": "sha256(canonical compact JSON mapping each sorted path to its file SHA-256)", + "files": { + "engraphis/__init__.py": "7efb24616f3a1c5181bf83bb4b60dd97122372b2f5c15db9a89f685ea39cbcbb", + "engraphis/ai_context.py": "4dfd5d39eb95d05c591d1981e9e855eced73232f53efd9fe9966e0e08957d030", + "engraphis/app.py": "44d68ad8c0ff46baed01978c9b04e40b8be5031609d5a69e205b7f05da3777fb", + "engraphis/backends/__init__.py": "a9f22b9278362904166614081f1df78469d453601b298ce4e8afdba8a3722b25", + "engraphis/backends/codegraph.py": "83e723a91068d23694092fbe00157fcb2597061d453eb36f955bf55bc5b4d35e", + "engraphis/backends/embedder_api.py": "56a6bceea4f757325dcea987b0339e41d3875634b1ae5103f0537a358cf5878b", + "engraphis/backends/embedder_deterministic.py": "ec8b23de7e7e8273416125f5876ca96f55e4ae7881841bae55783ab0ba9130ad", + "engraphis/backends/embedder_st.py": "e1c20fd980e07060387e3f9fa37fe02a916959fc8abce4e6067a62699c726de1", + "engraphis/backends/encrypted_db.py": "25f6c1480d296a88f317213700a8b3c81e2732399bfac464b0d893465b25e846", + "engraphis/backends/extractor.py": "f2e3455ab7f14caee1d5b5c4ef071e498e90118f1b0ddcb8510c969583b0fc57", + "engraphis/backends/graph_extractor.py": "88561efa0d3fabc447a0a005b10e36261379d46218cf62d905e6928cd2fda676", + "engraphis/backends/model_source.py": "8c3c7681f95214a2bbabd8de222e5ee11f42fe13402d27365654ae75fb363d4e", + "engraphis/backends/postgres_schema.py": "8468578c3add701d30d5eaa36d768ded2375d116e55f1836e09f6107a07a267e", + "engraphis/backends/query_planner.py": "bbdd77afc9b5523421b85b2ae63c8da7f5a7b777265450e0d21708a83e7bb23c", + "engraphis/backends/reranker.py": "747761d6cbfa421388974bcfd98d844f92391d80f4bf6a4feca00b0c7a6908ca", + "engraphis/backends/resources.py": "47cc867c3aecc8bd95fa284bc5bb04715f3339c19a0a11512973ef6171c95944", + "engraphis/backends/retention.py": "381d9371e3951d762f8b55eb54711de5697642acb39de99a714f246c059ecbd0", + "engraphis/backends/sync_folder.py": "e4f70a92a17f6a365910670df041e6e3ca421d44ada2827917cd66b4dc067bfa", + "engraphis/backends/sync_relay.py": "b8b9ad265453aba17ba7c27a355e12a793469b3e44cb217943c6fad9382a3006", + "engraphis/backends/vector_numpy.py": "c598831bea547824cfe08844816fa79857d3617cb0631238f95dad955a424f72", + "engraphis/backends/vector_sqlitevec.py": "6148e14ceaacc19239b64c642a3fba0e98797c78cec356210157afadf475a08b", + "engraphis/build_info.py": "624c22471e56d4c4047160808c4245488292af611564d1a63ca437605bbb414f", + "engraphis/classic_assets/__init__.py": "a7c1d52b285e3faa670ce231814b5758754aa0fbd05e1428e74c20c3ec51a4f1", + "engraphis/cloud_authz.py": "e80500579cb3a1d5fbf30814dc94e3e3967e50b311e8ed2fa56afcc13f7eb565", + "engraphis/cloud_features.py": "a1bec76216d4f1276a3313dabc1d29a1666378e11863d05d1a02e695cf6d7293", + "engraphis/cloud_session.py": "7c83d7b85665c05aa4da2597a6b4ad2b951f1f8f4af20105d9d1750b9b123c2d", + "engraphis/commercial.py": "184f312066a9e682e51a0abeff042f1c0e8eed2d47470157b23930b5a17633aa", + "engraphis/config.py": "a46f3a335fad343e7df32942be91c04094fbafaf14b8b11f5fc433ef74743226", + "engraphis/core/__init__.py": "dd5143729c3939237f04636f437032b1f2d3a5f7d82c91bbc2a5a283c3f0ebaa", + "engraphis/core/adaptive_context.py": "cc5ce48109bb0d5230a5b2b8424b829c853feec5b5d5b82596413f2279b0c9f9", + "engraphis/core/browsing.py": "cfae752d52ef51b17c4ffbe44dde62d5b0e1ed0ca34ec0e1788f3991d94bf05f", + "engraphis/core/codegraph_export.py": "4641074258d7b23498f92dd45053a0fbb111863eaad2001c08e5e3c2dc2fd54f", + "engraphis/core/conflicts.py": "28530be25a4af0bffd8f609b965b33ca7f93199a70887789b2148fda8a61a486", + "engraphis/core/consolidate.py": "f66eedfe08319a64b761261ccf1c99b163eba564d6d4060534bf8c575aecf232", + "engraphis/core/context.py": "9fb55c9b2fbbb1b85c16418cd2f7fe5fffe35c28cd6d1baf4f3a2ae709804f33", + "engraphis/core/diagnostics.py": "7d563cbbb204ed2fdaa880c4912acd47df946f91652eb2d1a9444c420b724889", + "engraphis/core/documents.py": "84385db39ba44e06b58b4b26dbf954228ff4abed7230f28a7280166fa6457861", + "engraphis/core/engine.py": "8d88554237ff9768b4268ed052a1268451bbeeb4b6c2600b6bd6fddd3dac478e", + "engraphis/core/fsutil.py": "6db770fa8bd3e1a57dfa70eb8e8bc46d48c2dc53ead1b0b43eeecf085ef58cfc", + "engraphis/core/graph_layers.py": "64d74ab01c77119f6343ba6f1d6a84f9653f1a5d34d47ce7966f3ac31b29d2ea", + "engraphis/core/graph_policy.py": "ec5b373d01adb2de87df31d9f543130018e9a73faaaed239a184f14a32646615", + "engraphis/core/graph_scene.py": "cab0aef9ce464620d1ee9ff88fab13fd89707c831212e1d8f1ae2c603c8b6010", + "engraphis/core/graphrank.py": "1279a58396104d3f906bfd5ec75b32efedfefe52201467bf19d80be3517017a5", + "engraphis/core/grounded.py": "ac40057dc37aa907e09c68e6b8cd54a989525fb310097df2970858708870ba3e", + "engraphis/core/ids.py": "6bd0d98a2865a0c8b7a8e047fce177f13792ac7c5a262871f74a00876815d16c", + "engraphis/core/interfaces.py": "93544dcb75d8373c594babc439baf2641ac46b195c89aacfcd4d252cdd3f5e1f", + "engraphis/core/mutations.py": "dbb46a97686994e1652b2698e50c3309ff428d7258d6e8e53cbad7bb55b459aa", + "engraphis/core/obsidian.py": "991267c153cb7c4c40f7fe8f50aa71688892e250aaaf383b22c9e5910dc263b7", + "engraphis/core/poisoning.py": "5bc67169ee8032f3777f2d3969dcf71821437bd473ce4f917c4b41a50e845fb6", + "engraphis/core/query_planner.py": "249062d67392ab7c203cc71e9040e99bee91bf570604e90949149a93cb652120", + "engraphis/core/read_snapshots.py": "be08e63a88bd38ed91d61b28657a65201c38994856db2798b209a73151dd202a", + "engraphis/core/recall.py": "529f6518783b9a5e6ea35660d55f472467458a7f1f031b8dd37011142384a5a9", + "engraphis/core/resolve.py": "f01a6f55e44320ab04b97e516342f20155668863b2fc4765305e066d87586524", + "engraphis/core/retention_policy.py": "864c03bdb6e743cd0002c706de471e920f1fa1f1a9918ab343ef4c2042b47429", + "engraphis/core/retrieval_policy.py": "7e970ac57762a1e55091bac46314c3d60aba0bf2cbb11405ce0f7e032448866e", + "engraphis/core/savings.py": "cfbcfc7e476f4e28028555cd519696e23099f6210cf0b733225832aeaa0bc7dc", + "engraphis/core/schema.py": "ac273d3f0383995be815bbd866f2a36ea1398f30833aed57b8d4459afc87096b", + "engraphis/core/scoring.py": "f5b6ac291edf0968b3de83cb1951a97d5bfd8a8d079199cb2ef95bba0884c89a", + "engraphis/core/secrets.py": "a4835ba06e2616156528df6365ca1aba6cba0c97cdf834a709d2797a371099d2", + "engraphis/core/store.py": "ff4522a9861fabbaba762161e18fa20a5e39196ac850f7db06617cb8a4efdd1c", + "engraphis/core/sync.py": "69f75b50fdb1ec9352f92460c89efeec8d72ca642bd10beb29474a8c62b4f58a", + "engraphis/core/textutil.py": "acd65031729fa5d91d09527b8eb52518b83cfce77a55e6b7ae2d94686e35c1a6", + "engraphis/core/user_model.py": "3147ec8ee7cfd855783f639874b63f331cdc822bd8bd9298cfb326dd18666026", + "engraphis/core/vector_repair.py": "a8c1812de4e3ed288eda3e54a505e136d6ebd3ec296788bcbb8804b11e13cfc8", + "engraphis/core/vector_search.py": "75800052e573e9af01c6fd098eaf8647c3c45cd7eb2601dae05d42359e19b234", + "engraphis/dashboard_app.py": "9305c9c72c43027b2b79c0ce559d398fc232929968d6ea03c37065e3227c8d51", + "engraphis/dashboard_assets/__init__.py": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "engraphis/device_connect.py": "c8cd0a22e9fd2d92a65bd74047cc3a8b7159bfc9a297cb639c1c7f1699f8802e", + "engraphis/document_import.py": "94fa0ca340ad0ebd060b143f46657798a81c440a11b82aa46fefa83fb65295dc", + "engraphis/engines/__init__.py": "111232af583889195c5f5a60298e32484348608e81d2bdd822fd3ecd2a33c1e4", + "engraphis/engines/embedder.py": "998b65dd566966bb6581fd9f09cdf46c58a3923ef5df3073ccdaa541153a3581", + "engraphis/engines/ingest.py": "1a5d4b52c13e533864329f9fff11c0f6ebc299ff7093a9d9275e5c9626a39ce2", + "engraphis/engines/intelligence.py": "b561589b98deb98271f104dfec6276aeba13c4815e627259be5f8769f2e7ad82", + "engraphis/engines/recall.py": "f979580d065599c07acbc3add59f71e52d9a186a2104b0e257daa7959ea88d26", + "engraphis/engines/reweight.py": "91ec5815f5d356a7068c36133d24405334450f361f902f99275bed3ccebffd49", + "engraphis/engines/thoughts.py": "4adb9c8a9bcfe736cb42fff9b5ce24631da6ec473d178e83f1c176fde3b8b814", + "engraphis/factory.py": "3b8765834cb04b052b89a9964b357b4ffb9c41a0f769bf1261768033653f708d", + "engraphis/graphdata.py": "195e583a4d4aefe97d8cff635cabea1ff9cd3f11c54ad392d951765d89910863", + "engraphis/hosted_client.py": "9c67aff6881c29704498f4ca99f836009be4ea58a248d74459c536dac7341a88", + "engraphis/http_security.py": "596981e96741fd47064d03db409605bbb435f062c0c6ef69b040aacdd8763a20", + "engraphis/inspector/__init__.py": "720cac28b8a6019d0a0c53809d5905b7d6eb9d4ecbac767505904c6ec3c39071", + "engraphis/inspector/app.py": "8a1b540de82ab3d1a6381630bc48056ba62e708118ba738092831c729959ffb4", + "engraphis/licensing.py": "7e73c28b0e1c3536e2080a129af614f838d2cae3ec3a48a3d8ed7e5153c9e935", + "engraphis/llm/__init__.py": "f3096d2ddd652b99e6fc0b4c5a8786d9bbaba41b259df0b44ce93b57bde3a8b1", + "engraphis/llm/client.py": "304330bf7a45b0eef8f5beabee419b971d205c55f686de86c26d91fea69d172e", + "engraphis/local_auth.py": "b0ad3a1926d417a2aaa6c44a7dbf6e51f575290ddfa27875b78a03db176623c3", + "engraphis/logging_setup.py": "f7d2edc756458a852e0401453e9c71b785aba08fa7859aacbdc23fb30dc7982a", + "engraphis/managed_processing.py": "6d33cdfd10800d9552fcfae3c2b071d2b39fe10fb69d1a8e5d9ed6026882197e", + "engraphis/mcp_classic_cli.py": "778122b121a1c654b8f85810fad05d9c8d7799cf13903d7dc274938b51008da0", + "engraphis/mcp_cli.py": "ed2d997438d727180842dc5fb3f6776f5a5d97974f690ee7229264be1ff61957", + "engraphis/mcp_http_cli.py": "f6ac8bb04a0cb179e840502fdd543b8f55d0f1bf0045fc7900e06ae002cf422d", + "engraphis/mcp_server.py": "bc293747112af2b4de5b0fd5bacc437fca9b2c1357b0e6fef3fc6fbbfdff5b9b", + "engraphis/models.py": "6e76e97db0aca3805c6f582ea78cc6e1c0ccd2665e16fd8ab81eb91b94141b51", + "engraphis/netutil.py": "2e0f8a9095f6f31dcb5b96d323f023b9214369d59e1c488125a7d443a55972ff", + "engraphis/observability.py": "a3a6945bf33a0d8e216da56ca7efec0031b82dc64a66cff36f0b2161f5db4981", + "engraphis/obsidian_import.py": "f5afc4a2deddf0eab92d9d9eb81540de89738df3223ddcb22c04b583be0de2a1", + "engraphis/private_state.py": "7485570efcaee8a1dc00b64ebfdc23178517235ae17609aa78db8bdda7e45fe3", + "engraphis/read_only_api.py": "478c7efa4e462e349d758143d3d44d18b9152656067c0171904bfe675a2dedbe", + "engraphis/redirector.py": "5ba964b81f09008c9369180cb49d247519000763274aabc5e046215b12fa641d", + "engraphis/routes/__init__.py": "f0d59080212cfa0d9b50877bca28e5832d1ae917899500d52c68b1c8821231af", + "engraphis/routes/memory.py": "9ca066e1762eeeaafd9790ed57d730efcaceb57742dbe0c830ad8764500ff9e5", + "engraphis/routes/v2_api.py": "9ff441c08f3f6f082646735026c03f3a4b59655f25a0a651c11131d04f7b0404", + "engraphis/routes/vault.py": "1a7eee7c1a7c7aa11091042756aa2739a3eb963647020f40584a6a38da1988af", + "engraphis/service.py": "347291d289b9f9919ca0a6c65a6318e35d41eca8df48bfb9f5e5424c1669ce5e", + "engraphis/service_context.py": "3de9289f49a977cdc206285ac42a9953a104eb1d1b1bc8ea77febd75c7cd82ab", + "engraphis/static/__init__.py": "1fff4c4e2554e7f5fcf3eace269feba09827524917193a4dd65df95bae64ad1f", + "engraphis/stores/__init__.py": "48ee4326c8f28eecf46f558b7aea21adb779226a7038299017ab90196d5d84be", + "engraphis/stores/graph.py": "ebf603b54cf8450e7c9a7319bd05db2f39fcda8491f5969d6af3e8da61571bc2", + "engraphis/stores/ledger.py": "df5cbb30d977decc0a9c3a2365c9c115cfbb5fe951bae48446436661c80e5d30", + "engraphis/stores/vaults.py": "2c986129b9d1e7aab33e18a3b9a278eb5ad2236895587f69b5816a5d96796bc3", + "engraphis/stores/vectors.py": "45a1baca381fc647548cc89424eb36d5853f7562c275b191b35b99339a190b7d", + "engraphis/update_check.py": "ffbf5ef682fb15177915073ebc0b5eab4dee9092bbf0f58d36a8a54c6605ccf4", + "eval/__init__.py": "639f0c6d9d6aac8ff6dc605a34a0a301058905cc53bff4eaed5912247f0e7c56", + "eval/ablation.py": "16f159dee75d2f96cc42f230c2403fa19ea0bda7091c4823660da553463a194a", + "eval/adversarial_memory_security.py": "35dd8d981bcbad50e9815465be420b05b62a9dea28a78eb6cc1e09ec51c320c4", + "eval/agent_benchmarks.py": "91c157b1d3d445fe0daa236edf21decb7e3713ad9bbaacbf0a46c0d8a5d1f2ee", + "eval/benchmark.py": "ed828e3548e8fb05ffafe9479791e545e56504421ff88676e4bf4466d6beaf91", + "eval/capacity_matrix.py": "38c269c3eac8196ba90eea9b602b836f99b4e353732eb86cf76c58256c526622", + "eval/chunking_eval.py": "a16544353940c0a8c40cea3b9932d3399b35ea5994b809b78f5dbe4a952c467f", + "eval/code_agent_ab.py": "d98bba6b77700ff6bf86ff0d2cf518a67e5a2676ef51bbddabbb2ff26e1f3aaa", + "eval/code_arm.py": "d211166fce1b8a4173848e1617873b7e84aadeff43746effe7483c54bbdb6f1d", + "eval/coding_acceptance.py": "4b39cbcb60d7fba503cca597399cf9d04ad9567a43cdb950015ccf552e6a2773", + "eval/consolidation_ranking.py": "917b578d4e0bcb929bf1a1a37611acf7716a520c076abf4ade0d8d12a1c455de", + "eval/context_economy.py": "709ac7cc866855f96d7717ab2bea12e8b0d3a140d15fb978a2a929ad085931f2", + "eval/context_efficiency_guardrails.py": "22afd1a6fe17219e74701dc587ec35f569a5bf22bea270944525f51746723f14", + "eval/datasets/codemem.jsonl": "341313023c22850a2e14f02742b571ad1deca824f886a1654a59541304c01f3c", + "eval/datasets/longdoc.jsonl": "7f5ade95e1f283d0db8cf78e53ed8995d3534f847e616d2c0005fd8da37ac790", + "eval/engine_capacity.py": "3030485afafd4735283195ec8188ac815a2e8eeefa76b255aacd3a01925e3f2d", + "eval/external.py": "d93cc071e555c31f4c5521ab0b2aeb370df24656e5ee7b60904113d97b1416ae", + "eval/extractor_quality.py": "50820fe7f821d111e17e4e77a3d1159e7d6979d110b052c4f254a5b309c2652a", + "eval/fts_insert_scaling.py": "a8ecfbe19695f6d4659c3edf389b007c965b214b64fdd58d5ee86635fa766144", + "eval/graph_every_bench.py": "79da573c5edf315f71bfab412d3ea283b8da45d1fdabc78ddd19302ead09e4f0", + "eval/graph_traversal.py": "b094f75c3a1d75ba3cf19e372187d692d3c595a1d9bde19bbe95ae0c79a5175f", + "eval/grounded.py": "053d5193b716a2c3e507fcd44057d392de910a4442b46bd7cc1f30ac0ba68541", + "eval/handoff_quality.py": "7daf635510764e236f48ca7e2537a85d8ebc1ad995513144329c1f0236405937", + "eval/harness.py": "d9c5f960e891a3d0912e519eec554a970c973b3b8893df861f0258aa16342310", + "eval/hosted_evidence.py": "7946cd8c1e3aa291268271b2aa11210d5f09c9b05ba635aa0b64bef07bdcee45", + "eval/hosted_ledger.py": "a53036d12ff671371c148910a816fb20c7e7f3346250a303722352f47b06c476", + "eval/hosted_luna.py": "4dbf02a65eec38bcde92d82952a0b372abbac1f68378d11a04528f4a31a835dc", + "eval/longmemeval_v2.py": "defb4d47f453aa4615a8f101b82df3fadf64f0f9eae0ce1021d86d3750dad437", + "eval/longmemeval_v2_evidence.py": "8562d32590e4267e033cb1da2a7fda626bdc2630ebbf8547df282896f34abf8b", + "eval/longmemeval_v2_matrix.py": "ca085cd59481813cce5dbdfbc94f40f67173ac3a1bc3dce6f6d3e09eb7b08153", + "eval/metrics.py": "16857e2cf6ed339cb57a26c9bfa1879444b4d279bd972e5a9fa644ed1308afe0", + "eval/native_coverage_scaling.py": "0c7c3f5c80570c7ab02310f14927eb82399d1a624d65df895e937ed87339fe9c", + "eval/performance.py": "6b63a87f9fa8104bb9a3e7242fef0bceb8510da73fd5b0523f025b9654b4c63f", + "eval/performance_engine.py": "3d37cf0a5989c8fa6e8b6ab7ae0b2e0d5410a8b922d2f3130c1a7794d93dcbb1", + "eval/planned_recall.py": "f9a87291ecb181045b98ca65fe55db820bf7cee4ae4f4d087ca3458afdd7837e", + "eval/proactive_ranking.py": "8610541f1d547f9c0eb46d078dbcaa670c0a97157acc37f96ec08b482cb7a6ab", + "eval/productivity.py": "6d4644ebdc44472aeb3879963774fab276bfa269b781139c46ded48774a22717", + "eval/public_readiness.py": "5ce8a18d0bfe09e75e88548a589b8fc6d2cbf04c0f8cd1ce51cd9519136a2751", + "eval/redteam_poisoning.py": "fce120cc3adf2ee966b59cd3ea7f20d242a0af49b52492143543130fe14c0cc8", + "eval/reinforcement.py": "72ed766775a2658eaa728afec51c0ac22d97a90e813111954df66a6ec50f2bef", + "eval/repair_discovery.py": "db05496fbbcb0df86c5cdc2f0c85fb6b6605b0cace6cb44ae2add10b72784b5f", + "eval/resolver_reworded_corrections.py": "a9054778a37b2175b46f04b674b4779e358931eee5d2ae52bbc5f953d234fb9e", + "eval/resource_hierarchy.py": "5ab6c989bb143c4386749c45a33c190447e829c1b5657e8c0aca30f34bd69461", + "eval/rework_statistics.py": "e12c14288797c5cf2dd93d51f606244287bc2f4ff8bd401f1d1b072efd1f9529", + "eval/run_longmemeval_v2.py": "2e003d8ecf4f44ac5a3f80bd3ba8fe18bc74e769298fefe63fde8bb2a98f3a04", + "eval/task_pairs.py": "fddc54804e8837ec0731813297fb55825458317f898e29176e16f3f5a2f527fd", + "eval/vector_scale.py": "3f9c327d9eca1a857512ddc208e972933be1a7d4fa7fa0017aca0cbf8fe7bb6d", + "eval/vector_scale_storage.py": "bda0c1139596eb9232cd75c826fc941101b6116bae32ad7895525d43f9d35484", + "eval/vector_scan_plan.py": "92de2f3b41aa457dcfee11998936ce35e023fe61596ed98f3836c998a6e9a1cd", + "scripts/export_offline_evidence.py": "6e32efbf4448cb4bdbdf7ac6d52293f5996e2acb78ae89dd9a1bd92c00fcf2ee" + } + } +} diff --git a/docs/benchmark-evidence/offline-fixtures-v9.json.sha256 b/docs/benchmark-evidence/offline-fixtures-v9.json.sha256 new file mode 100644 index 00000000..82b67e4e --- /dev/null +++ b/docs/benchmark-evidence/offline-fixtures-v9.json.sha256 @@ -0,0 +1 @@ +455fc9d32a236e582a49aaaf9b84f30cae2573dc6ed982f4dd7dd845afcaf24c offline-fixtures-v9.json diff --git a/docs/images/context-efficiency.svg b/docs/images/context-efficiency.svg index cb679799..deb71132 100644 --- a/docs/images/context-efficiency.svg +++ b/docs/images/context-efficiency.svg @@ -1,6 +1,6 @@ What the memory system changes -A compact dark telemetry chart of local measurements and deterministic fixtures across continuity, graph reasoning, retrieval quality, and context economy. A local LoCoMo diagnostic reduces replayed context from 49,915,394 to 891,857 tokens, 98.21% lower, while preserving the measured retrieval result for that diagnostic. Cross-session handoff satisfaction rises from 3 of 15 queries with the last memories to 15 of 15 with proactive ranking or a consolidated summary. Intent-layered graph routing rises from 0 of 3 to 3 of 3 correct top-1 targets. Two-hop graph recall rises from 0 of 3 with one-hop expansion to 3 of 3 with Personalized PageRank. Consolidation-aware ranking selects the expected digest in 2 of 2 summary cases instead of 0 of 2 for the baseline while preserving raw and source evidence. Structure-aware chunks reduce retrieved context from 740.3 to 214.3 tokens and the smallest evidence-holding memory from 162.2 to 42.4 tokens, both with Recall at 5 of 1.000. A compact JSON-shape proxy, not an MCP transport response, uses 10,982 rather than 23,810 tokens, with Recall at 5, hit at 5, and answer-token recall all 1.000. Grounded recall makes 11 of 11 correct decisions, 8 of 8 memory-security checks pass, and packed context averages 85.38 tokens under a 1,500-token cap. This measures estimated prompt-context reduction, does not measure provider billing, with current chunking, payload and grounding aggregates bound to public fixture SHA-256 2d6b4fab9e75edc91d105d49877f9225f28ffe4d366e40a44e931f19cb13f498. +A compact dark telemetry chart of local measurements and deterministic fixtures across continuity, graph reasoning, retrieval quality, and context economy. A local LoCoMo diagnostic reduces replayed context from 49,915,394 to 891,857 tokens, 98.21% lower, while preserving the measured retrieval result for that diagnostic. Cross-session handoff satisfaction rises from 3 of 15 queries with the last memories to 15 of 15 with proactive ranking or a consolidated summary. Intent-layered graph routing rises from 0 of 3 to 3 of 3 correct top-1 targets. Two-hop graph recall rises from 0 of 3 with one-hop expansion to 3 of 3 with Personalized PageRank. Consolidation-aware ranking selects the expected digest in 2 of 2 summary cases instead of 0 of 2 for the baseline while preserving raw and source evidence. Structure-aware chunks reduce retrieved context from 740.3 to 214.3 tokens and the smallest evidence-holding memory from 162.2 to 42.4 tokens, both with Recall at 5 of 1.000. A compact JSON-shape proxy, not an MCP transport response, uses 10,982 rather than 23,810 tokens, with Recall at 5, hit at 5, and answer-token recall all 1.000. Grounded recall makes 11 of 11 correct decisions, 8 of 8 memory-security checks pass, and packed context averages 85.38 tokens under a 1,500-token cap. This measures estimated prompt-context reduction, does not measure provider billing, with current chunking, payload and grounding aggregates bound to public fixture SHA-256 455fc9d32a236e582a49aaaf9b84f30cae2573dc6ed982f4dd7dd845afcaf24c. diff --git a/docs/images/evidence-backed-agent-examples.png b/docs/images/evidence-backed-agent-examples.png index 389aed29..9c253d98 100644 Binary files a/docs/images/evidence-backed-agent-examples.png and b/docs/images/evidence-backed-agent-examples.png differ diff --git a/docs/images/evidence-backed-agent-examples.svg b/docs/images/evidence-backed-agent-examples.svg index c03de7ea..dac57ddd 100644 --- a/docs/images/evidence-backed-agent-examples.svg +++ b/docs/images/evidence-backed-agent-examples.svg @@ -1,6 +1,6 @@ Three evidence-backed Engraphis agent behaviors - A three-card summary of deterministic offline fixtures. Focused context returns 740.3 to 214.3 tokens while retaining Recall at 5 of 1.000. A grounded answer returns support for 5/5 answerable questions. An unsupported question safely abstains for 6/6 off-topic questions. Reproduce with eval.chunking_eval and eval.grounded. Exact commands and config digests are registered in BENCHMARKS.md. Public-safe artifact SHA-256: 2d6b4fab9e75edc91d105d49877f9225f28ffe4d366e40a44e931f19cb13f498. + A three-card summary of deterministic offline fixtures. Focused context returns 740.3 to 214.3 tokens while retaining Recall at 5 of 1.000. A grounded answer returns support for 5/5 answerable questions. An unsupported question safely abstains for 6/6 off-topic questions. Reproduce with eval.chunking_eval and eval.grounded. Exact commands and config digests are registered in BENCHMARKS.md. Public-safe artifact SHA-256: 455fc9d32a236e582a49aaaf9b84f30cae2573dc6ed982f4dd7dd845afcaf24c. @@ -47,5 +47,5 @@ Reproduce: eval.chunking_eval + eval.grounded - SHA256 2d6b4fab9e75edc91d105d49877f9225f28ffe4d366e40a44e931f19cb13f498 + SHA256 455fc9d32a236e582a49aaaf9b84f30cae2573dc6ed982f4dd7dd845afcaf24c diff --git a/engraphis/__init__.py b/engraphis/__init__.py index d01cf0b7..d9e0d35b 100644 --- a/engraphis/__init__.py +++ b/engraphis/__init__.py @@ -2,7 +2,7 @@ from importlib.metadata import PackageNotFoundError, version as _dist_version -_SOURCE_VERSION = "1.7.3" +_SOURCE_VERSION = "1.7.4" try: __version__ = _dist_version("engraphis") @@ -14,7 +14,7 @@ except PackageNotFoundError: # source tree without an installed distribution # Keep in step with [project] version in pyproject.toml — tests/test_packaging.py # pins the two together so a release cannot ship them out of sync. - __version__ = "1.7.3" + __version__ = "1.7.4" def _default_memory_engine_factory(**kwargs): diff --git a/engraphis/commercial_manifest.json b/engraphis/commercial_manifest.json index 261a1224..509cf6ed 100644 --- a/engraphis/commercial_manifest.json +++ b/engraphis/commercial_manifest.json @@ -1,6 +1,6 @@ { "schema": "engraphis-commercial/v2", - "version": "1.7.3", + "version": "1.7.4", "control_plane": "https://api.engraphis.com", "account_portal": "https://api.engraphis.com/account", "billing": { diff --git a/engraphis/core/consolidate.py b/engraphis/core/consolidate.py index c5d1bd9a..08d527f7 100644 --- a/engraphis/core/consolidate.py +++ b/engraphis/core/consolidate.py @@ -1697,9 +1697,22 @@ def _build_digest_content( ) -> tuple[str, str, bool, dict[str, Any]]: """Build deterministic content and an optional bounded provider summary.""" subject = ", ".join(_common_tokens(cluster)) or "recurring episode" + # Memory ids are time-sortable only to the millisecond and intentionally carry + # random suffixes. A cluster built from records written at different clock + # resolutions must therefore not use timestamp or id order to choose its bounded + # quote set: that would make compaction accounting and the digest body vary across + # otherwise identical runs. + quote_cluster = sorted( + cluster, + key=lambda memory: ( + memory.content, + memory.title, + memory.id, + ), + ) quotes = [ memory.content.strip().replace("\n", " ")[:300] - for memory in cluster[:DIGEST_QUOTES] + for memory in quote_cluster[:DIGEST_QUOTES] ] content = ( f"Recurring pattern ({len(cluster)} occurrences): {subject}.\n" diff --git a/engraphis/core/ids.py b/engraphis/core/ids.py index 580dc29f..5fd64241 100644 --- a/engraphis/core/ids.py +++ b/engraphis/core/ids.py @@ -9,12 +9,32 @@ """ from __future__ import annotations +import os import secrets +import threading import time from typing import Optional _CROCKFORD = "0123456789ABCDEFGHJKMNPQRSTVWXYZ" # excludes I, L, O, U _MAX_TIMESTAMP_MS = 1 << 48 +_MAX_RANDOM = (1 << 80) - 1 +_ULID_LOCK = threading.Lock() +_LAST_TIMESTAMP_MS = -1 +_LAST_RANDOM = -1 +_LAST_PID = os.getpid() + + +def _reset_ulid_state_after_fork() -> None: + """Drop inherited sequence state and locks in a forked child.""" + global _LAST_PID, _LAST_RANDOM, _LAST_TIMESTAMP_MS, _ULID_LOCK + _ULID_LOCK = threading.Lock() + _LAST_PID = os.getpid() + _LAST_TIMESTAMP_MS = -1 + _LAST_RANDOM = -1 + + +if hasattr(os, "register_at_fork"): + os.register_at_fork(after_in_child=_reset_ulid_state_after_fork) # Canonical prefixes for each entity kind. @@ -45,7 +65,7 @@ def _encode(value: int, length: int) -> str: def ulid(timestamp_ms: Optional[int] = None) -> str: - """Return a 26-char, lexicographically sortable ULID.""" + """Return a 26-char ULID that is monotonic within one process and timestamp.""" if timestamp_ms is None: ts = int(time.time() * 1000) elif isinstance(timestamp_ms, bool) or not isinstance(timestamp_ms, int): @@ -54,7 +74,21 @@ def ulid(timestamp_ms: Optional[int] = None) -> str: ts = timestamp_ms if not 0 <= ts < _MAX_TIMESTAMP_MS: raise ValueError("timestamp_ms must be an integer in range [0, 2**48)") - rand = secrets.randbits(80) + global _LAST_PID, _LAST_RANDOM, _LAST_TIMESTAMP_MS + with _ULID_LOCK: + pid = os.getpid() + if pid != _LAST_PID: + _LAST_PID = pid + _LAST_TIMESTAMP_MS = -1 + _LAST_RANDOM = -1 + if ts == _LAST_TIMESTAMP_MS: + if _LAST_RANDOM >= _MAX_RANDOM: + raise RuntimeError("ULID entropy exhausted within one millisecond") + rand = _LAST_RANDOM + 1 + else: + rand = secrets.randbits(80) + _LAST_TIMESTAMP_MS = ts + _LAST_RANDOM = rand return _encode(ts, 10) + _encode(rand, 16) diff --git a/engraphis/mcp_classic_cli.py b/engraphis/mcp_classic_cli.py index f9bf07b0..8cf2160a 100644 --- a/engraphis/mcp_classic_cli.py +++ b/engraphis/mcp_classic_cli.py @@ -26,15 +26,10 @@ def main(argv=None) -> None: # Import after argparse so --help works without the optional MCP dependency. # See mcp_http_cli.py for the try/except ImportError rationale. - from engraphis.mcp_server import classic_mcp + from engraphis.mcp_server import _safe_run_stdio_async, classic_mcp - try: - from engraphis.mcp_server import _eager_exact_backend_check - except ImportError: - _eager_exact_backend_check = lambda: None # noqa: E731 - - _eager_exact_backend_check() - classic_mcp.run() + import anyio + anyio.run(lambda: _safe_run_stdio_async(classic_mcp)) if __name__ == "__main__": diff --git a/engraphis/mcp_server.py b/engraphis/mcp_server.py index e7fad55c..5159fa05 100644 --- a/engraphis/mcp_server.py +++ b/engraphis/mcp_server.py @@ -3162,8 +3162,13 @@ async def _safe_run_stdio_async(server: FastMCP) -> None: real_stdout_buffer = getattr(sys.stdout, "buffer", None) real_stdin_buffer = getattr(sys.stdin, "buffer", None) + # Redirect before any eager backend construction or background warmup. A + # dependency may write diagnostics to stdout while it imports; stdio MCP + # reserves that stream exclusively for JSON-RPC frames. + sys.stdout = sys.stderr + _eager_exact_backend_check() + _start_background_warmup() if real_stdout_buffer is not None and real_stdin_buffer is not None: - sys.stdout = sys.stderr wrapped_stdout = anyio.wrap_file(TextIOWrapper(real_stdout_buffer, encoding="utf-8")) wrapped_stdin = anyio.wrap_file(TextIOWrapper(real_stdin_buffer, encoding="utf-8", errors="replace")) async with stdio_server(stdin=wrapped_stdin, stdout=wrapped_stdout) as (read_stream, write_stream): @@ -3183,8 +3188,6 @@ async def _safe_run_stdio_async(server: FastMCP) -> None: def main() -> None: """Console entry point (``engraphis-mcp``). Runs Smart MCP over stdio.""" - _eager_exact_backend_check() - _start_background_warmup() import anyio anyio.run(lambda: _safe_run_stdio_async(mcp)) diff --git a/pyproject.toml b/pyproject.toml index 01164d5d..b75cb51b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -10,7 +10,7 @@ build-backend = "setuptools.build_meta" [project] name = "engraphis" -version = "1.7.3" +version = "1.7.4" description = "Local-first AI memory engine for agents — Ebbinghaus decay, interaction-aware recall, bi-temporal facts, hybrid retrieval, and an MCP server. You bring the LLM." readme = "README.md" license = "Apache-2.0" diff --git a/scripts/check_release_readiness.py b/scripts/check_release_readiness.py index b175b366..d6feff82 100644 --- a/scripts/check_release_readiness.py +++ b/scripts/check_release_readiness.py @@ -10,7 +10,9 @@ import hashlib import json import math +import os import re +import stat import subprocess from datetime import datetime, timedelta, timezone from pathlib import Path @@ -30,6 +32,51 @@ _HASH = re.compile(r"[a-f0-9]{64}\Z") _COMMIT = re.compile(r"[a-f0-9]{40}\Z") _MAX_BYTES = 8 * 1024 * 1024 +_EXECUTABLE_SUFFIXES = frozenset({ + # Source files are included because an ignored module such as + # ``sitecustomize.py`` executes before the candidate package and can alter + # imports even when the tracked tree is clean. + ".bat", ".cjs", ".cmd", ".css", ".dll", ".dylib", ".exe", ".html", + ".egg", ".js", ".jsx", ".mjs", ".node", ".pth", ".ps1", ".pyd", ".py", + ".pyc", ".pyo", ".pyw", ".sh", ".so", ".ts", ".tsx", ".whl", ".zip", +}) +_IGNORED_RUNTIME_DIRS = frozenset({ + ".codex-pytest-tmp", ".hosted-eval-results", ".playwright", ".private-eval", + ".pytest_cache", ".release-full-tmp", ".ruff_cache", ".secrets", ".venv", + "build", "dist", "models_cache", "node_modules", "playwright-report", + "test-results", "venv", +}) +_IGNORED_RUNTIME_ENTRYPOINTS = frozenset({ + "__init__.py", "__main__.py", "sitecustomize.py", "usercustomize.py", +}) + + +def _is_ignored_runtime_artifact(root: Path, relative: Path) -> bool: + """Return whether an ignored path can execute or affect imports.""" + if relative.suffix.lower() in _EXECUTABLE_SUFFIXES: + return True + path = root / relative + try: + if path.is_symlink(): + return True + mode = path.stat().st_mode + if mode & (stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH): + return True + with path.open("rb") as source: + return source.read(2) == b"#!" + except OSError: + # An unreadable ignored artifact cannot be proven harmless. + return True + + +def _is_ignored_runtime_entrypoint(relative: Path) -> bool: + """Return whether an excluded directory contains a top-level import hook.""" + parts = relative.parts + return ( + len(parts) == 2 + and parts[0].lower() in _IGNORED_RUNTIME_DIRS + and parts[1].lower() in _IGNORED_RUNTIME_ENTRYPOINTS + ) def canonical_bytes(value: Any) -> bytes: @@ -73,6 +120,36 @@ def _decode_json(payload: bytes) -> Any: ValueError("non-finite JSON number"))) +def _ignored_executable_paths(root: Path) -> list[str]: + """Return ignored executable artifacts that can affect a source checkout. + + ``git status`` deliberately hides ignored files. Release qualification may + import source from the checkout, so an ignored source, bytecode, native + artifact or runtime script can change behavior even when the tracked tree + is clean. Standard tool/runtime directories are excluded because they are + not candidate source paths; all matching artifacts elsewhere fail closed, + including bytecode under ``__pycache__``. + """ + ignored = subprocess.check_output( + ["git", "ls-files", "--others", "--ignored", "--exclude-standard", "-z"], + cwd=root, stderr=subprocess.DEVNULL, + ) + suspicious: list[str] = [] + for entry in ignored.split(b"\0"): + if not entry: + continue + relative = Path(os.fsdecode(entry)) + if _is_ignored_runtime_entrypoint(relative): + suspicious.append(relative.as_posix()) + continue + parts = {part.lower() for part in relative.parts} + if parts & _IGNORED_RUNTIME_DIRS: + continue + if _is_ignored_runtime_artifact(root, relative): + suspicious.append(relative.as_posix()) + return suspicious + + def new_ledger(components: dict) -> dict: """Create an explicitly incomplete ledger; this does not run any gate.""" return { @@ -359,10 +436,16 @@ def visit(name: str, active: set[str], complete: set[str]) -> bool: cwd=engine_root, stderr=subprocess.DEVNULL) hidden = any(entry[:1].islower() or entry[:1] == b"S" for entry in indexed.split(b"\0") if entry) + ignored_executables = _ignored_executable_paths(engine_root) engine_identity = components.get("engine") if (not isinstance(engine_identity, dict) - or actual != engine_identity.get("commit") or dirty or hidden): - errors.append("engine checkout must be clean and match the candidate commit") + or actual != engine_identity.get("commit") or dirty or hidden + or ignored_executables): + if ignored_executables: + errors.append("engine checkout contains ignored executable artifacts: " + + ", ".join(ignored_executables[:8])) + else: + errors.append("engine checkout must be clean and match the candidate commit") else: engine_verified = True except (OSError, subprocess.CalledProcessError): diff --git a/tests/e2e/ask-home.spec.js b/tests/e2e/ask-home.spec.js index e8bf6a3a..90ecd82f 100644 --- a/tests/e2e/ask-home.spec.js +++ b/tests/e2e/ask-home.spec.js @@ -18,7 +18,7 @@ async function fixture(page, { coverage, answerFailures = 0, previewFailures = 0 const body = req.method() === 'POST' ? req.postDataJSON() : null; requests.push({ path, body, query: Object.fromEntries(url.searchParams) }); const ok = json => route.fulfill({ json }); - if (path === '/bootstrap') return ok({ version: '1.7.1', workspaces: [{ name: 'home-work', memories: 12 }], license: { plan: 'local', features: [], known_features: {} } }); + if (path === '/bootstrap') return ok({ version: '1.7.4', workspaces: [{ name: 'home-work', memories: 12 }], license: { plan: 'local', features: [], known_features: {} } }); if (path === '/repos') return ok({ repos: [{ id: 'repo_alpha', name: 'alpha' }, { id: 'repo_beta', name: 'beta' }] }); if (path === '/stats') return statsUnavailable ? route.fulfill({ status: 503, json: { detail: 'Stats unavailable' } }) : ok({ memories: 12, total_rows: 15, sessions: 3, workspaces: 1, by_type: { semantic: 12 } }); if (path === '/memories') return ok({ memories: [], count: 0, total_count: 0, next_cursor: null }); diff --git a/tests/e2e/memory-workflow.spec.js b/tests/e2e/memory-workflow.spec.js index f4100581..cffc07d4 100644 --- a/tests/e2e/memory-workflow.spec.js +++ b/tests/e2e/memory-workflow.spec.js @@ -22,7 +22,7 @@ async function workflowFixture(page, { projectsUnavailable = false, delayProject requests.push({ path, query: Object.fromEntries(url.searchParams), body }); const ok = payload => route.fulfill({ contentType: 'application/json', body: JSON.stringify(payload) }); if (path === '/bootstrap') return ok({ - version: '1.7.1', workspaces: [{ name: 'work-one', memories: 2 }, { name: 'work-two', memories: 0 }], + version: '1.7.4', workspaces: [{ name: 'work-one', memories: 2 }, { name: 'work-two', memories: 0 }], license: { plan: 'local', features: [], known_features: {}, trial: { used: false, trial_days: 3 } }, embedder: { semantic: true }, }); diff --git a/tests/test_benchmark_evidence.py b/tests/test_benchmark_evidence.py index 0d3b2486..4d5ef094 100644 --- a/tests/test_benchmark_evidence.py +++ b/tests/test_benchmark_evidence.py @@ -103,7 +103,7 @@ def _committed_evidence() -> dict: ``test_public_numeric_evidence_registry_is_complete_and_live`` with a 0.5% band. """ artifact = json.loads( - (ROOT / "docs" / "benchmark-evidence" / "offline-fixtures-v3.json").read_text( + (ROOT / "docs" / "benchmark-evidence" / "offline-fixtures-v9.json").read_text( encoding="utf-8" ) ) @@ -151,10 +151,10 @@ def test_readme_distinguishes_every_registered_token_context_measurement(): "not an MCP transport response", "must not be added together", "not a storage-reduction claim", - "offline-fixtures-v3.json", + "offline-fixtures-v9.json", "offline-chunking", "offline-performance", - "2d6b4fab9e75edc91d105d49877f9225f28ffe4d366e40a44e931f19cb13f498", + "455fc9d32a236e582a49aaaf9b84f30cae2573dc6ed982f4dd7dd845afcaf24c", "There is no universal memory-count", "python -m eval.vector_scale", 'vector_backend="sqlite-vec"', @@ -288,7 +288,7 @@ def test_example_visual_uses_the_checked_in_offline_fixture_results( } assert "5/5 answerable questions" in visual assert "6/6 off-topic questions" in visual - assert "2d6b4fab9e75edc91d105d49877f9225f28ffe4d366e40a44e931f19cb13f498" in visual + assert "455fc9d32a236e582a49aaaf9b84f30cae2573dc6ed982f4dd7dd845afcaf24c" in visual def test_context_savings_visual_uses_only_registered_measurements(): @@ -358,7 +358,7 @@ def test_context_savings_visual_uses_only_registered_measurements(): for unsupported in ( "Public evidence is checksum-bound", - "offline-fixtures-v3.json", + "offline-fixtures-v9.json", "No external or model-dependent number is published without the same evidence", "Evidence pending", "No external or model-dependent number is published", @@ -386,12 +386,12 @@ def test_public_numeric_evidence_registry_is_complete_and_live( ): """Every retained public aggregate resolves to one checksum-bound live run.""" artifact_path = ( - ROOT / "docs" / "benchmark-evidence" / "offline-fixtures-v3.json" + ROOT / "docs" / "benchmark-evidence" / "offline-fixtures-v9.json" ) sidecar_path = artifact_path.with_suffix(".json.sha256") artifact_bytes = artifact_path.read_bytes() artifact_sha = hashlib.sha256(artifact_bytes).hexdigest() - expected_sha = "2d6b4fab9e75edc91d105d49877f9225f28ffe4d366e40a44e931f19cb13f498" + expected_sha = "455fc9d32a236e582a49aaaf9b84f30cae2573dc6ed982f4dd7dd845afcaf24c" assert artifact_sha == expected_sha assert sidecar_path.read_text(encoding="ascii") == ( diff --git a/tests/test_consolidate.py b/tests/test_consolidate.py index aef77f94..97ae3ac1 100644 --- a/tests/test_consolidate.py +++ b/tests/test_consolidate.py @@ -6,7 +6,7 @@ import pytest -from engraphis.core.consolidate import _cluster_by_subject, consolidate +from engraphis.core.consolidate import _build_digest_content, _cluster_by_subject, consolidate from engraphis.core.engine import MemoryEngine from engraphis.core.interfaces import MemoryRecord, MemoryType, Scope, SearchFilter from engraphis.service import MemoryService, ValidationError @@ -716,6 +716,16 @@ def test_consolidate_reports_compaction_savings_on_a_real_cluster(): assert report["compaction"]["total_tokens_saved"] >= comp["tokens_saved"] +def test_digest_compaction_is_stable_for_equivalent_cluster_order(): + eng, wid, rid = _engine_with_large_cluster() + flt = SearchFilter(workspace_id=wid, repo_id=rid, mtypes=[MemoryType.EPISODIC]) + cluster = eng.store.list_memories_page(flt) + forward, *_ = _build_digest_content(cluster, llm=None) + reverse, *_ = _build_digest_content(list(reversed(cluster)), llm=None) + + assert forward == reverse + + def test_consolidate_archive_reports_freed_tokens(): eng = MemoryEngine.create(":memory:") wid = eng.store.get_or_create_workspace("w") @@ -2583,4 +2593,4 @@ def test_profiles_dry_run_produces_zero_database_writes(): ).fetchone()[0] assert after_memories == before_memories assert after_links == before_links - assert after_entities == before_entities \ No newline at end of file + assert after_entities == before_entities diff --git a/tests/test_core_ids.py b/tests/test_core_ids.py index 82b95920..5dc22735 100644 --- a/tests/test_core_ids.py +++ b/tests/test_core_ids.py @@ -21,6 +21,27 @@ def test_ulid_is_time_sortable(): assert early < late +def test_ulids_are_monotonic_within_one_timestamp(): + values = [ids.ulid(timestamp_ms=42_000) for _ in range(4)] + assert values == sorted(values) + + +def test_ulid_sequence_resets_when_process_id_changes(monkeypatch): + random_values = iter((100, 200)) + process_id = 1000 + monkeypatch.setattr(ids.os, "getpid", lambda: process_id) + monkeypatch.setattr(ids.secrets, "randbits", lambda _: next(random_values)) + + first = ids.ulid(timestamp_ms=42_000) + second = ids.ulid(timestamp_ms=42_000) + process_id = 1001 + third = ids.ulid(timestamp_ms=42_000) + + assert first.endswith(ids._encode(100, 16)) + assert second.endswith(ids._encode(101, 16)) + assert third.endswith(ids._encode(200, 16)) + + _CROCKFORD = { char: index for index, char in enumerate("0123456789ABCDEFGHJKMNPQRSTVWXYZ") } diff --git a/tests/test_mcp_server.py b/tests/test_mcp_server.py index f2934572..3884945d 100644 --- a/tests/test_mcp_server.py +++ b/tests/test_mcp_server.py @@ -562,7 +562,7 @@ def test_mcp_server_module_entrypoint_runs_stdio_handshake(tmp_path): "ENGRAPHIS_EXTRACTOR": "none", "ENGRAPHIS_GRAPH_EXTRACTOR": "none", "ENGRAPHIS_VECTOR_BACKEND": "numpy", - "ENGRAPHIS_MCP_WARMUP": "0", + "ENGRAPHIS_MCP_WARMUP": "1", }) result = subprocess.run( [sys.executable, "-m", "engraphis.mcp_server"], @@ -624,7 +624,7 @@ def test_classic_mcp_entrypoint_preserves_historical_server_identity(tmp_path): "ENGRAPHIS_EXTRACTOR": "none", "ENGRAPHIS_GRAPH_EXTRACTOR": "none", "ENGRAPHIS_VECTOR_BACKEND": "numpy", - "ENGRAPHIS_MCP_WARMUP": "0", + "ENGRAPHIS_MCP_WARMUP": "1", }) result = subprocess.run( [sys.executable, "-m", "engraphis.mcp_classic_cli"], diff --git a/tests/test_product_release_readiness.py b/tests/test_product_release_readiness.py index e7aa2bf4..c5e1f60e 100644 --- a/tests/test_product_release_readiness.py +++ b/tests/test_product_release_readiness.py @@ -1,6 +1,8 @@ """A checklist label cannot bypass missing, stale or contradictory evidence.""" import hashlib +import importlib.util import json +import py_compile import subprocess import pytest @@ -250,6 +252,119 @@ def test_strict_cli_requires_clean_matching_engine(ledger, tmp_path): assert main(args) == 1 +def test_ignored_executable_artifact_cannot_qualify_candidate(ledger, tmp_path): + repository = tmp_path / "ignored-repo" + repository.mkdir() + (repository / ".gitignore").write_text("*.pyc\n", encoding="utf-8") + (repository / "engine.py").write_text("original", encoding="utf-8") + subprocess.run(["git", "init", "--quiet", str(repository)], check=True) + subprocess.run(["git", "add", ".gitignore", "engine.py"], cwd=repository, check=True) + subprocess.run(["git", "-c", "user.name=Fixture", "-c", "user.email=fixture@example.invalid", + "commit", "--quiet", "-m", "fixture"], cwd=repository, check=True) + ledger["components"]["engine"]["commit"] = subprocess.check_output( + ["git", "rev-parse", "HEAD"], cwd=repository, text=True).strip() + ledger["candidate_id"] = candidate_id(ledger["components"]) + for name in RELEASE_GATES: + pass_gate(ledger, tmp_path, name) + (repository / "ignored.pyc").write_bytes(b"not executable Python bytecode") + result = validate(ledger, tmp_path, engine_root=repository) + assert not result["engine_checkout_verified"] + assert any("ignored executable artifacts" in error for error in result["errors"]) + assert not result["valid"] + + +def test_ignored_importable_source_cannot_qualify_candidate(ledger, tmp_path): + repository = tmp_path / "ignored-source-repo" + repository.mkdir() + (repository / ".gitignore").write_text("sitecustomize.py\n", encoding="utf-8") + (repository / "engine.py").write_text("original", encoding="utf-8") + subprocess.run(["git", "init", "--quiet", str(repository)], check=True) + subprocess.run(["git", "add", ".gitignore", "engine.py"], cwd=repository, check=True) + subprocess.run(["git", "-c", "user.name=Fixture", "-c", "user.email=fixture@example.invalid", + "commit", "--quiet", "-m", "fixture"], cwd=repository, check=True) + ledger["components"]["engine"]["commit"] = subprocess.check_output( + ["git", "rev-parse", "HEAD"], cwd=repository, text=True).strip() + ledger["candidate_id"] = candidate_id(ledger["components"]) + for name in RELEASE_GATES: + pass_gate(ledger, tmp_path, name) + (repository / "sitecustomize.py").write_text("raise RuntimeError('ignored')\n", encoding="utf-8") + result = validate(ledger, tmp_path, engine_root=repository) + assert not result["engine_checkout_verified"] + assert any("sitecustomize.py" in error for error in result["errors"]) + assert not result["valid"] + + +def test_unchecked_hash_bytecode_cannot_qualify_candidate(ledger, tmp_path): + repository = tmp_path / "unchecked-bytecode-repo" + repository.mkdir() + (repository / ".gitignore").write_text("__pycache__/\n", encoding="utf-8") + source = repository / "engine.py" + source.write_text("value = 'tracked'\n", encoding="utf-8") + subprocess.run(["git", "init", "--quiet", str(repository)], check=True) + subprocess.run(["git", "add", ".gitignore", "engine.py"], cwd=repository, check=True) + subprocess.run(["git", "-c", "user.name=Fixture", "-c", "user.email=fixture@example.invalid", + "commit", "--quiet", "-m", "fixture"], cwd=repository, check=True) + ledger["components"]["engine"]["commit"] = subprocess.check_output( + ["git", "rev-parse", "HEAD"], cwd=repository, text=True).strip() + ledger["candidate_id"] = candidate_id(ledger["components"]) + for name in RELEASE_GATES: + pass_gate(ledger, tmp_path, name) + py_compile.compile( + str(source), + cfile=importlib.util.cache_from_source(str(source)), + doraise=True, + invalidation_mode=py_compile.PycInvalidationMode.UNCHECKED_HASH, + ) + result = validate(ledger, tmp_path, engine_root=repository) + assert not result["engine_checkout_verified"] + assert any("__pycache__" in error for error in result["errors"]) + assert not result["valid"] + + +def test_extensionless_ignored_script_cannot_qualify_candidate(ledger, tmp_path): + repository = tmp_path / "extensionless-script-repo" + repository.mkdir() + (repository / ".gitignore").write_text("release-helper\n", encoding="utf-8") + (repository / "engine.py").write_text("original", encoding="utf-8") + subprocess.run(["git", "init", "--quiet", str(repository)], check=True) + subprocess.run(["git", "add", ".gitignore", "engine.py"], cwd=repository, check=True) + subprocess.run(["git", "-c", "user.name=Fixture", "-c", "user.email=fixture@example.invalid", + "commit", "--quiet", "-m", "fixture"], cwd=repository, check=True) + ledger["components"]["engine"]["commit"] = subprocess.check_output( + ["git", "rev-parse", "HEAD"], cwd=repository, text=True).strip() + ledger["candidate_id"] = candidate_id(ledger["components"]) + for name in RELEASE_GATES: + pass_gate(ledger, tmp_path, name) + (repository / "release-helper").write_text("#!/bin/sh\necho ignored\n", encoding="utf-8") + result = validate(ledger, tmp_path, engine_root=repository) + assert not result["engine_checkout_verified"] + assert any("release-helper" in error for error in result["errors"]) + assert not result["valid"] + + +def test_ignored_build_entrypoint_cannot_qualify_candidate(ledger, tmp_path): + repository = tmp_path / "ignored-build-repo" + repository.mkdir() + (repository / ".gitignore").write_text("build/\n", encoding="utf-8") + (repository / "engine.py").write_text("original", encoding="utf-8") + subprocess.run(["git", "init", "--quiet", str(repository)], check=True) + subprocess.run(["git", "add", ".gitignore", "engine.py"], cwd=repository, check=True) + subprocess.run(["git", "-c", "user.name=Fixture", "-c", "user.email=fixture@example.invalid", + "commit", "--quiet", "-m", "fixture"], cwd=repository, check=True) + ledger["components"]["engine"]["commit"] = subprocess.check_output( + ["git", "rev-parse", "HEAD"], cwd=repository, text=True).strip() + ledger["candidate_id"] = candidate_id(ledger["components"]) + for name in RELEASE_GATES: + pass_gate(ledger, tmp_path, name) + build = repository / "build" + build.mkdir() + (build / "__main__.py").write_text("raise RuntimeError('ignored build')\n", encoding="utf-8") + result = validate(ledger, tmp_path, engine_root=repository) + assert not result["engine_checkout_verified"] + assert any("build/__main__.py" in error for error in result["errors"]) + assert not result["valid"] + + @pytest.mark.parametrize("flag", ["--assume-unchanged", "--skip-worktree"]) def test_hidden_git_changes_cannot_qualify_candidate(ledger, tmp_path, flag): repository = tmp_path / "hidden-repo"