Skip to content

fix: contract sweep — serde feature, no_std, NaN guards, doc accuracy - #63

Merged
NickFlach merged 1 commit into
masterfrom
fix/contract-sweep
Aug 10, 2026
Merged

NickFlach merged 1 commit into
masterfrom
fix/contract-sweep

Conversation

@NickFlach

Copy link
Copy Markdown
Collaborator

Verify-triage of all 34 open issues against HEAD, then a grouped fix pass. Do not merge — for review.

The headline: the serde feature never compiled

Five issues (#2 #43 #44 #55 #56) all reported "the serde feature can't serialize X". Every one of those types already carried the correct #[cfg_attr(feature = "serde", derive(...))]. The actual cause was one line in Cargo.toml: serde is pulled in with default-features = false (needed for no_std), which drops serde's Vec/String impls. So PhiNode.connections: Vec<usize> and XiSignature.values: Vec<f32> failed to compile — and that killed the entire --features serde build, taking the Vec-free types down with it.

This stayed invisible because tests/serde_feature.rs is gated on #![cfg(feature = "serde")]. Under plain cargo test it reported running 0 tests, and cargo test --features serde didn't compile. The fix is serde = ["dep:serde", "serde/alloc"]; those 10 tests now actually execute.

no_std was broken too — the earlier detect_hives fix reached for f32::rem_euclid, which core doesn't provide. Added to F32Ext.

Numeric guards

Issue Was Now
#58 One NaN phase reached every peer via sin(phases[j] - phases[i]) and overwrote healthy oscillators on the first Euler step Non-finite oscillators quarantined from both sides of the coupling sum, never integrated
#62 Raw Euler accumulation walked phases past 2π (reported 9.23 rad) Folded into [0, 2π). sin/cos are 2π-periodic, so no dynamics change — pinned by a test
#41 f32::clamp propagates NaN, so k_base * NaN came back as NaN coupling Holds last good coupling. (The mean_signal() half was already fixed)
#52 exp(-λt) with negative t is a growth term — clock skew made memories stronger than base amplitude Age floored at 0
#54 Promised [0, 1] but only had a ceiling, so opposed vectors leaked -1.0 into ranking code Clamped both ends
#53 Single-node graph reported num_partitions: 0, indistinguishable from empty 1 for one node, 0 only for empty

Docs corrected to match code

The README's usage snippet called KuramotoModel::new(vec![...]) and model.sync(dt, k) — neither exists in any version of this API. Replaced with a working example that is now compiled as a test (readme_kuramoto_example_compiles) so it can't rot again. Also removed the bind/bundle/permute primitives and the eigendecomposition-Φ claim (neither is implemented) and the bridge-level chiral mode (#61 — chiral lives in kuramoto).

NATS contract: reactions carry the shared envelope (#28), dream.end matches KANNAKA.dreams as its own description claims (#38), dependency map points at the singular KANNAKA.exemplar.* subject (#39).

Gates

cargo test --all-features    83 + 10 + 6 passed, 0 failed   (was 71 + 0 + 5)
cargo clippy --all-targets --all-features -- -D warnings    clean
cargo fmt --all --check                                     clean
cargo check --no-default-features                           clean  (was failing)
cargo check --features serde                                clean  (was failing)

Closed separately as already-fixed

18 issues were verify-triaged as already fixed at HEAD and closed with evidence: #11 #27 #30 #31 #32 #33 #34 #37 #40 #42 #45 #46 #47 #48 #49 #50 #51 #57.

Left open deliberately

Four need a call on the metric definition rather than a guess from me:

🤖 Generated with Claude Code

The serde feature never compiled. `serde` was pulled in with
`default-features = false` (for no_std) and no `alloc`, so `Vec<T>` had
no Serialize/Deserialize impl. `PhiNode.connections` and
`XiSignature.values` failed to compile, which took the whole
`--features serde` build down with them — including the Vec-free types
that already had correct derives. tests/serde_feature.rs is gated on
`#![cfg(feature = "serde")]`, so it silently ran 0 tests and the
breakage stayed invisible. Adding `serde/alloc` fixes the cluster; the
10 tests in that file now actually execute.

no_std was likewise broken: the detect_hives fix reached for
`f32::rem_euclid`, which core does not provide. Added it to F32Ext.

Numeric guards:
- sync() quarantines non-finite oscillators. One NaN phase reached every
  peer through sin(phases[j] - phases[i]) and overwrote healthy
  oscillators on the first Euler step.
- sync() folds phases back into [0, 2π). sin/cos are 2π-periodic so this
  changes no dynamics, but raw accumulation walked past the contract
  QUEEN.phase.* publishes and that mean_field_step already honored.
- MarketMediated holds coupling on a non-finite signal. f32::clamp
  propagates NaN rather than bounding it.
- Wave strength floors age at 0. exp(-λt) with negative t is a growth
  term, so clock skew made a memory stronger than its base amplitude.
- xi_diversity_boost clamps both ends. It promised [0, 1] but only had a
  ceiling, so opposed vectors leaked -1.0 into ranking code.
- compute_phi reports 1 partition for a single node, 0 only for empty.

Docs corrected to match the code: the README's usage snippet called
`KuramotoModel::new(vec![...])` and `model.sync(dt, k)`, neither of which
exist in any version of this API; it is now pinned by a test. Also
removed the bind/bundle/permute primitives and the eigendecomposition Φ
claim (neither implemented), and the bridge-level chiral mode (chiral
lives in kuramoto). NATS contract: reactions now carry the shared
envelope, dream.end matches KANNAKA.dreams as its description claims,
and the dependency map points at the singular exemplar subject.

Left open deliberately — these need a call on the metric definition
rather than a guess: #35 (two-vector Xi collapses to 0 because variance
over a single pair is always 0), #60 (mixed-dimension embeddings read as
xi=0 instead of an input error), #36 (unified_xi ignores the xi field),
#59 (single-oscillator sync reports r=1.0, which is mathematically
correct but inconsistent with compute_swarm_phi's n<2 → 0.0).

Fixes #2
Fixes #43
Fixes #44
Fixes #55
Fixes #56
Fixes #29
Fixes #58
Fixes #62
Fixes #41
Fixes #52
Fixes #54
Fixes #53
Fixes #61
Fixes #28
Fixes #38
Fixes #39

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant