From 58127cc06da1019f7a8793d7f7b9eb1696eb617c Mon Sep 17 00:00:00 2001 From: AdaWorldAPI Date: Thu, 22 Oct 2026 22:34:54 +0200 Subject: [PATCH 1/5] test(lab): test(nars): independent evidence counts and Jeffreys Bayesian correspondence --- .../palette256_nars_bayes_evidence_probe.rs | 44 +++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100644 crates/causal-edge/tests/palette256_nars_bayes_evidence_probe.rs diff --git a/crates/causal-edge/tests/palette256_nars_bayes_evidence_probe.rs b/crates/causal-edge/tests/palette256_nars_bayes_evidence_probe.rs new file mode 100644 index 000000000..304a7e036 --- /dev/null +++ b/crates/causal-edge/tests/palette256_nars_bayes_evidence_probe.rs @@ -0,0 +1,44 @@ +//! Distinguish NARS independent evidence count, Bayesian posterior, and +//! quantized palette projection. A similarity score is not a sample size. +#[derive(Clone, Copy)] +struct Evidence { + positive: u64, + negative: u64, + sources: u64, +} +impl Evidence { + fn merge(self, other: Self) -> Option { + (self.sources & other.sources == 0).then_some(Self { + positive: self.positive.checked_add(other.positive)?, + negative: self.negative.checked_add(other.negative)?, + sources: self.sources | other.sources, + }) + } + fn frequency(self) -> f64 { + self.positive as f64 / (self.positive + self.negative) as f64 + } + fn nars_confidence(self) -> f64 { + let n = self.positive + self.negative; + n as f64 / (n as f64 + 1.0) + } + fn jeffreys_posterior_mean(self) -> f64 { + (self.positive as f64 + 0.5) / (self.positive + self.negative) as f64 .mul_add(1.0, 1.0) + } +} +#[test] +fn independent_equal_frequency_groups_do_not_increase_frequency() { + let a = Evidence { positive: 7, negative: 3, sources: 1 }; + let b = Evidence { positive: 7, negative: 3, sources: 2 }; + let both = a.merge(b).unwrap(); + assert!((both.frequency() - 0.7).abs() < 1e-12); + assert!((both.nars_confidence() - (20.0 / 21.0)).abs() < 1e-12); + assert!((both.jeffreys_posterior_mean() - 14.5 / 21.0).abs() < 1e-12); +} +#[test] +fn frequency_is_not_evidence_mass_and_duplicate_sources_do_not_count() { + let low = Evidence { positive: 1, negative: 1, sources: 1 }; + let high = Evidence { positive: 50, negative: 50, sources: 2 }; + assert_eq!(low.frequency(), high.frequency()); + assert!(high.nars_confidence() > low.nars_confidence()); + assert!(low.merge(low).is_none(), "do not double-count the same source"); +} From 121cb1d48718dfb5117b43764c7e33d65e2cdc99 Mon Sep 17 00:00:00 2001 From: AdaWorldAPI Date: Thu, 22 Oct 2026 22:34:56 +0200 Subject: [PATCH 2/5] test(lab): test(nars): independent evidence counts and Jeffreys Bayesian correspondence --- .../2026-10-22-pal256-nars-bayes-evidence-contract.md | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 .claude/board/entries/2026-10-22-pal256-nars-bayes-evidence-contract.md diff --git a/.claude/board/entries/2026-10-22-pal256-nars-bayes-evidence-contract.md b/.claude/board/entries/2026-10-22-pal256-nars-bayes-evidence-contract.md new file mode 100644 index 000000000..0b6617eaf --- /dev/null +++ b/.claude/board/entries/2026-10-22-pal256-nars-bayes-evidence-contract.md @@ -0,0 +1,11 @@ +# NARS revision and Bayesian updates: one measurable evidence basis + +Status: **lab-only executable mathematics**, not a replacement for `causal-edge` truth semantics. + +Existing measured result: `.claude/board/entries/2026-10-10-d-rpf-p5-nars-beta-correspondence.md`. NARS expectation with horizon k=1 equals the Jeffreys Beta(1/2,1/2) posterior mean for Bernoulli counts **before u8 information loss**; that is a special correspondence, not universal Bayesian equivalence. + +Proposed cold typed algebra: `EvidenceCounts {positive, negative, independent_sources}`. Allow exact count sum only when source roots are disjoint; preserve n with a provenance witness outside the u8 F/C lanes. A future `BayesianLogLikelihood` type is distinct and may be summed only under its own independence/model assumptions. Absolutely no `sum(atanh(cosine)) == NARS revision` rule. + +Falsifiers: same f at very different n has different c; duplicate roots refuse; two groups with 7/10 produce 14/20, *not* tanh(2*atanh(0.4)). + +Run: `cargo test --manifest-path crates/causal-edge/Cargo.toml --test palette256_nars_bayes_evidence_probe`. From e1dde5d70303deda1e19bc6ec912e50da0825ce5 Mon Sep 17 00:00:00 2001 From: AdaWorldAPI Date: Thu, 22 Oct 2026 22:35:33 +0200 Subject: [PATCH 3/5] fix(test): explicit Jeffreys posterior denominator --- .../causal-edge/tests/palette256_nars_bayes_evidence_probe.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/causal-edge/tests/palette256_nars_bayes_evidence_probe.rs b/crates/causal-edge/tests/palette256_nars_bayes_evidence_probe.rs index 304a7e036..0f788f773 100644 --- a/crates/causal-edge/tests/palette256_nars_bayes_evidence_probe.rs +++ b/crates/causal-edge/tests/palette256_nars_bayes_evidence_probe.rs @@ -22,7 +22,7 @@ impl Evidence { n as f64 / (n as f64 + 1.0) } fn jeffreys_posterior_mean(self) -> f64 { - (self.positive as f64 + 0.5) / (self.positive + self.negative) as f64 .mul_add(1.0, 1.0) + (self.positive as f64 + 0.5) / ((self.positive + self.negative) as f64 + 1.0) } } #[test] From f2039fb556528fa21793a5d40ed2c7b3b8af9769 Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 22 Oct 2026 21:41:49 +0000 Subject: [PATCH 4/5] fix(ci): rustfmt the probe test, regenerate the board entries index Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01G22yT6htkcdyXsihxxXdrg --- .claude/board/entries/README.md | 3 +- .../palette256_nars_bayes_evidence_probe.rs | 29 +++++++++++++++---- 2 files changed, 26 insertions(+), 6 deletions(-) diff --git a/.claude/board/entries/README.md b/.claude/board/entries/README.md index dd6231c6a..57c4b5994 100644 --- a/.claude/board/entries/README.md +++ b/.claude/board/entries/README.md @@ -25,10 +25,11 @@ index row, (3) no duplicate entry id. Checks 1 and 2 are deliberately opposite directions; the stranding this convention prevents shows up in exactly one of them, never both. -429 entries, 2026-08-06 .. 2026-10-22. +430 entries, 2026-08-06 .. 2026-10-22. | date | entry id | finding | file | |---|---|---|---| +| 2026-10-22 | `pal256-nars-bayes-evidence-contract` | | [2026-10-22-pal256-nars-bayes-evidence-contract.md](2026-10-22-pal256-nars-bayes-evidence-contract.md) | | 2026-10-22 | `math-compiler-stage-b-e1` | | [2026-10-22-math-compiler-stage-b-e1.md](2026-10-22-math-compiler-stage-b-e1.md) | | 2026-10-22 | `math-compiler-gap-matrix` | | [2026-10-22-math-compiler-gap-matrix.md](2026-10-22-math-compiler-gap-matrix.md) | | 2026-10-22 | `D-MPS-9` | | [2026-10-22-d-mps-9-mork-oracle.md](2026-10-22-d-mps-9-mork-oracle.md) | diff --git a/crates/causal-edge/tests/palette256_nars_bayes_evidence_probe.rs b/crates/causal-edge/tests/palette256_nars_bayes_evidence_probe.rs index 0f788f773..9768a2da2 100644 --- a/crates/causal-edge/tests/palette256_nars_bayes_evidence_probe.rs +++ b/crates/causal-edge/tests/palette256_nars_bayes_evidence_probe.rs @@ -27,8 +27,16 @@ impl Evidence { } #[test] fn independent_equal_frequency_groups_do_not_increase_frequency() { - let a = Evidence { positive: 7, negative: 3, sources: 1 }; - let b = Evidence { positive: 7, negative: 3, sources: 2 }; + let a = Evidence { + positive: 7, + negative: 3, + sources: 1, + }; + let b = Evidence { + positive: 7, + negative: 3, + sources: 2, + }; let both = a.merge(b).unwrap(); assert!((both.frequency() - 0.7).abs() < 1e-12); assert!((both.nars_confidence() - (20.0 / 21.0)).abs() < 1e-12); @@ -36,9 +44,20 @@ fn independent_equal_frequency_groups_do_not_increase_frequency() { } #[test] fn frequency_is_not_evidence_mass_and_duplicate_sources_do_not_count() { - let low = Evidence { positive: 1, negative: 1, sources: 1 }; - let high = Evidence { positive: 50, negative: 50, sources: 2 }; + let low = Evidence { + positive: 1, + negative: 1, + sources: 1, + }; + let high = Evidence { + positive: 50, + negative: 50, + sources: 2, + }; assert_eq!(low.frequency(), high.frequency()); assert!(high.nars_confidence() > low.nars_confidence()); - assert!(low.merge(low).is_none(), "do not double-count the same source"); + assert!( + low.merge(low).is_none(), + "do not double-count the same source" + ); } From 1d296248301b89a74e11dadcca6cb9990571f19a Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 22 Oct 2026 21:53:46 +0000 Subject: [PATCH 5/5] probe: fold #1720's production-surface test into this series Moves crates/causal-edge/tests/palette_bayes_nars_bnn_probe.rs here from #1720. Unlike the local helpers already in this series, it exercises the real implementation, so the series keeps its experiment contract and gains the concrete counter-probe. #1720 is closed as superseded once this lands. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01G22yT6htkcdyXsihxxXdrg --- .../tests/palette_bayes_nars_bnn_probe.rs | 63 +++++++++++++++++++ 1 file changed, 63 insertions(+) create mode 100644 crates/causal-edge/tests/palette_bayes_nars_bnn_probe.rs diff --git a/crates/causal-edge/tests/palette_bayes_nars_bnn_probe.rs b/crates/causal-edge/tests/palette_bayes_nars_bnn_probe.rs new file mode 100644 index 000000000..2fca35803 --- /dev/null +++ b/crates/causal-edge/tests/palette_bayes_nars_bnn_probe.rs @@ -0,0 +1,63 @@ +//! Bayesian predictive uncertainty is not NARS confidence by renaming. +use causal_edge::CausalEdge64; + +#[derive(Clone, Copy)] +struct Posterior { + successes: u32, + trials: u32, +} + +impl Posterior { + fn mean(self) -> f64 { + (self.successes as f64 + 0.5) / (self.trials as f64 + 1.0) + } + fn variance(self) -> f64 { + let a = self.successes as f64 + 0.5; + let b = (self.trials - self.successes) as f64 + 0.5; + a * b / ((a + b) * (a + b) * (a + b + 1.0)) + } +} + +#[test] +fn same_frequency_does_not_imply_same_uncertainty() { + let few = Posterior { + successes: 7, + trials: 10, + }; + let many = Posterior { + successes: 700, + trials: 1000, + }; + assert!((7.0_f64 / 10.0 - 700.0 / 1000.0).abs() < f64::EPSILON); + assert!(many.variance() < few.variance() / 50.0); + assert!((few.mean() - many.mean()).abs() < 0.02); +} + +#[test] +fn ce64_expectation_is_a_quantized_projection_not_the_count_carrier() { + let sample = Posterior { + successes: 7, + trials: 10, + }; + let mut edge = CausalEdge64(0); + edge.set_frequency_u8((255.0_f64 * 7.0 / 10.0).round() as u8); + edge.set_confidence_u8((255.0_f64 * 10.0 / 11.0).round() as u8); + assert!((edge.expectation() as f64 - sample.mean()).abs() < 0.01); + assert!(sample.variance() > 0.0); + // The sample size must be carried separately; the two u8 codes + // cannot recover an arbitrary exact 1000-observation history. +} + +#[test] +fn polarity_and_evidence_mass_are_independent_axes() { + let a = Posterior { + successes: 1, + trials: 2, + }; + let b = Posterior { + successes: 500, + trials: 1000, + }; + assert!((a.mean() - b.mean()).abs() < 1e-12); + assert!(a.variance() > b.variance() * 100.0); +}