CHANGELOG.md

# Changelog

All notable changes to this project are documented here. The format
follows [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).

**Telemetry schema stability.** Within the `0.1.x` and later `1.x`
lines, the event names, measurement keys, and metadata keys of the
`[:phi_accrual, ...]` telemetry schema are contract — breaking
changes only in `v2.0.0`. See the README for the committed schema.

## [Unreleased]

## [1.0.0] - 2026-05-07

### Added

- `PhiAccrual.inspect_state/1` for IEx introspection — delegates to
  `PhiAccrual.Estimator.core_state/1`.

### Changed

- `[:phi_accrual, :phi, :computed]` now emits `phi: 0.0` when state is
  `:insufficient_data` or `:stale`, instead of a recomputed-but-not-
  meaningful φ value. Pre-1.0 contract clarification — schema shape
  unchanged.

### Notes

The roadmap has shifted: the previously-planned in-tree `UdpSource` is
now scoped as a separate package, `phi_accrual_udp`. The core stays
transport-agnostic. See README "Companion packages" for the current
direction.

## [0.1.0] - 2026-04-20

Initial public release. **Alpha** — the API may change before `v1.0`.
The telemetry event schema is already stable; the rest is subject to
tuning based on real-deployment feedback.

### Added

- **Core EWMA estimator** (`PhiAccrual.Core`) — pure Hayashibara 2004
  math with West 1979 incremental variance and **separate α for mean
  and variance**. Numerically stable φ computation via softplus (no
  `:math.exp` overflow on extreme deltas).
- **Four-state φ result** — distinguishes `:steady`, `:recovering`
  (warm estimator absorbing a recent large gap), `:insufficient_data`
  (bootstrap phase), and `:stale` (no heartbeat past grace window).
- **Per-node estimator processes** — each monitored node runs its own
  `PhiAccrual.Estimator` GenServer under a `DynamicSupervisor`,
  registered via `Registry`. Isolation means one slow node cannot
  block observations for others.
- **Overload shedding** — `PhiAccrual.observe/2` drops samples and
  emits `[:phi_accrual, :overload, :shed]` telemetry when the target
  estimator's mailbox exceeds `:shed_threshold`.
- **Local-pause awareness** (`PhiAccrual.PauseMonitor`) — subscribes
  to `:erlang.system_monitor` for `:long_gc`, `:long_schedule`, and
  `:busy_dist_port`. Publishes pause state via `:persistent_term` and
  tags φ output with `local_pause?` / `confidence` metadata so
  consumers can filter rather than having the detector silently
  freeze.
- **Bring-your-own-signal API** — call `PhiAccrual.observe/2` from
  any code that already receives cross-node traffic (GenServer
  replies, `:pg`, `:global` sync).
- **Reference source** (`PhiAccrual.Source.DistributionPing`) —
  opt-in 1 s app-layer ping over BEAM distribution. Supervised
  separately from estimators so a ping-source restart does not wipe
  state.
- **Optional threshold layer** (`PhiAccrual.Threshold`) — subscribes
  to the φ gauge stream and emits `:suspected` / `:recovered` events
  with configurable hysteresis. Multiple instances coexist.
- **Telemetry schema (contract)** — `[:sample, :observed]`,
  `[:phi, :computed]`, `[:local_pause, :start|:stop]`,
  `[:overload, :shed]`, `[:source, :started]`,
  `[:threshold, :suspected|:recovered]`.

### Not included (deferred to v2)

- Dedicated UDP channel (`UdpSource`) — necessary for decision-grade
  detection by escaping head-of-line blocking on the BEAM
  distribution socket.
- Non-parametric / mixture estimators — pending real-deployment
  traces to justify the added complexity.
- Multi-node `:peer`-based integration tests.
- `phi_accrual_libcluster` companion package.

[Unreleased]: https://github.com/thatsme/phi_accrual/compare/v1.0.0...HEAD
[1.0.0]: https://github.com/thatsme/phi_accrual/releases/tag/v1.0.0
[0.1.0]: https://github.com/thatsme/phi_accrual/releases/tag/v0.1.0