# Changelog

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

The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## UNRELEASED

### Added

- Optimizations for agentic development (`AGENTS.md`, `.mcp.json`, `llms.txt`, etc.)

## [0.1.0a14](https://github.com/int-brain-lab/bpod-core/releases/tag/0.1.0a14) - 2026-07-24

### Added

- `Bpod` publishes live trial events over the PUB/SUB channel as a tagged union of
  typed messages.
- `RemoteBpod` accepts an `event_callback` that receives each live trial-event
  message.
- `ServiceHost.get_metadata` for accessing per-request connection metadata from within
  a request handler.
- `ServiceHost.publish` for broadcasting events over the PUB/SUB channel;
  `ServiceClient` decodes them per its new `event_type` parameter.
- `ServiceHost` remembers the TCP ports last bound for a caller-supplied `uuid`
  (stored in the user state directory) and reuses them on restart; explicit
  `port_rep` / `port_pub` arguments take precedence.
  `ServiceHost.has_subscribers`: the host tracks PUB/SUB subscriptions and
  `publish` drops messages before encoding while nobody is listening.
- `ServiceClient.request` accepts an optional `timeout`; the client recovers cleanly
  after a timed-out request.

### Changed

- Add UTC timezone to trial DataFrame timestamps.
- `ServiceClient` adopts the host's serialization format during the
  handshake, replacing the per-request trial-and-error fallback.
- the WELCOME handshake carries the PUB channel's TCP port instead of full TCP
  addresses.
- errors raised by `bpod_core.ipc` are now uniformly `ServiceError` subclasses
- remote method calls (`BpodRequestCall` / `BpodRequestData`) are validated against
  an explicit allowlist instead of dispatching to arbitrary attributes.

### Fixed

- `ServiceClient` no longer blocks indefinitely when the host dies mid-request.
- exceptions with non-serializable attributes no longer break error replies from
  `ServiceHost`.
- resolved several shutdown races between `close()` and the event threads / `publish()`.
- `ServiceIterator.close()` now terminates an iteration blocked in `__next__`
  (e.g., with `timeout=None`) instead of leaving the consumer waiting forever.

## [0.1.0a13](https://github.com/int-brain-lab/bpod-core/releases/tag/0.1.0a13) - 2026-06-18

### Changed

- further work on bringing `RemoteBpod` to parity with `Bpod`.
- `ExtendedSerial.read_struct` and `write_struct` methods accept precompiled structs.
- reduced public interface of `bpod_core.ipc`.
- improved documentation.

## [0.1.0a12](https://github.com/int-brain-lab/bpod-core/releases/tag/0.1.0a12) - 2026-04-30

Just some minor improvements …

### Changed

- further refinements to documentation.
- cleaned up rendering of Graphviz graphs.

### Removed

- removed unused `misc.DocstringInheritanceMixin`

## [0.1.0a11](https://github.com/int-brain-lab/bpod-core/releases/tag/0.1.0a11) - 2026-04-24

### Added

- `ExtendedSerial.read_struct_iter` and `ExtendedSerial.stream_struct` methods.
- `misc.SuggestionDict` for key lookup with typo suggestions.
- added optional `trial_number` parameter to `Bpod.run` method.

### Changed

- replaced `NamedTuples` with `misc.SuggestionDict` for `Bpod.inputs` and
  `Bpod.outputs`
- refactored Sphinx documentation and API reference.

## [0.1.0a10](https://github.com/int-brain-lab/bpod-core/releases/tag/0.1.0a10) - 2026-04-16

### Added

- Bpod.address property — exposes the ZeroMQ address of the running instance.
- `Bpod.peek_data` - read trial data before trial end.
- `misc.ByteEnum` - an extended `IntEnum` that caches its values as bytes.
- Timer fields in StateMachine now accept timedelta values in addition to floats.
- `bpod` CLI entry point for launching a Bpod instance that can be connected to via TCP
  Unix Sockets.
- `state machine` column added to trial data output (hash of the FSM)

### Changed

- renamed `Bpod.send_state_machine` to `Bpod.run`.
- removed `Bpod.run_state_machine`.
- switched to Polars `LazyFrame` for storing trial data.
- replaced use of `Queue` with `SimpleQueue`.
- switched `Bpod.module` field from `NamedTuple` to `dict`.
- replaced hashlib.blake2b with xxhash for state machine hashing.
- cache validation and compilation of state machines.
- `StateMachine.hash` now returns `bytes` instead of `str`.

## [0.1.0a9](https://github.com/int-brain-lab/bpod-core/releases/tag/0.1.0a9) - 2026-04-02

### Added

- `bpod.is_ready` property indicating whether a compiled FSM is loaded and ready to run
- `bpod.is_queued` property indicating whether an FSM is queued to run after the current
  one
