6 Commits
Author SHA1 Message Date
swaits 4cccb65124 feat!: protocol v2 wire format and module restructure
The wire protocol is re-specified as DongLoRa Protocol v2 (see PROTOCOL.md). Every type_id, tag-correlation rule, and field layout is incompatible with 0.1.0.

* Add PROTOCOL.md as the normative spec for the v2 wire format.

* Replace framing.rs with a streaming FrameDecoder that emits (type_id, tag, payload) triples on each COBS-delimited, CRC-checked frame.

* Split the single-file lib.rs into dedicated modules: frame, commands, events, errors, modulation, info, crc, chip_id. Re-exports preserve convenience imports at the crate root.

* Replace RadioConfig / Bandwidth with a Modulation enum covering LoRa, FSK/GFSK, LR-FHSS, and FLRC, each with its own typed parameter struct.

* Add TxFlags, RxOrigin, SetConfigResult, OkPayload to model v2 response shapes, and RadioChipId for GET_INFO.

* Rewrite fuzz corpus: replace the 4 cobs_* / command_roundtrip targets with decoder_feed, frame_roundtrip, lora_config_roundtrip, and parse_device_message; drop parse_radio_config.

* Expand proptest and mutation-killer coverage for the new wire shape.

* Rewrite canonical-byte test vectors against the v2 spec.
2026-04-22 09:21:11 -06:00
swaits 670321efd1 ci: GitHub Actions workflow + drop test-fuzz-long
Eight parallel jobs on push/PR:

- test × 3 (default / no-default / all-features) via nextest + doc
- clippy × 3 feature permutations, -D warnings
- fmt
- doc (all-features, -D warnings on rustdoc)
- deny (cargo-deny action)
- miri (nightly, lib + vectors under default + no-default)
- fuzz (nightly, 60 s smoke on every target)
- mutants × 2 feature configs (same equivalence exclusions as local)

Swatinem/rust-cache on every cargo job; taiki-e/install-action for
nextest / cargo-fuzz / cargo-mutants. Uploads mutants.out on failure.

Drops test-fuzz-long from the justfile — 60 s per target in CI every
push plus the local proptest 1M-case suite already covers this.
2026-04-13 12:12:12 -06:00
swaits 78cb84d8da test: run mutants under both feature configurations
test-mutants now runs cargo-mutants twice — once with defaults (defmt
derives present) and once with --no-default-features (derives absent)
— so feature-gated paths are covered in both shapes. Same three
equivalent mutants are excluded in both runs.
2026-04-13 12:12:12 -06:00
swaits ef576ba1ec test: three more cargo-fuzz targets + test-fuzz-long recipe
- command_roundtrip: structure-aware (via arbitrary crate) Command
  encode → parse → equal. Symmetric to cobs_roundtrip.
- cobs_decoder_multi_frame: chunked feeding with arbitrary split sizes;
  asserts bounded payload and that command count never exceeds sentinel
  count.
- cobs_chunk_invariant: same stream through two decoders (chunked vs
  all-at-once) must produce the same command sequence.

Adds test-fuzz-long recipe (600s per target, ~1h 10m total) for CI
cron / pre-release. All seven targets smoke-tested at 100k runs each
with zero findings.
2026-04-13 12:12:12 -06:00
swaits 7a9820e495 test: miri-clean + mutation-hardened
Adds tests/mutation_killers.rs with six targeted tests derived from
cargo-mutants findings: cad_enabled true/false paths, Transmit
with-config boundary, CobsDecoder::reset behaviour, empty-frame
handling, and the cobs_encode_response success path.

Three mutants remain as provably equivalent — the justfile excludes
them by exact regex so any genuinely new mutant on the same line will
still surface. Updates test-miri to also run the integration tests
(proptest stays skipped because its file-persistence layer calls
getcwd). Gitignore picks up mutants.out / mutants.out.old.

cargo mutants: 89 caught, 9 unviable, 0 missed.
2026-04-13 12:12:12 -06:00
swaits 53f801ec0b chore: add full-treatment quality gates
Mirrors the ucobs convention:
- justfile aggregates test-{unit,clippy,fmt,doc,deny,fuzz,miri,mutants}
  behind a single 'just test' target.
- mise.toml pins rust + cargo-{deny,fuzz,mutants,nextest}.
- deny.toml enforces permissive licenses only and bans wildcard /
  unknown-source deps.
- CLAUDE.md captures identity and first principles.
- Cargo.toml adds unsafe_code = forbid and docs.rs all-features metadata.

cargo check (all feature permutations), nextest, clippy with warnings
as errors, fmt check, doc, and deny all pass. fuzz/miri/mutants land
in follow-up commits.
2026-04-13 12:12:12 -06:00