# Changelog

All notable changes to this project will be documented in this file.

Format based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).

## 0.2.0

### Added

- **`osentinel init -q`**: Quick (non-interactive) init — auto-detects your API key and writes a minimal config in one shot.
- **CLI output formatting**: Rich-formatted console output for all CLI commands (headings, YAML previews, success/error indicators).
- **Model auto-detection**: Automatically resolves the best LLM model from whichever API key is present (`OPENAI_API_KEY` → `gpt-4o-mini`, `GEMINI_API_KEY` → `gemini/gemini-2.5-flash`, etc.).
- **Model & API-key validation**: `osentinel serve` and `osentinel init` now validate that the required API key exists for the configured model before starting.
- **YAML as single source of truth**: `osentinel.yaml` is now the primary configuration surface. Removed the `OSNTL_*` environment-variable prefix; API keys are still read from env vars / `.env`.
- **Path resolution**: Relative paths in `osentinel.yaml` (e.g. `policy: ./workflow.yaml`) are resolved relative to the config file location.
- **Config validation at startup**: `osentinel serve` checks that referenced policy files exist and that the required API key is present; exits with a clear error if not.
- **API-key syncing**: Keys loaded from `.env` are synced into `os.environ` so downstream libraries (LiteLLM, LangChain) work without explicit `load_dotenv()`.
- **Langfuse env-var aliases**: `LANGFUSE_PUBLIC_KEY`, `LANGFUSE_SECRET_KEY`, and `LANGFUSE_HOST` are read directly from the environment alongside YAML config.
- **Engine-specific `osentinel compile`**: The policy compiler now accepts `--engine` to target a specific engine format (judge, fsm, llm, nemo).
- **`docs/configuration.md`**: Full configuration reference for `osentinel.yaml`.

### Changed

- **Default engine** changed from `nemo` to `judge` — works out of the box with inline rules; no external config directory required.
- **Tracing disabled by default**: `tracing.enabled` now defaults to `false` and `exporter_type` defaults to `none` to avoid noisy OTLP connection errors on first run.
- **`proxy.default_model`** defaults to `None` instead of eagerly auto-detecting; the model is resolved at startup via YAML or auto-detection.
- **Intervention merge logic** refactored for consistency across FSM and LLM engines.
- **Policy compiler** refactored into per-engine modules (`fsm`, `llm`, `judge`, `nemo`).
- **Docs updated**: `developing.md`, `examples/README.md`, and `README.md` updated to reflect YAML-first configuration.

### Fixed

- Judge engine: score clamping, criterion failure checks, JSON validation, timezone-aware timestamps.
- Session ID propagation for internal LLM calls in the Judge engine.
- `intervention` and `classifier` YAML sections now correctly map to `SentinelSettings`.

## 0.1.0 (alpha)

Initial release.

### Added

- Transparent LLM proxy built on LiteLLM. Point any OpenAI-compatible client at it with a one-line `base_url` change.
- **Judge engine**: scores responses against plain-English rubrics using a sidecar LLM. Three reliability modes (safe/balanced/aggressive). Async by default -- zero latency on the critical path.
- **FSM engine**: enforces agent behavior as a finite state machine. Three-tier classification cascade (tool call matching, regex, embedding similarity). LTL-lite temporal constraint evaluation.
- **LLM engine**: classifies conversation state and detects drift using LLM-based reasoning.
- **NeMo engine**: integrates NVIDIA NeMo Guardrails for content safety and dialog rails.
- **Composite engine**: runs multiple engines in parallel, merges results (most restrictive wins).
- **Policy compiler**: translates natural language policies to engine-specific YAML via `osentinel compile`.
- **CLI**: `osentinel init`, `osentinel serve`, `osentinel compile`, `osentinel validate`, `osentinel info`.
- **OpenTelemetry tracing**: spans for every proxy call, policy evaluation, and intervention. Console, OTLP, and Langfuse backends.
- Fail-open design: hook failures pass the request through unmodified. Only intentional blocks propagate.
- Deferred intervention: violations detected async are applied as prompt injections on the next turn.
- Session ID extraction from headers, query params, or request body.

### Known Limitations

- Session state is in-memory only. Not persistent across restarts.
- No dashboard UI.
- No pre-built policy library.
- No rate limiting.
