From cd2db11367b8dc39d9b7cf2d9f2c7c9fca33998b Mon Sep 17 00:00:00 2001 From: Aaron Stainback Date: Fri, 24 Apr 2026 02:35:52 -0400 Subject: [PATCH] =?UTF-8?q?core:=20Veridicality=20=E2=80=94=20Provenance?= =?UTF-8?q?=20+=20Claim<'T>=20types=20+=20validateProvenance/Claim=20?= =?UTF-8?q?=E2=80=94=205th=20graduation?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Ships the foundation for the bullshit-detector / veridicality- scoring module — the `Provenance` and `Claim<'T>` input types plus the minimum-provenance-validity predicate from Amara's 10th ferry (PR #294 `docs/aurora/2026-04-23-amara-aurora-deep-research- report-10th-ferry.md`). Fifth graduation under the Otto-105 cadence. Naming (per Otto-112 memory feedback_veridicality_naming_for_ bullshit_detector_graduation_aaron_concept_origin_amara_ formalization_2026_04_24): - Module: `Veridicality` (NOT `BullshitDetector` — informal "bullshit" stays in comments/commit-message etymology, programmatic surface uses the formal term) - `Veridicality` = how true-to-reality a claim looks; the scorable. Bullshit = 1 - veridicality (informal). Attribution (two-layer per Otto-104/111/112 pattern): - Aaron = concept origin (bullshit-detector / provenance-aware- scoring framing present in bootstrap conversation at `docs/amara-full-conversation/**` before Amara's ferries formalized it; Aaron Otto-112: "bullshit, it was in our conversation history too, not just her ferry") - Amara = formalization (7th ferry veridicality formula V(c) = σ(β₀ + β₁(1-P) + ...), 8th ferry semantic-canonicalization "rainbow table" + quantum-illumination grounding, 9th/10th ferries 7-feature BS(c) composite + oracle-rule specification) - Otto = implementation (this and subsequent graduations) Surface: - Veridicality.Provenance record — 7 fields (SourceId, RootAuthority, ArtifactHash, BuilderId option, TimestampUtc, EvidenceClass, SignatureOk) matching Amara's 10th-ferry spec verbatim - Veridicality.Claim<'T> record — 4 fields (Id, Payload 'T, Weight int64, Prov) polymorphic over payload type - Veridicality.validateProvenance : Provenance -> bool — minimum-validity gate (non-empty SourceId/RootAuthority/ ArtifactHash + SignatureOk=true); matches Amara's snippet - Veridicality.validateClaim : Claim<'T> -> bool — convenience alias, wraps validateProvenance on claim's Prov Negative-Weight semantics (per Z-set retraction-native algebra): validateClaim does NOT inspect Weight; a retraction-claim (Weight = -1) is valid if its provenance is valid. Retraction semantics live at the ledger level, not the claim-validity level. Matches Zeta's existing ZSet signed-weight discipline (Otto-73 retraction-native-by-design). What this DOESN'T ship: - Veridicality scorer (Amara's V(c) / BS(c)) — next graduation - antiConsensusGate (needs Provenance; small follow-up) - SemanticCanonicalization (rainbow-table canonical-claim-key) - OracleVector (aggregated scoring vector) Tests (10, all passing): - validateProvenance: accepts fully-populated, rejects on each required-field violation, accepts BuilderId=None (not a hard gate) - validateClaim: wraps prov validation, polymorphic over Payload, rejects bad-prov claims - Claim supports negative Weight (retraction semantics) Build: 0 Warning / 0 Error. `dotnet test --filter FullyQualifiedName~Veridicality` reports 10/10 passed. SPOF consideration (per Otto-106): pure data types + pure validation function; no external deps; no SPOF introduced. Downstream scorers that combine provenance across many claims should use RobustStats.robustAggregate (PR #295) for outlier- resistant combination, not arithmetic mean. Composes with: - src/Core/RobustStats.fs (PR #295) — 1st graduation - src/Core/TemporalCoordinationDetection.fs (PR #297 + #298 + pending #306) — parallel module for the firefly-network arc Next graduation queue: - antiConsensusGate (10th ferry; uses Provenance) - SemanticCanonicalization / CanonicalClaimKey (8th ferry) - scoreVeridicality (Amara's V(c) or BS(c) composite — ADR needed) Co-Authored-By: Claude Opus 4.7 --- src/Core/Core.fsproj | 1 + src/Core/Veridicality.fs | 121 ++++++++++++++++++ .../Algebra/Veridicality.Tests.fs | 96 ++++++++++++++ tests/Tests.FSharp/Tests.FSharp.fsproj | 1 + 4 files changed, 219 insertions(+) create mode 100644 src/Core/Veridicality.fs create mode 100644 tests/Tests.FSharp/Algebra/Veridicality.Tests.fs diff --git a/src/Core/Core.fsproj b/src/Core/Core.fsproj index e43b4c64..3fc6e80f 100644 --- a/src/Core/Core.fsproj +++ b/src/Core/Core.fsproj @@ -41,6 +41,7 @@ + diff --git a/src/Core/Veridicality.fs b/src/Core/Veridicality.fs new file mode 100644 index 00000000..8b62832d --- /dev/null +++ b/src/Core/Veridicality.fs @@ -0,0 +1,121 @@ +namespace Zeta.Core + +open System + + +/// **Veridicality — provenance-aware claim scoring (foundation).** +/// +/// This module hosts the primitives for what the bootstrap-era +/// conversation called the "bullshit detector" and Amara's +/// subsequent ferries (7th-10th) formalized as veridicality +/// scoring. The name `Veridicality` (from Latin *veridicus*, +/// "truth-telling") names the scorable quantity: how true-to- +/// reality a claim looks given its provenance, falsifiability, +/// coherence, drift, and compression-gap signals. "Bullshit" is +/// the informal inverse (`bullshit = 1 - veridicality`). +/// +/// **First graduation (this file):** `Provenance` + `Claim<'T>` +/// record types + `validateProvenance`. These are the input +/// shapes for every downstream scorer. The actual veridicality +/// scorer (`V(c) = σ(β₀ + β₁(1-P) + β₂(1-F) + β₃(1-K) + …)` from +/// Amara's 7th ferry, or `BS(c) = σ(w₁·C + w₂·(1-P) + …)` from +/// the 10th ferry) is a separate graduation that composes over +/// these types. +/// +/// **Attribution.** +/// * **Concept** — the bullshit-detector / provenance-aware- +/// scoring framing is Aaron's design, present in the bootstrap +/// conversation (`docs/amara-full-conversation/**`) before +/// Amara's ferries formalized it. Aaron 2026-04-24 Otto-112: +/// *"bullshit, it was in our conversation history too, not +/// just her ferry."* +/// * **Formalization** — Amara (7th/8th/9th/10th ferries): +/// veridicality formula, semantic-canonicalization "rainbow +/// table", oracle-rule specification, 7-feature composite. +/// * **Implementation** — Otto, under the Otto-105 graduation +/// cadence. Fifth graduation. +/// +/// Future graduations add (in priority order): `antiConsensusGate` +/// (requires `Provenance`); `canonicalizeClaim` (semantic +/// canonicalization → `CanonicalClaimKey`); `scoreVeridicality` +/// (the composite function). +[] +module Veridicality = + + /// **Provenance** — the evidence trail behind a claim. + /// + /// Every accepted claim MUST carry provenance with at minimum + /// `SourceId`, `RootAuthority`, `ArtifactHash`, and + /// `SignatureOk = true`. Empty-string `SourceId` or + /// `RootAuthority`, empty `ArtifactHash`, or `SignatureOk = + /// false` all indicate unverified or missing evidence. + /// + /// Fields match Amara's 9th/10th ferry specification verbatim + /// (`docs/aurora/2026-04-23-amara-aurora-deep-research- + /// report-10th-ferry.md` §ADR-style spec for oracle rules and + /// implementation). + /// + /// `RootAuthority` vs `SourceId`: a single source may speak + /// under different authorities (a mailing list, an academic + /// publication, a company blog), and consumers of the claim + /// need both to distinguish "two sources, same root + /// authority" (anti-consensus-gate failure) from "two sources, + /// two independent roots" (anti-consensus-gate pass). + type Provenance = + { SourceId: string + RootAuthority: string + ArtifactHash: string + BuilderId: string option + TimestampUtc: DateTimeOffset + EvidenceClass: string + SignatureOk: bool } + + /// **Claim<'T>** — a piece of information with a payload, + /// a weight (matches the Z-set weight model for retraction- + /// native semantics), and its provenance. + /// + /// `Id` is the claim's identity in the claim ledger. `Payload` + /// is the domain-specific information being claimed (a string, + /// a record, a numeric oracle reading — whatever the caller + /// has). `Weight` is a signed multiplicity: positive for + /// assertion, negative for retraction. Total net-zero after + /// assertion+retraction matches Z-set semantics. + type Claim<'T> = + { Id: string + Payload: 'T + Weight: int64 + Prov: Provenance } + + /// **Validate provenance** — returns `true` when the + /// provenance has the minimum fields populated + a valid + /// signature. Returns `false` on empty-string `SourceId`, + /// `RootAuthority`, or `ArtifactHash`, or when `SignatureOk + /// = false`. + /// + /// Matches Amara's 10th-ferry snippet: + /// + /// ``` + /// let validateProvenance c = + /// c.Prov.SourceId <> "" + /// && c.Prov.RootAuthority <> "" + /// && c.Prov.ArtifactHash <> "" + /// && c.Prov.SignatureOk + /// ``` + /// + /// `BuilderId = None`, `TimestampUtc`, and `EvidenceClass` + /// are NOT checked by this predicate — they are evidence + /// quality signals that downstream scorers consume, not + /// hard validity gates. An unsigned artifact with known + /// source/root/hash is still rejected, because cryptographic + /// attestation is the minimum trust bar. + let validateProvenance (p: Provenance) : bool = + p.SourceId <> "" + && p.RootAuthority <> "" + && p.ArtifactHash <> "" + && p.SignatureOk + + /// Convenience alias for `validateProvenance` on a full + /// `Claim<'T>`, matching Amara's 10th-ferry snippet which + /// takes a claim rather than bare provenance. + let validateClaim (c: Claim<'T>) : bool = + validateProvenance c.Prov diff --git a/tests/Tests.FSharp/Algebra/Veridicality.Tests.fs b/tests/Tests.FSharp/Algebra/Veridicality.Tests.fs new file mode 100644 index 00000000..a9c9ff37 --- /dev/null +++ b/tests/Tests.FSharp/Algebra/Veridicality.Tests.fs @@ -0,0 +1,96 @@ +module Zeta.Tests.Algebra.VeridicalityTests + +open System +open FsUnit.Xunit +open global.Xunit +open Zeta.Core + + +// ─── Provenance / validateProvenance ───────── + +let private goodProv () : Veridicality.Provenance = + { SourceId = "repo/amara/ferry-10" + RootAuthority = "amara@aurora" + ArtifactHash = "blake3:3f8e..." + BuilderId = Some "otto-115" + TimestampUtc = DateTimeOffset.UtcNow + EvidenceClass = "research" + SignatureOk = true } + +[] +let ``validateProvenance accepts a fully-populated signed provenance`` () = + Veridicality.validateProvenance (goodProv ()) |> should equal true + +[] +let ``validateProvenance rejects empty SourceId`` () = + let p = { goodProv () with SourceId = "" } + Veridicality.validateProvenance p |> should equal false + +[] +let ``validateProvenance rejects empty RootAuthority`` () = + let p = { goodProv () with RootAuthority = "" } + Veridicality.validateProvenance p |> should equal false + +[] +let ``validateProvenance rejects empty ArtifactHash`` () = + let p = { goodProv () with ArtifactHash = "" } + Veridicality.validateProvenance p |> should equal false + +[] +let ``validateProvenance rejects SignatureOk = false`` () = + let p = { goodProv () with SignatureOk = false } + Veridicality.validateProvenance p |> should equal false + +[] +let ``validateProvenance accepts BuilderId = None (not a hard gate)`` () = + // BuilderId is a quality signal, not a validity gate. An + // artifact can be legitimately signed without a builder + // identity (e.g., a human-authored doc signed with a personal + // key). + let p = { goodProv () with BuilderId = None } + Veridicality.validateProvenance p |> should equal true + + +// ─── Claim<'T> / validateClaim ───────── + +[] +let ``validateClaim wraps validateProvenance on the claim's provenance`` () = + let c = + { Id = "claim-001" + Payload = 42 + Weight = 1L + Prov = goodProv () } + Veridicality.validateClaim c |> should equal true + +[] +let ``validateClaim is polymorphic over the Payload type`` () = + // Same validation whether payload is int, string, record, etc. + // The provenance discipline doesn't depend on payload shape. + let c = + { Id = "claim-002" + Payload = "Zeta is a retraction-native substrate." + Weight = 1L + Prov = goodProv () } + Veridicality.validateClaim c |> should equal true + +[] +let ``validateClaim rejects a claim with invalid provenance`` () = + let c = + { Id = "claim-003" + Payload = () + Weight = 1L + Prov = { goodProv () with SignatureOk = false } } + Veridicality.validateClaim c |> should equal false + +[] +let ``Claim supports negative Weight for retraction semantics`` () = + // Z-set style: negative weight = retraction. validateClaim + // does NOT inspect Weight; a retraction claim is valid if its + // provenance is valid. Retraction semantics are at the ledger + // level, not the claim-validity level. + let c = + { Id = "claim-004" + Payload = 7 + Weight = -1L + Prov = goodProv () } + Veridicality.validateClaim c |> should equal true diff --git a/tests/Tests.FSharp/Tests.FSharp.fsproj b/tests/Tests.FSharp/Tests.FSharp.fsproj index f9e64744..9c6d4286 100644 --- a/tests/Tests.FSharp/Tests.FSharp.fsproj +++ b/tests/Tests.FSharp/Tests.FSharp.fsproj @@ -19,6 +19,7 @@ +