- `bpod.get_data` for returning trial data after a state machine run.

### Changed

- renamed `BNC` input events and output actions to `TTLIn` and
  `TTLOut`.
- replaced MD5 hashing of `fsm.StateMachine` with blake2b.
- improved readability of `ValidationError` messages in `fsm.StateMachine`.
- state machine runs are now handled by three separate threads:
  - `ReadThread` for serial communication with the Bpod,
  - `EventThread` for handling and structuring the incoming data, and
  - `SoftcodeThread` for executing soft-codes.

### Fixed

- reorganization of finalizers for better garbage collection.

## [0.1.0a8](https://github.com/int-brain-lab/bpod-core/releases/tag/0.1.0a8) - 2026-03-04

Just a quick bugfix release …

### Changed

- `ipc.ServiceHost`: set Zeroconf to listen on all interfaces, reorder `WelcomeData`
  fields, and improve type hints.
- event handler callback type hint to return `None` instead of `Any`.
- refactor CI workflows.

## [0.1.0a7](https://github.com/int-brain-lab/bpod-core/releases/tag/0.1.0a7) - 2026-03-01

### Added

- `com.find_ports` for finding serial ports that match given filter criteria.
- `com.verify_serial_discovery` for checking if a serial device sends an expected
  discovery message.
- convenience functions for reading and writing integers in `com.ExtendedSerial`.
- `misc.extend_packed` for extending a bytearray by multiple values of the same format.
- `misc.DocstringInheritanceMixin` for inheriting docstrings from base classes.
- `ipc.LocalServiceAdvertisement`: local service advertisement and discovery
- `ipc.iter_services` and `ipc.ServiceIterator` for discovering services.
- `bpod.discover_remote_bpod` for discovering remote Bpod instances.
- more examples.

### Changed

- more verbose debug logging during state machine runs.
- replace unmaintained `appdirs` dependency with `platformdirs`.
- switch to zero-based indexing for global counters, timers, conditions and soft-codes.
- added file locking to `misc.SettingsDict`.
- switch to using ZMQ multipart messages for communication.
- renamed `ipc.DualChannelHost` / `ipc.DualChannelClient` to `ipc.ServiceHost` /
  `ipc.ServiceClient`.
- restructured `bpod` module into several submodules.
- zero-copy behavior on send path of `ipc.ServiceClient` and receive path of
  `ipc.ServiceHost`.

### Fixed

- decoupled finalizers and event loops from instance references.

## [0.1.0a6](https://github.com/int-brain-lab/bpod-core/releases/tag/0.1.0a6) - 2025-10-29

### Added

- Initial work on cached state machine validation: `fsm.StateMachine.check`

### Changed

- `com.ExtendedSerial` no longer supports NumPy types, integers, strings and iterables.
- refactoring of `com.ChunkedSerialReader`

### Removed

- `com.to_bytes`
- dependency on Pandas

## [0.1.0a5](https://github.com/int-brain-lab/bpod-core/releases/tag/0.1.0a5) - 2025-09-03

### Added

- `fsm.to_file` and `fsm.from_file` for export/import of state machines.
- YAML import/export for state machines
- Work on documentation: Finite-State Machines

### Changed

- moved state machine structure from msgspec Struct back to Pydantic Model
- merged `fsm_types` module back into `fsm`
- renamed parameters for `add_state` method: `state_change_conditions` -> `transitions`
  and `output_actions` -> `actions`

## [0.1.0a4](https://github.com/int-brain-lab/bpod-core/releases/tag/0.1.0a4) - 2025-08-25

### Added

- `ipc.DualChannelHost` and `ipc.DualChannelClient`
- JSON import/export for state machines
- example state machines

### Changed

- improved export of state machines to graphviz
- improved settings management
- moved state machine structure from Pydantic Model to msgspec Struct

## [0.1.0a3](https://github.com/int-brain-lab/bpod-core/releases/tag/0.1.0-alpha.3) - 2025-08-04

### Added

- state machine assembly
- state machine thread
- ZMQ communication module
- basic settings management

### Changed

- switched package management from PDM to uv.

## [0.1.0a2](https://github.com/int-brain-lab/bpod-core/releases/tag/0.1.0-alpha.2) - 2025-05-07

### Added

- pydantic model for state machine

### Changed

- further refactoring of the code
- renamed `serial` module to `com` to avoid confusion with PySerial.

## [0.1.0a1](https://github.com/int-brain-lab/bpod-core/releases/tag/0.1.0-alpha.1) - 2025-04-22

### Changed

- major reorganization of the existing codebase.
- renamed `serial_extensions` module to `serial`.

### Removed

- removed `SerialSingleton` class.

## [0.1.0a0](https://github.com/int-brain-lab/bpod-core/releases/tag/0.1.0-alpha) - 2025-04-17

First alpha release. Nothing works.
