ready-active-safe 0.1.3

Lifecycle engine for externally driven systems
Documentation
# Free Functions

Convenience wrappers that make `match` arms read like sentences.

## `stay()` — remain in the current mode

```rust
use ready_active_safe::prelude::*;

let d: Decision<&str, ()> = stay();
assert!(d.is_stay());
assert!(d.target_mode().is_none());
assert!(d.commands().is_empty());
```

## `transition(target)` — move to a new mode

```rust
use ready_active_safe::prelude::*;

let d: Decision<&str, ()> = transition("active");
assert!(d.is_transition());
assert_eq!(d.target_mode(), Some(&"active"));
```

## `ignore()` — deliberate no-op

Semantically identical to `stay()`, but communicates intent. Use in catch-all
arms to signal that silence is by design, not an oversight.

```rust
use ready_active_safe::prelude::*;

#[derive(Debug, Clone, PartialEq, Eq)]
enum Mode { Ready, Active }

#[derive(Debug)]
enum Event { Start, Ping }

struct System;

impl Machine for System {
    type Mode = Mode;
    type Event = Event;
    type Command = ();

    fn initial_mode(&self) -> Mode { Mode::Ready }

    fn on_event(&self, mode: &Mode, event: &Event) -> Decision<Mode, ()> {
        match (mode, event) {
            (Mode::Ready, Event::Start) => transition(Mode::Active),
            _ => ignore(), // deliberate: these events need no response
        }
    }
}

let system = System;
let d = system.decide(&Mode::Active, &Event::Ping);
assert!(d.is_stay());
```

## `apply_decision(current_mode, decision)` — consume and apply

```rust
use ready_active_safe::prelude::*;

let decision: Decision<&str, &str> = transition("active").emit("init");
let (mode, commands) = apply_decision("ready", decision);
assert_eq!(mode, "active");
assert_eq!(commands, vec!["init"]);
```

Stay decisions return the current mode unchanged:

```rust
use ready_active_safe::prelude::*;

let decision: Decision<&str, ()> = stay();
let (mode, commands) = apply_decision("ready", decision);
assert_eq!(mode, "ready");
assert!(commands.is_empty());
```

## `apply_decision_checked(current_mode, decision, policy)` — apply with guard

```rust
use ready_active_safe::prelude::*;

let decision: Decision<&str, &str> = transition("active").emit("go");
let (mode, commands) = apply_decision_checked("ready", decision, &AllowAll)?;
assert_eq!(mode, "active");
assert_eq!(commands, vec!["go"]);

let decision: Decision<&str, &str> = transition("active");
let err = apply_decision_checked("ready", decision, &DenyAll).unwrap_err();
assert!(matches!(err, LifecycleError::TransitionDenied { .. }));
# Ok::<(), LifecycleError<&str>>(())
```

## See Also

- [`Decision`]decision.md — the type these functions create
- [`Machine`]machine.md — uses these in `on_event` match arms