The format follows Keep a Changelog and the project adheres to Semantic Versioning.

[Unreleased]

Added

  • Initial extraction as a standalone library.

  • DAG builder with cycle detection (Baton, Baton.DAG).

  • Node-backed state store (workflow_nodes) — no oban_jobs.meta mutation.

  • Worker macros: Baton.Worker, Baton.LLMWorker.

  • Dependency gating, completion-triggered rescheduling, retry idempotency.

  • Multi-model fan-out + synthesis (Baton.MultiModel).

  • Baton.Plugin (Oban plugin) for orphan rescue and failure telemetry.

  • Baton.Pricing behaviour + reference implementation.

  • Per-step stats and context-window capture (optional features).

  • Versioned schema via Baton.Migration.

  • Terminal {:workflow_finished, _} PubSub event (and [:baton, :workflow, :finished] telemetry) when a workflow's last step settles, with :completed/:failed outcome and the failed step names (Baton.Completion).

  • Baton.Plugin backstops that notification for workflows that settle without a clean worker return (hard crash / Oban kill).

  • Schema v2: workflow_completions table — an atomic claim guaranteeing the finished notification fires exactly once across the worker and plugin paths.

  • Configurable LLM client for Baton.Debug.call_llm/3 (config :baton, llm_client: ...).

  • Opt-in data retention: Baton.Plugin can prune Baton's own tables (workflow_nodes, workflow_step_stats, workflow_debug_logs, workflow_completions) once their Oban job is pruned, with an optional shorter age cap for workflow_debug_logs (prune: true, debug_log_max_age:). See Baton.Retention.

Changed

Removed

  • Baton.Stats.record_cache_hit (dead code — was never called).

Fixed

  • Baton.LLMWorker no longer injects the Oban Pro-only :kill_timeout option, which made use Baton.LLMWorker fail to compile under Oban OSS. Replaced with a configurable timeout/1 callback (:timeout option, default :infinity).
  • PubSub broadcast failures no longer crash workers — broadcasting is now best-effort over telemetry (Baton.Events).
  • Baton.LLMWorker stores the step result before recording stats and no longer raises on an unexpected llm_usage key, preventing a wasted/repeated LLM call on retry.