@@ -116,21 +116,21 @@ Public 1.1.0 hosted-connect and graph-experience release.
116116
117117### Added
118118
119- - ** ` engraphis connect --token engr_ct_… ` ** — the missing client half of device connect.
119+ - ** ` engraphis connect --token engr_ct_… ` ** : the missing client half of device connect.
120120 ` cloud_session.save_bootstrap() ` is the only writer of ` ~/.engraphis/cloud_session.json ` ,
121121 and it had no production caller: the docs told paying customers to prefer a file nothing
122122 created, so a purchased installation could not be connected without hand-writing state.
123123 The new command redeems the one-time connect token from the account portal against
124124 ` POST /v1/devices/connect ` , saves the returned session with owner-only permissions, and
125125 verifies ` cloud_session.configured() ` before reporting success. The token is sent in the
126- request body and nowhere else — never printed, logged, or written to disk — and every
126+ request body and nowhere else; it is never printed, logged, or written to disk, and every
127127 refusal maps to fixed, actionable copy (an expired or already-used token is not confused
128128 with a lapsed subscription). Session storage is pre-flighted before the exchange, so an
129129 unwritable state directory or a ` cloud_session.json ` replaced by a link fails the command
130- * without* spending the single-use token — the customer fixes the path and retries with the
130+ * without* spending the single-use token; the customer fixes the path and retries with the
131131 same token instead of returning to the portal for a new one. Faults that can only happen
132- * after* the exchange — a reply truncated mid-body (` http.client.IncompleteRead ` ), or an
133- endpoint that stops resolving before the session is written (` CloudUrlUnresolved ` ) — are
132+ * after* the exchange: a reply truncated mid-body (` http.client.IncompleteRead ` ), or an
133+ endpoint that stops resolving before the session is written (` CloudUrlUnresolved ` ) are
134134 reported as errors that say the token was already used, rather than escaping as tracebacks
135135 that leave the customer unable to tell whether to retry. Also installed as
136136 ` engraphis-connect ` .
@@ -328,7 +328,7 @@ and safe hosted deployment.
328328
329329### Security
330330
331- - Every entrypoint sends baseline response headers — CSP, ` X-Frame-Options: DENY ` ,
331+ - Every entrypoint sends baseline response headers: CSP, ` X-Frame-Options: DENY ` ,
332332 ` X-Content-Type-Options ` , ` Referrer-Policy ` , ` Permissions-Policy ` , and HSTS over HTTPS
333333 only. Override with ` ENGRAPHIS_CSP ` / ` ENGRAPHIS_HSTS ` ; set either to an empty string to
334334 omit that header where a fronting proxy supplies its own.
@@ -422,10 +422,10 @@ and safe hosted deployment.
422422 insert sequence (engine-level write lock): concurrent near-duplicate writes can no
423423 longer both resolve ADD and store duplicates instead of NOOP/INVALIDATE.
424424- The Inspector's ` /api/auth/login ` /` setup ` no longer run PBKDF2 (600k iterations)
425- on the asyncio event loop — password hashing moved to a worker thread, so a burst
425+ on the asyncio event loop; password hashing moved to a worker thread, so a burst
426426 of logins can't stall every other request.
427427- A failed vector-index upsert on the write path is now logged and audited
428- (` index_upsert_failed ` ) instead of silently swallowed — previously the memory
428+ (` index_upsert_failed ` ) instead of silently swallowed. Previously, the memory
429429 stayed invisible to semantic recall with no trace.
430430- URLs built from a bind host are now IPv6-safe and connectable (` engraphis.netutil ` ):
431431 ` ENGRAPHIS_HOST=:: ` no longer yields the malformed ` http://:::8700 ` in the printed
@@ -468,7 +468,7 @@ and safe hosted deployment.
468468
469469### Fixed
470470- 1-hop graph recall (and the PPR large-graph fallback) now honors ` graph_layers ` , matching
471- the PPR arm — ` Store.neighbors() ` gained a ` layers ` filter.
471+ the PPR arm: ` Store.neighbors() ` gained a ` layers ` filter.
472472- ` FolderTransport.push() ` no longer follows peer-planted symlinks in the shared sync folder
473473 (unpredictable temp name + ` O_CREAT|O_EXCL|O_NOFOLLOW ` ), closing an arbitrary-file-write
474474 vector that mirrored the already-hardened read side.
@@ -477,7 +477,7 @@ and safe hosted deployment.
477477- Caller-supplied ` metadata.retention_supervision ` is stripped at the service boundary; only
478478 the validated ` retention_class ` presets can influence importance/stability.
479479- ` merge_workspaces() ` no longer duplicates symbols/code edges when both workspaces indexed
480- the same file in a same-named repo — the losing snapshot's rows are cleared, and its
480+ the same file in a same-named repo: the losing snapshot's rows are cleared, and its
481481 memory↔code links are re-pointed at the surviving same-fqname symbols.
482482- ` engraphis-graph impact/prs ` reject leading-dash git revisions (git option injection), and
483483 graph exports refuse a symlinked output directory and are written atomically without
@@ -486,7 +486,7 @@ and safe hosted deployment.
486486 (` limit ` -derived cap) so a large workspace graph or indexed repo can't produce unbounded
487487 viewer-role responses.
488488- Relay sync fails closed when a workspace's settings are unreadable rather than treating a
489- possibly-personal folder as shared — in the sync CLI and in the dashboard/background
489+ possibly-personal folder as shared: in the sync CLI and in the dashboard/background
490490 ` _sync_all ` path; resource extraction enforces its own raw-size cap.
491491
492492## [ 0.9.6] - 2026-07-16
@@ -574,22 +574,22 @@ and safe hosted deployment.
574574### Changed
575575- ** Team mode is now ON by default (opt-out).** ` ENGRAPHIS_TEAM_MODE ` defaults to on;
576576 set ` ENGRAPHIS_TEAM_MODE=0 ` (or false/no/off) to disable. The per-user login wall is
577- no longer raised just because the mode flag is on — it now requires a * live* ` team `
577+ no longer raised just because the mode flag is on. It now requires a * live* ` team `
578578 feature entitlement (` licensing.has_feature("team") ` ), checked at request time in
579579 ` dashboard_app.py ` and reflected in ` /api/auth/state ` . Solo / no-license installs stay
580- fully open, and the wall appears the moment a team license key is added — even via the
580+ fully open, and the wall appears the moment a team license key is added, even via the
581581 dashboard UI at runtime. A ` team ` license is still required to * add seats* beyond the
582582 first admin (bootstrap admin is created unconditionally). Docs (` .env.example ` ,
583583 ` AGENTS.md ` , ` README.md ` , ` SECURITY.md ` , ` scripts/init.py ` ) and team-mode test fixtures
584584 updated.
585585- ** Team-invite email rewritten to separate "join" from "activate a key".** The old
586586 invite conflated the two, so members pasted the shared team key into the hosted/Railway
587587 dashboard, saw it "work" (it just re-activated a license already active there), and
588- thought they'd joined — when joining means signing in with email + password. The email
588+ thought they'd joined, when joining means signing in with email + password. The email
589589 now frames two distinct options: ** Option 1** (required to join) sign in to the team
590- dashboard with email + the admin-set password — explicitly * no license key needed here,
590+ dashboard with email + the admin-set password, with explicitly * no license key needed here,
591591 don't paste one* ; ** Option 2** (optional) run Engraphis on your own machine and access
592- the team's memories locally — that is what the shared team key is for (LOCAL
592+ the team's memories locally; that is what the shared team key is for (LOCAL
593593 ` http://127.0.0.1:8700 ` → Settings → License, then Settings → Cloud Sync to pull the
594594 converged team store down to a local offline copy). Invites now always carry a
595595 clickable sign-in link: ` dashboard_url ` resolves explicit arg → ` ENGRAPHIS_DASHBOARD_URL `
@@ -625,7 +625,7 @@ and safe hosted deployment.
625625- ** The dashboard (` engraphis-dashboard ` / ` http://127.0.0.1:8700 ` ) would not start.**
626626 ` scripts/start_dashboard.py ` runs uvicorn against ` engraphis.dashboard_app:app ` , but
627627 ` dashboard_app.py ` only defined the ` create_app() ` factory and never built a module-level
628- ` app ` instance — so uvicorn aborted with ` Attribute "app" not found ` and nothing bound
628+ ` app ` instance, so uvicorn aborted with ` Attribute "app" not found ` and nothing bound
629629 port 8700. The missing ` app = create_app() ` (present in ` engraphis/app.py ` and
630630 ` engraphis/redirector.py ` , but dropped from ` dashboard_app.py ` ) is now restored. The
631631 background autosync/dreaming/revalidation loops inside ` create_app() ` are pytest-guarded,
@@ -649,7 +649,7 @@ and safe hosted deployment.
649649 ` tests/test_online_only_enforcement.py ` .
650650- ** Deterministic, offline sub-file chunking on the write path (` ENGRAPHIS_EXTRACTOR=chunk ` ).**
651651 A third ` Extractor ` alongside passthrough/LLM: ` ChunkingExtractor ` splits a document into
652- retrieval-sized ` ExtractedFact ` chunks that preserve meaning — markdown headings start new
652+ retrieval-sized ` ExtractedFact ` chunks that preserve meaning: markdown headings start new
653653 chunks and become the title, fenced code blocks stay intact, prose is packed to a token
654654 budget (` ENGRAPHIS_CHUNK_TOKENS ` , default 256) with a sentence-level overlap
655655 (` ENGRAPHIS_CHUNK_OVERLAP ` , default 32); a hard per-document cap
@@ -667,7 +667,7 @@ and safe hosted deployment.
667667- ** Chunking eval + ` longdoc ` dataset.** ` eval/chunking_eval.py ` +
668668 ` eval/datasets/longdoc.jsonl ` compare whole-file vs chunked ingestion through the real
669669 recall pipeline. On the offline embedder: identical recall@5 (1.000) at ** ~ 73% fewer
670- context tokens** (809 → 219) and ~ 4× smaller tokens-to-evidence (162 → 42) — the "quality per token"
670+ context tokens** (809 → 219) and ~ 4× smaller tokens-to-evidence (162 → 42); the "quality per token"
671671 number ` BENCHMARKS.md ` calls for. ` tests/test_chunking_eval.py ` .
672672- ** "Dreaming" trigger for automated maintenance.** ` automation.should_dream ` / ` dream_due `
673673 run a consolidation sweep * before* the cadence when enough new episodic memories have
@@ -676,7 +676,7 @@ and safe hosted deployment.
676676 cron behaviour is unchanged; still Pro-gated. ` tests/test_dreaming_trigger.py ` .
677677- ** Associative cross-cluster inference (dream pass 4).** ` consolidate.infer_links ` /
678678 ` consolidate(infer=True) ` proposes evidence-only links between memories in * different,
679- dissimilar* subject clusters that share a bridging entity — the "connect distant dots" step
679+ dissimilar* subject clusters that share a bridging entity: the "connect distant dots" step
680680 same-subject distillation never reaches. ** Off by default** (` infer=False ` ); the pass
681681 follows the sweep's own ` dry_run ` flag, so a dry-run proposes into the report and a real
682682 run applies. Applied inferences are low-salience (` importance=0.25 ` ), ` trusted:false ` ,
@@ -686,13 +686,13 @@ and safe hosted deployment.
686686 ` rediscovered ` ) and the per-sweep text scan is computed once, not per entity.
687687 ` tests/test_inference.py ` .
688688- ** Inference is reachable from the maintenance path.** A new ` infer ` policy knob (off
689- by default) runs the inference pass inside ` run_maintenance ` — manual * or * the dream loop
690- — following the sweep's ` dry_run ` . ` /api/consolidate ` takes ` infer ` (` false ` by default);
689+ by default) runs the inference pass inside ` run_maintenance ` , whether manual or from the dream loop,
690+ following the sweep's ` dry_run ` . ` /api/consolidate ` takes ` infer ` (` false ` by default);
691691 ` /api/automation ` round-trips ` infer ` ; the dashboard Automation tab has an Inference
692692 toggle. ` tests/test_dashboard_v2.py ` (policy round-trip + ` /maintenance/run ` proposes the
693693 Redis bridge), ` tests/test_dashboard_dream_ui.py ` .
694694- ** Dreaming runs without cron.** A dashboard background loop (` _maybe_start_dreaming ` ,
695- mirroring auto-sync) runs a maintenance sweep whenever ` automation.dream_due ` fires — opt-in,
695+ mirroring auto-sync) runs a maintenance sweep whenever ` automation.dream_due ` fires. It is opt-in,
696696 Pro-gated, fault-isolated, with an ` ENGRAPHIS_DREAM_LOOP=0 ` kill switch. The ` /api/automation `
697697 policy round-trips the ` dream ` / ` dream_min_new ` / ` dream_idle_minutes ` knobs, and the
698698 dashboard's Automation tab surfaces them as form controls (toggle + thresholds). The
@@ -710,7 +710,7 @@ and safe hosted deployment.
710710 instance no longer deadlocks on the team-feature gate with no way to proceed.
711711 No backend change; frontend-only.
712712- ` MemoryService.create ` now defaults ` extractor ` from ` settings.extractor `
713- (` ENGRAPHIS_EXTRACTOR ` ) when unset — mirroring the existing ` graph_extractor ` fallback — so
713+ (` ENGRAPHIS_EXTRACTOR ` ) when unset, mirroring the existing ` graph_extractor ` fallback so
714714 the dashboard and automated-maintenance front ends honor the config knob, not just the MCP
715715 server and CLI. An explicit ` extractor="none" ` still overrides the environment.
716716
@@ -733,12 +733,12 @@ and safe hosted deployment.
733733### Added
734734- ** Personal vs. shared folders + a redesigned Team dashboard.** A folder can now be
735735 created ` visibility='personal' ` (owned by, and visible/usable only to, the creating
736- dashboard user) or ` shared ` (the whole team — the previous, still-default behaviour).
736+ dashboard user) or ` shared ` (the whole team, the previous, still-default behaviour).
737737 Enforcement runs through a single workspace-authorization chokepoint, so every scoped
738738 read/write inherits it and a non-owner cannot access another user's personal folder.
739739 Personal folders are excluded from relay sync so they stay on-device. The ** Team
740740 dashboard** gains a team overview (seat usage + activity), a Folders panel that creates
741- and manages shared/personal folders (folder creation now lives here — the Workspaces
741+ and manages shared/personal folders (folder creation now lives here: the Workspaces
742742 tab is selection-only in team mode), members with last-active, and a team audit log with
743743 CSV export. New/updated: ` service.py ` , ` routes/v2_api.py ` , ` dashboard_app.py ` ,
744744 ` static/index.html ` ; tests in ` tests/test_personal_folders.py ` ,
@@ -761,7 +761,7 @@ and safe hosted deployment.
761761 with auth/license/trial routes instead of a permanently signed-out UI.
762762 ` engraphis-server ` remains available as an explicit override for single-user
763763 deployments.
764- - ** CI** : ruff lint errors and core-floor (numpy-only) test collection —
764+ - ** CI** : ruff lint errors and core-floor (numpy-only) test collection.
765765 fastapi-dependent tests now skip cleanly on the minimal core floor. ` loads_strict `
766766 now rejects pathologically deep JSON on every Python version (3.12's JSON scanner
767767 no longer raises RecursionError for ~ 1000-deep input, which had broken the
@@ -825,14 +825,14 @@ and safe hosted deployment.
825825### Fixed
826826- Static package discovery: ` engraphis/static/__init__.py ` added
827827- Vendor glob: recursive pattern so ` static/vendor/ ` bundles ship in wheel
828- - Dashboard 500 on ` GET / ` — ` static/index.html ` was missing from wheel (packaging bug)
829- - Dashboard 500 on fresh install — ` GET /api/memories ` crashed on empty workspace
828+ - Dashboard 500 on ` GET / ` : ` static/index.html ` was missing from wheel (packaging bug)
829+ - Dashboard 500 on fresh install: ` GET /api/memories ` crashed on empty workspace
830830
831831---
832832
833833## Earlier versions (condensed)
834834
835- ### 0.5.x — 0.7.x
835+ ### Versions 0.5.x to 0.7.x
836836- MCP server with 18 tools
837837- Memory Inspector product UI (` engraphis-inspector ` , port 8710)
838838- Dashboard rebuilt on v2 engine with recall, governance, consolidate, analytics
@@ -846,7 +846,7 @@ and safe hosted deployment.
846846- Docker + docker-compose deployment
847847- 300+ tests, eval harness, ablation suite
848848
849- ### 0.1.0 — 2026-07-09
849+ ### [ 0.1.0] - 2026-07-09
850850- Initial public release: local-first AI memory engine for agents
851851- Ebbinghaus decay, interaction-aware recall, bi-temporal facts
852852- Background consolidation; you bring the LLM
0 commit comments