All notable changes to this project are documented here. This project adheres to Semantic Versioning.
[Unreleased]
[0.1.4] — 2026-10-05
Added
- Text-body documents in
retain_files. A file given as%{"text" => body}(or a bare binary) is retained as-is by a dedicated text converter, bypassing the configured converter and never reading a"path". This is the shape a Hindsight migration carries by construction. Without a"document_id"or"filename"the document gets a content-addressed id (text:<sha256>), so single-file calls cannot collide onfile-0. Pass"request" => %{"async" => false}for a synchronous write. Request options are read with string keys; atom keys are ignored. - Blank text bodies are rejected, not silently dropped: retain discards items with no alphanumeric content, which would make a blank document vanish from a copy without trace.
update_modepassthrough onretain_files(per file or in"request"). Re-retaining adocument_idupserts the document but, by default, appends a second set of memory units."update_mode" => "replace"deletes the prior set but also rebuilds every entity in the bank on each call, so it is opt-in only; bulk copies should rely on their own once-only ledger. Large text bodies are retained as a single unchunked memory unit: pre-chunk them.
Documentation
config :foresight, backend:is now documented in the getting-started guide, whose "working configuration" omitted it and so left new consumers on the Noop backend. Usebackend: Foresight.Backend.Store;storage: Foresight.Storage.Ectobelongs underengine:and lacksretain_files/3as a backend.
Fixed
update_mode: "replace"raised on any document that already had memory units (Postgrex expected a binary of 16 bytesinaffected_observation_ids): the source-unit id array is now bound with an explicit{:array, Ecto.UUID}type. The path had no Postgres coverage before.update_mode: "replace"now releases sibling units for reconsolidation. Units that fed an observation deleted by the replace were left marked consolidated; they are reset asdelete_documentsalready did.
[0.1.3] — 2026-09-28
Changed
- Trademark acknowledgment in the README. Upstream Hindsight now carries
a claimed trademark mark alongside a commercial cloud offering. Foresight
is an independent port and is not affiliated with, endorsed by, or
sponsored by Vectorize AI, Inc.; references to Hindsight serve attribution
(the MIT notice in
LICENSE, unchanged since 0.1.0) and interoperability description only. No code changes.
[0.1.2] — 2026-09-28
Fixed
Foresight.Migrations.install/2no longer collides across BEAMs. The scratch directory used to materialize control-plane migrations was named withSystem.unique_integer/1, which is unique only within a single BEAM. Two VMs sharing aTMPDIR— a release beside a migration task, concurrent cold boots, CI jobs on a shared volume — could land on the same path and silently load each other's partial link trees. Scratch directories are now allocated under cryptographically random names with an exclusivemkdir(retried on the astronomically unlikely collision), partial link trees are removed on failure, and stale directories left by another BEAM are ignored.
[0.1.1] — 2026-09-27
Added
Foresight.Migrations.install/2, an idempotent in-BEAM installer for packaged control-plane migrations using the collision-safeforesight_schema_migrationsledger.Foresight.Tenancy.provision_mode_c_schema/4, the supported role-neutral consumer seam for installing the control plane and provisioning a tenant schema without creating roles or tenant keys.- An exhaustive packaged-migration classification manifest.
- Automatic adoption of structurally verified 0.1.0 control-plane migrations into the dedicated Foresight ledger.
Fixed
- Explicit per-call
rls_enabled: falsenow reaches every Ecto tenant scope, parallel recall strategy, nested reflect helper, and applicable async worker instead of being replaced by the application default. - Tenant webhook discovery and delivery creation now execute inside the same RLS scope as the operation that emitted them.
[0.1.0] — 2026-09-07
Initial public release, published as foresight_memory.
Foresight is an Elixir port of Hindsight (MIT, Vectorize AI, Inc.). The ported architecture is theirs and is attributed in the README (Provenance) and the LICENSE (third-party notice); divergence from it is documented where introduced. Everything below predates the first publish and is part of the 0.1.0 story.
Changed
- Recall fusion now defaults to
:normalized/:zscore(was:rrf/:min_max). Measured over 134 graded-relevance queries: +0.1009 nDCG@10, 95% CI [0.0597, 0.1476], and MRR 0.776 → 0.903.:rrfmerges on rank position and discards the arm scores; normalizing keeps them. Existing banks with an explicitrecall_fusionoverride are unaffected. - Default reranker is now
Rerankers.Passthrough(wasRerankers.Bumblebee). The old default made a bare install demand the Nx/Bumblebee/EXLA stack and fail its capability preflight, so Foresight could not boot without ML dependencies nobody had asked for.
Fixed
- Foresight is installable.
:plugand:llm_corewere declaredoptional: truewhile being referenced unconditionally at compile time, so{:foresight, "~> 0.1"}on its own failedmix compile.:plugand the new direct:llm_toolkitare now required;:llm_coreremains optional and its adapter is guarded, with a stub that names the missing dependency. - Recall trace reports the fusion algorithm actually in use. It was hardcoded
to
"rrf"and reported the wrong algorithm on every request once the default changed. - MCP:
async_processingaccepted as an alias forasync; fabricated lenient sessions are closed at the end of the request that created them; undeclared tool arguments are named in the log instead of being dropped. - Enqueueing without Oban returns a structured
:unavailableerror instead of raising. - Scrivener ingestion: path traversal via an unvalidated bundle UUID, escape via symlinked path components, and unbounded reads from non-regular files are all closed.
Security
- Mode C schema-per-tenant isolation verified under a genuine least-privilege
role (
rolsuper = false, RLS forced): five forged-header cross-tenant attacks, 5/5 blocked, verified by canary rather than status code.
[0.1.0]
Initial development version.