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`. diff --git a/.claude/board/entries/README.md b/.claude/board/entries/README.md index 4d888f2b2..39f5f1f9d 100644 --- a/.claude/board/entries/README.md +++ b/.claude/board/entries/README.md @@ -25,11 +25,12 @@ 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. -434 entries, 2026-08-06 .. 2026-10-22. +436 entries, 2026-08-06 .. 2026-10-22. | date | entry id | finding | file | |---|---|---|---| | 2026-10-22 | `pal256-salience-mp3-probe` | | [2026-10-22-pal256-salience-mp3-probe.md](2026-10-22-pal256-salience-mp3-probe.md) | +| 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 | `pal256-immutable-needle-distribution-probe` | | [2026-10-22-pal256-immutable-needle-distribution-probe.md](2026-10-22-pal256-immutable-needle-distribution-probe.md) | | 2026-10-22 | `pal256-argextrema-margins` | | [2026-10-22-pal256-argextrema-margins.md](2026-10-22-pal256-argextrema-margins.md) | | 2026-10-22 | `pal256-3sigma-statistical-gate` | | [2026-10-22-pal256-3sigma-statistical-gate.md](2026-10-22-pal256-3sigma-statistical-gate.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 new file mode 100644 index 000000000..9768a2da2 --- /dev/null +++ b/crates/causal-edge/tests/palette256_nars_bayes_evidence_probe.rs @@ -0,0 +1,63 @@ +//! 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 + 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" + ); +}