Changelog

View Source

All notable changes to lemon_core are documented here. The format follows Keep a Changelog; releases follow Semantic Versioning from 0.1.0 onward.

[Unreleased]

First release as a standalone package. lemon_core used to be the umbrella's catch-all shared app; this release turns it into a library you can embed. The theme of every change below is the same: nothing in lemon_core knows about Telegram, run history, durable memory, kanban boards, or ~/.lemon.

Added

  • LemonCore.Store can run as many named instances as you like. Configuration comes from start_link/1 options first and application environment second, so an embedding application no longer has to write into :lemon_core's app env to configure a store it owns.
  • LemonCore.Store.Hooks — the extension point that replaced hardcoded calls in finalize_run/2. Collaborators register {module, function, args} hooks (kept in :persistent_term, so they survive a store restart) and failures in one hook are isolated from the run and from other hooks. Reads invert the same way through a configurable :run_history_provider.
  • LemonCore.Secrets.KeyProvider — a behaviour with keychain, environment and file providers built in, and a configurable chain. Non-macOS hosts now have a first-class provisioning path (mix lemon.secrets.init, writing a 0600 key file) instead of a macOS-Keychain-only one.
  • LemonCore.Paths — every filesystem location the library uses is resolved through one configurable module. The ~/.lemon defaults are now the reference runtime's configuration rather than baked-in library behaviour.
  • LemonCore.Env.Registry — environment variables are declared by the package that reads them and aggregated here through :env_registries. Registries that are not loaded are skipped, so the aggregate always describes what your build can actually read.
  • LemonCore.EngineInfoBridge — a configured-implementation bridge (the same shape as RouterBridge, pointed the other way) that answers engine-registry, transport-registry and gateway-config questions with a documented degraded answer when no implementation is registered.
  • LemonCore.Doctor.RuntimeModules and the :doctor_checks config key: any application can register its own diagnostics instead of lemon_core naming foreign modules.
  • LemonCore.UUID — a vendored UUIDv7 generator.

Changed

  • :exqlite, :sentry, :finch, :phoenix_pubsub and :file_system are now optional dependencies. Embedding lemon_core no longer drags in a SQLite NIF, an HTTP client, an error reporter and a pubsub server. Each one degrades explicitly and audibly: the bus falls back to a local Registry, the store falls back to ETS, the config reloader polls, and the Sentry handler is skipped. Detection happens at runtime, not compile time, so the same build works with or without them.
  • LemonCore.Store.ReadCache uses per-store ETS table sets held by reference. Two differently-named stores can now run in one node without silently sharing a cache; a genuine collision raises CollisionError instead of failing open.
  • :inets and :ssl are declared applications (they back LemonCore.Httpc), which fixes a half-loaded httpc in pruned builds.
  • Cached store tables are per-instance options plus register_cached_table/1, rather than a fixed list containing channel-specific tables.

Removed

  • LemonCore.Memory* — the eight durable-memory modules moved to the new lemon_memory package as LemonMemory.*. The app env key moved with them, from :lemon_core, LemonCore.MemoryStore to :lemon_memory, LemonMemory.Store.
  • LemonCore.GoalStore, KanbanStore and HeartbeatStore — moved to lemon_agent as LemonAgent.Workspace.*.
  • LemonCore.ProviderPoolRotator and ProviderConfigResolver — moved to their single consumers (coding_agent and lemon_agent respectively).
  • Weak raw master keys are rejected with :weak_master_key rather than being silently stretched; allow_legacy_raw_keys: true is the deprecation escape hatch. Stretching would have quietly broken existing ciphertexts.

Known gaps

  • Secrets key rotation and re-encryption are not implemented; the gap is documented in LemonCore.Secrets's moduledoc.