Commit Graph
10 Commits
Author SHA1 Message Date
kyle 69715a1505 fix(ros2): rclrs 0.8 API + bytes payload mapping
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).
2026-10-18 21:03:32 -07:00
kyle 20436badd0 feat(service): standalone tines service with Unix-socket IPC
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.
2026-10-18 16:41:02 -07:00
kyle 7be09f8e9a Task 9: tines-ros2 — pure topic_name escaping (default, tested) + optional rclrs TinesNode (feature ros2)
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.
2026-10-18 14:46:57 -07:00
kyle d089d9edaa feat(bt): BLE transport over BlueZ with identity-preserving Addr
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.
2026-10-18 14:06:48 -07:00
kyle 43b73f88cd feat(store): add tines-store persistent append-only LogStore
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.
2026-10-18 12:43:42 -07:00
kyle 0bb4d568ea feat(core): Store::release and is_released (0.3.0) 2026-10-18 07:22:45 -07:00
kyleandClaude Opus 5.5 8b233c787f chore: release 0.2.1 with crates.io metadata
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>
2026-10-18 05:26:39 -07:00
kyleandClaude Opus 5.5 5c8bfe89ac chore: release 0.2.0; document the store contract and on_send_error
CI / ci (push) Canceled after 0s
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>
2026-10-18 05:24:30 -07:00
kyle 5dca574c50 feat(sim): world, contact trace, SimTransport 2026-10-17 16:06:51 -07:00
kyle 8108feb146 feat(core): workspace, Observation, content-derived id 2026-10-16 18:05:52 -07:00