behaviortree 0.8.0

A #![no_std] compatible behavior tree library similar to BehaviorTree.CPP.
Documentation
# CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

## Project Overview

A `#![no_std]` compatible behavior tree library in Rust, modeled after [BehaviorTree.CPP](https://www.behaviortree.dev/). Supports both standard OS and embedded targets (via Ariel-OS). Trees are defined in BehaviorTree.CPP v4 XML format and can interoperate with the Groot2 editor/monitor.
Part of the dibbots ecosystem, hosted on Codeberg.

## Common Commands

```bash
# Build
cargo build
cargo build --release

# Test
cargo test                        # std tests
cargo test --all-features
cargo test --no-default-features  # test no_std mode

# Single test
cargo test test_name

# Lint
cargo clippy
cargo fmt --check

# Doc
cargo doc --no-deps

# Benchmarks
cargo bench
cargo make bench-baseline   # save criterion baseline "main"
cargo make bench-compare    # compare against baseline "main"

# Coverage (requires nightly + cargo-llvm-cov + cargo-make + llvm-tools-preview)
cargo make cov          # LCOV report → coverage/lcov.info
cargo make cov-html     # HTML report

# Embedded compile test
./verify_embedded_compile.sh

# Run tests on embedded device
./run_embedded_tests.sh <board-identifier>
```

See [Makefile.toml](Makefile.toml) for the full task list and install preconditions at the top of that file.

## Workspace structure

The top-level `behaviortree` crate (`src/`) is a thin re-export layer. The real logic lives in four sub-crates:

| Crate | Path | Role |
|-------|------|------|
| `behaviortree-core` | `core/` | Traits, built-in control-flow behaviors, `BehaviorTree` runtime, XML export. See `core/CLAUDE.md`. |
| `behaviortree-factory` | `factory/` | `BehaviorTreeFactory`, `FactoryRegistry`, XML parser (BehaviorTree.CPP v4), behavior registration |
| `behaviortree-behaviors` | `behaviors/` | Optional feature-gated behaviors: actions, conditions, decorators |
| `behaviortree-derive` | `derive/` | Proc-macro crate — `Action`, `Condition`, `Control`, `Decorator` derives |

### Core flow: Registry → Factory → Tree → Tick

1. **`FactoryRegistry`** (`factory/src/registry.rs`) — holds registered behavior creation functions, the tinyscript runtime, and loaded libraries (plugins).
2. **`BehaviorTreeFactory`** (`factory/src/factory.rs`) — users register behaviors (custom structs or simple functions), then call `create_from_text(xml)` to parse XML and instantiate a `BehaviorTree`.
3. **`BehaviorTree`** (`core/src/tree/tree.rs`) — the runtime tree. Call `tick_while_running().await` or `tick_exactly_once().await` to execute.
4. **`Behavior` trait** (`core/src/behavior_traits.rs`) — implement `tick()` (async, required). Optionally override `on_start()`, `on_halt()`, `start()`, `halt()`.

Each node is a `BehaviorTreeElement` (`core/src/tree/tree_element.rs`) holding a `BehaviorPtr` (boxed `dyn BehaviorExecution`), a `BehaviorData` (uid, state, blackboard, description), children, and pre/post conditions.

### Behavior categories (`behaviors/src/`)

- **Actions** (`action/`) — leaf nodes: Script, SetBlackboard, Sleep, PopFromQueue, UnsetBlackboard
- **Conditions** (`condition/`) — leaf nodes: ScriptCondition, WasEntryUpdated
- **Controls** (`control/`) — multi-child: IfThenElse, Switch (2–6 arms), WhileDoElse
- **Decorators** (`decorator/`) — single-child: Delay, EntryUpdated, ForceState, Inverter, KeepRunningUntilFailure, LoopQueue, Precondition, Repeat, RetryUntilSuccessful, RunOnce, Timeout

Each behavior is individually feature-gated. The `all_behaviors` feature enables everything. When adding a new behavior, register its feature in `behaviors/Cargo.toml` **and** `Cargo.toml`, then append it to the `all_behaviors` list.

### Derive macros (`derive/`)

Four derives: `Action`, `Condition`, `Control`, `Decorator`. These generate `BehaviorExecution` (kind, portlist access, downcasting) plus `create_fn()` and `register()` methods.

Key struct attributes: `#[behavior(no_create)]`, `#[behavior(no_register)]`.  
Key field attributes: `#[behavior(portlist)]`, `#[behavior(parameter)]`, `#[behavior(default = ...)]`.

### Ports and Blackboard

- **Ports** (from `dataport` crate) — typed I/O declarations. Use `PortArray<N>`, `PortMap`, or `PortVec`. Initialized via `port_array_init!` macro with `create_inbound_entry_parseable!` / `create_outbound_entry_parseable!`.
- **Blackboard** (from `databoard` crate) — `Databoard`, hierarchical key-value store shared across the tree. Supports remapping so subtrees can alias port names.
- **Scripting** (from `tinyscript` crate) — embedded scripting for pre/post conditions and Script/ScriptCondition nodes.

### Pre/post conditions

`PRE_CONDITIONS = [_failureIf, _successIf, _skipIf, _while]`  
`POST_CONDITIONS = [_onHalted, _onFailure, _onSuccess, _post]`

Evaluated via tinyscript at each tick. XML attributes with these names are parsed by the factory and stored on each `BehaviorTreeElement`.

### XML parsing and generation

- **Parsing**`factory/src/xml/` parses BehaviorTree.CPP v4 format (`<root BTCPP_format="4">`). Uses `roxml`.
- **Generation**`core/src/xml/creator.rs` uses `woxml` to write XML from a live tree.

### Observer / Groot2 integration

`BehaviorTreeObserver` trait for monitoring tick state changes. `Groot2Connector` (std only) enables live monitoring via ZeroMQ over an `embassy-sync` channel, compatible with the Groot2 desktop tool.

## Sibling crates (local path dependencies)

- `databoard` (`../databoard`) — blackboard implementation
- `dataport` (`../dataport`) — port system
- `roxml` (`../roxml`) — no_std XML reader
- `tinyscript` (`../tinyscript`) — scripting engine
- `woxml` (`../woxml`) — XML writer

## Features / no_std

- `std` (default) — propagates std to all sub-crates and enables tokio, uuid, zeromq, libloading, rand
- `testing` — implies `std`; exposes test-only helpers in `behaviortree-core` (e.g. `Groot2ConnectorData::new_for_test()`) without requiring a live ZeroMQ socket
- `all_behaviors` — enables all optional behaviors in `behaviortree-behaviors`
- Individual behavior features: `script`, `sleep`, `inverter`, `if_then_else`, `switch2``switch6`, etc.

Disable default features for `no_std` usage:

```toml
behaviortree = { version = "...", default-features = false }
```

## Embedded Support

The [embedded/ariel-os/](embedded/ariel-os/) directory contains benchmarks, tests, and usage examples for various targets via the ariel-os framework. Builds use the `laze` build system rather than plain Cargo.

## Coverage caveat: nanoserde derives

`BehaviorState` uses `#[derive(nanoserde::DeJson)]`. `nanoserde-derive` stamps every token with `Span::call_site()`, so LLVM source-based coverage cannot attribute hits to the derive attribute line — it stays at 0 in `lcov` even when exercised. This is a tooling limitation, not a missing test.