# `Raxol.AgentClientProtocol.Telemetry`
[🔗](https://github.com/DROOdotFOO/raxol-agent/blob/raxol_agent_client_protocol-v0.1.0/packages/raxol_agent_client_protocol/lib/raxol/agent_client_protocol/telemetry.ex#L1)

The classified registry of every `:telemetry` event this package emits.

This module exists because the package already *detected* its own impossible
states and then did nothing about them: `Session` emits
`[:raxol, :acp, :zero_updates_turn]` (and logs a warning) when a turn
completes without a single `session/update` for a non-empty prompt, and a bug
that did exactly that shipped anyway -- because no test ever asserted on the
event. Detection without enforcement is not a guard.

## The three classes

  * `:invariant` -- can only fire if RAXOL ITSELF is wrong. Enforced: it must
    never fire during our own test run. `Raxol.AgentClientProtocol.Test.InvariantSentinel`
    turns any occurrence into a test failure.
  * `:peer` -- caused by the remote agent/client misbehaving: a malformed
    frame, an unknown notification, a duplicate or late id. Negative tests
    drive these on purpose. Not enforced.
  * `:operational` -- normal life: a delivery decision, backpressure shed, a
    policy verdict, an idle reap. Not enforced.

## The classification criterion, applied literally

If a peer, the network, the filesystem, the clock, or a user of this library
can cause the event, it is NOT an invariant. Err toward `:peer` or
`:operational`: a false invariant makes the suite flaky and gets the whole
mechanism deleted, which is strictly worse than a missed one.

## Adding an event

The package's test suite parses `lib/` for `[:raxol, ...]` event
literals and fails if any is missing from `events/0` (or if `events/0` claims
an event no source file mentions). A new event therefore cannot land without
someone classifying it here, and the one-line WHY comment on each row below is
the artifact that author reads.

# `class`

```elixir
@type class() :: :invariant | :peer | :operational
```

Enforcement class. See the moduledoc for the criterion.

# `event`

```elixir
@type event() :: [atom()]
```

Telemetry event name, as passed to `:telemetry.execute/3`.

# `classify`

```elixir
@spec classify(event()) :: class() | nil
```

The class of `event`, or `nil` when it is not registered.

# `events`

```elixir
@spec events() :: %{required(event()) =&gt; class()}
```

Every telemetry event this package emits, mapped to its enforcement class.

# `invariant_events`

```elixir
@spec invariant_events() :: [event()]
```

The `:invariant` subset of `events/0`, sorted. This is what the sentinel arms.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
