# Change Log
All notable changes to this project will be documented in this file.
See [Conventional Commits](Https://conventionalcommits.org) for commit guidelines.
<!-- changelog -->
## [v0.3.0](https://github.com/futhr/ex_maude/compare/v0.2.0...v0.3.0) (2026-06-10)
### Breaking Changes:
* package: stop bundling GPL Maude binaries in the hex tarball by futhr
* port: default to plain pipes with -interactive, PTY opt-in by futhr
### Upgrade notes:
* **Install Maude separately.** The hex package no longer ships Maude
binaries (they are GPL-licensed; the package is MIT). Run
`mix maude.install` once after updating, keep `maude` on your `PATH`,
or set `config :ex_maude, maude_path: "..."`. The tarball shrinks from
~15 MB to ~110 KB.
* **Workers restart after a command timeout.** A timed-out worker is in
an indeterminate state (Maude cannot cancel an in-flight computation),
so all three backends now stop it with `{:shutdown, _}` and the pool
starts a replacement. Worker pids are therefore not stable across
timeouts, and a `[:ex_maude, :server, :timeout]` telemetry event is
followed by a fresh `[:ex_maude, :server, :start]`.
* **Port backend uses pipes by default.** Maude is launched with
`-interactive` over plain pipes — the mode the C-Node and NIF backends
always used. Set `use_pty: true` to restore the `script`/`unbuffer`
wrapper.
* **`verify_safety/3` and `verify_liveness/3` surface real errors.**
Encoding bugs, missing modules, and Maude syntax errors now return
`{:error, _}` instead of being absorbed into `{:ok, :unverified}`;
`:unverified` remains the result for timeouts and an unavailable pool.
* **`Pool.broadcast/2` no longer exits the caller** when a worker is
slow; slow workers yield `{:error, _}` entries in the result list.
`Pool.transaction/2` accepts `:checkout_timeout` (the old `:timeout`
key remains as an alias).
* **`ExMaude.version/0` returns the real interpreter version** (e.g.
`{:ok, "3.5.1"}` from `maude --version`) instead of a placeholder
string, and works without a started pool.
### Features:
* add parse, show_module and list_modules to the ExMaude facade by futhr
* maude: detect the real Maude version by futhr
* add bounded LTL safety and liveness verification by futhr
### Bug Fixes:
* nif: keep building the NIF once a local artifact exists by futhr
* pool: make broadcast survive slow workers and always return them by futhr
* iot: surface encoding and infrastructure bugs from verify functions by futhr
* iot: escape quotes and backslashes when encoding strings by futhr
* parser: accept kind-level sorts in result lines by futhr
* cnode: correlate bridge replies with refs and restart on failure by futhr
* nif: restart worker after native timeout, eof, or io error by futhr
* port: stop poisoned workers on timeout and fail fast at startup by futhr
* check: run the quality tools that deps: [:compiler] silently skipped by futhr
* iot: drop unreachable error clause in build_world by futhr
## [v0.2.0](https://github.com/futhr/ex_maude/compare/v0.1.1...v0.2.0) (2026-05-18)
### Features:
* add `ai-rules.maude` template (`priv/maude/ai-rules.maude`) — second
bundled Maude module alongside `iot-rules.maude`. Targets AI-generated
automation rules over Agents, Capabilities, ToolInvocations, and richer
predicates (capability, budget, jurisdiction, authority). Detects ten
conflict types including tool-call conflict, capability shadowing,
pack-tool composition mismatch, sovereignty violation, authority
escalation, approval-gate bypass, and agent-loop cascade. ~570 lines
of algebraic specification.
* add `ExMaude.AI` Elixir API parallel to `ExMaude.IoT`. Submodules:
- `ExMaude.AI.Encoder` — Elixir term → Maude syntax for ai-rules
- `ExMaude.AI.Validator` — pre-encode rule validation, including
explicit `:unverifiable` returns for `:contains` / `:matches`
regex operators
- `ExMaude.AI.ConflictParser` — Maude output → typed conflict maps,
handling both pairwise (`aiConflict`) and single-rule
(`aiConflictSingle`) constructors
* add `ExMaude.ai_rules_path/0` helper returning the bundled
`ai-rules.maude` path under `priv/`.
* add `[:ex_maude, :ai, :detect_conflicts, :start | :stop]` telemetry
events with `template: :ai_rules` metadata for observability parity
with the IoT path.
* promote `:nif` backend to production grade. The Rust crate now uses a
dedicated reader thread feeding a `crossbeam-channel`, enforces per-command
timeouts via `recv_timeout`, captures both stdout and stderr (matching the
Port backend's `stderr_to_stdout` semantics), and returns structured
errors (`{:timeout, ms}`, `:eof`, `{:io_error, msg}`, `{:lock_poisoned, what}`).
All blocking entry points run on the `DirtyIo` scheduler.
* add `ExMaude.Parser.parse_backend_response/1` as the single source of truth
for turning a Maude command's raw output into `{:ok, value} | {:error, %Error{}}`.
Both the Port and NIF backends now share this parser.
* expose a `nif_loaded/0` probe in the NIF native module — a cheap call used
by `ExMaude.Backend.available?/1` to detect whether Rustler has populated
the native function table.
### Bug Fixes:
* fix `ExMaude.Backend.available?(:nif)` checking the wrong function name
(`:initialize/1` instead of the actual `:start/1`), which made the backend
appear unavailable even when the precompiled binary loaded correctly.
* fix `ExMaude.Backend.NIF` no longer falling back into a "stub mode" when
the NIF fails to load — the GenServer now refuses to start and surfaces
a clear `:nif_not_loaded` error pointing at the `EX_MAUDE_BUILD=1`
escape hatch.
* fix `:not_implemented` error type removed; replaced by `:nif_not_loaded`
and `:nif_error` for genuine NIF failure modes.
## [v0.1.1](https://github.com/futhr/ex_maude/compare/v0.1.0...v0.1.1) (2026-04-07)
### Bug Fixes:
* align NIF precompiled build config with production patterns by Tobias Bohwalli
* switch NIF to RustlerPrecompiled for proper Hex packaging by Tobias Bohwalli
## [v0.1.0](https://github.com/futhr/ex_maude/compare/v0.1.0...v0.1.0) (2026-04-03)
### Features:
* add Livebook notebooks for interactive documentation by Tobias Bohwalli
* add bundled Maude binaries and IoT rules module by Tobias Bohwalli
* add NIF backend stub with Rustler scaffolding by Tobias Bohwalli
* add C-Node backend with maude_bridge by Tobias Bohwalli
* add mix maude.install task for binary installation by Tobias Bohwalli
* add IoT rule conflict detection module by Tobias Bohwalli
* add Maude binary management, server, pool, and public API by Tobias Bohwalli
* add backend behaviour and Port backend implementation by Tobias Bohwalli
* add parser and telemetry modules by Tobias Bohwalli
* add core types (Error, Term, Result structs) by Tobias Bohwalli
### Bug Fixes:
* remove HTML div wrapper and pre-release notice for hex.pm rendering by Tobias Bohwalli
* suppress noisy make output when binary is up-to-date by Tobias Bohwalli
* handle missing Location header in redirect safely by Tobias Bohwalli
* tighten encoder specs to resolve dialyzer contract_supertype warning by Tobias Bohwalli
* make CNode backend fully functional by Tobias Bohwalli
* split telemetry tests to use MaudeCase for integration tests by Tobias Bohwalli
* handle write() return values in maude_bridge.c by Tobias Bohwalli
* add ex_doc and doctor to test env for CI by Tobias Bohwalli
* suppress unused alias warnings in conditional test blocks by Tobias Bohwalli
* replace deprecated Exception.exception?/1 with is_exception/1 by Tobias Bohwalli
* convert @platform_patterns to function for compile-time compatibility by Tobias Bohwalli
### Performance Improvements:
* add benchmark suite by Tobias Bohwalli