All notable changes to this project are documented here. This project adheres to Semantic Versioning.

[Unreleased]

[0.1.2] — 2026-09-28

Fixed

  • Foresight.Migrations.install/2 no longer collides across BEAMs. The scratch directory used to materialize control-plane migrations was named with System.unique_integer/1, which is unique only within a single BEAM. Two VMs sharing a TMPDIR — 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 exclusive mkdir (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-safe foresight_schema_migrations ledger.
  • 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: false now 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. :rrf merges on rank position and discards the arm scores; normalizing keeps them. Existing banks with an explicit recall_fusion override are unaffected.
  • Default reranker is now Rerankers.Passthrough (was Rerankers.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. :plug and :llm_core were declared optional: true while being referenced unconditionally at compile time, so {:foresight, "~> 0.1"} on its own failed mix compile. :plug and the new direct :llm_toolkit are now required; :llm_core remains 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_processing accepted as an alias for async; 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 :unavailable error 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.