Rewrite tines-ros2/src/node.rs against the rclrs 0.8 API (Context::
default_from_env -> create_basic_executor -> create_node; type-inferred
subscriptions; thiserror-based RclrsError) and switch payloads from
std_msgs String to UInt8MultiArray:
* live topics publish the raw Observation.bytes as data (no UTF-8 lossy);
* inbound callbacks use msg.data verbatim;
* receipts are a 32-byte UInt8MultiArray (peer[..16] ++ id[..16]);
* supply the required MultiArrayLayout { dim: [], data_offset: 0 }.
Bump ros_env 0.1 -> 0.3 so the crate's std_msgs pins rclrs 0.8's rosidl
runtime 0.7 (was 0.6), and update Cargo.lock. Add #[allow(dead_code)] on
ManagedTopic::subscriber (drop-guard for the rcl subscription handle).
Keep the ROS2-free build green; no changes outside tines-ros2/ (and the
Cargo.lock entry).
New `tines` crate (added to workspace members) hosting a `Node<LogStore,
BtTransport>` and serving a tiny request/response IPC over a Unix-domain
socket for robots without ROS2. Four operations: `observe`, `belief`,
`events`, and `status`, over length-prefixed JSON frames.
The `serve` loop now serves each connection request-by-request (previously
it handled one request per connection, dropping the socket after the first
response). Integration tests drive `handle`/`serve` with a mock transport
that auto-acks observed broadcasts and echoes an empty Summary, so a
confidence event fires without a real BLE radio.
Adds the ninth fleet-deployment crate. Default build is ROS2-free: topic_name
hex-escapes arbitrary tines topics into valid ROS2 names under /tines/ (deterministic,
injective) and wires Node<LogStore, BtTransport>. The rclrs-backed self-contained
TinesNode lives under #[cfg(feature="ros2")] with an off-by-default ros2 feature, so
the crate builds/tests without a ROS2 toolchain. Adds scripts/check-ros2.sh (needs a
ROS2 toolchain; not run in CI), registers the crate in workspace members, and passes
sh scripts/ci.sh.
Task 8 of the fleet-deployment plan. Adds the tines-bt crate: a real
`Transport` over the `bluer` crate (D-Bus BlueZ).
- `Addr` = peer's advertised `NodeId`, so identity survives BLE
address rotation; advertising payload (flags + 16-bit service UUID +
NodeId in service data) fits legacy 31-byte EIR (`advertise()`).
- `BtTransport` drops any inbound frame whose `from` differs from the
connection's advertised NodeId (protocol violation at the transport;
core never sees a mismatch).
- Connection symmetry: the node with the numerically smaller NodeId is
the BLE central/initiator (`is_central`), independent of which side
opens the radio.
- `mtu()` reports the real L2CAP CoC MTU (falling back to the ATT MTU);
the transport does NOT split frames — core folds summaries/fragments
to `mtu()`.
- Radio I/O sits behind the narrow `Radio` trait (a `poll`-driven event
stream), so the pure logic (payload assembly, mismatch-drop, central
rule) is unit-tested with a mock radio and never needs hardware.
- `BluerRadio` drives the stack on a detached tokio task: powers the
adapter, advertises, monitors for the service UUID, opens an L2CAP
byte pipe, and surfaces inbound bytes tagged with the peer NodeId.
Adds `tests/adv.rs` (8 mock-Radio integration tests covering the 31-byte
limit, NodeId round-trip, MTU clamp, mismatch-drop, per-frame MTU, and
central rule). Added to workspace members; workspace CI (fmt, doc,
test, clippy -D warnings) is green.
Add the host-side std `tines-store` crate implementing the `tines_core::Store`
trait over a durable, append-only single-file log so a robot's memory survives
reboot.
- Log format: length-prefixed `[u32 LE][postcard]` records (Obs/Trim/Meta).
- On load the index is rebuilt by replaying the log, then every age is
rebased to load time: elapsed time since the last persisted clock marker is
folded into `age_ms` and `stored_at` reset to load `now`, so ages continue
instead of freezing across a reboot.
- Persisted state: released-id set, `next_seq`, and a clock marker in a `Meta`
record; dedupe to the oldest Obs and let the last event per id win so a
re-inserted id survives a trim.
- Implements `next_seq` and `flush`; `trim` writes Trim records best-effort.
- Registered as a workspace member; std-only, `#![forbid(unsafe_code)]`.
- Adds persistence tests (append durability, rebase-on-load, released/seq
persistence). Full gate (fmt, clippy, docs, tests, no_std thumb build) is green.
Share version, edition, license, authors, repository and readme through
[workspace.package]; add per-crate documentation, keywords and
categories. Fixes `cargo publish` warning about missing documentation,
homepage or repository.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Bump tines-core and tines-sim to 0.2.0 (Peer::in_flight changed type).
Add CHANGELOG.md. README gains a "Writing a store" section and a note on
calling Exchange::on_send_error when driving Exchange without Node.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>