mixle.substrate.belief module

Calibrated belief store: harvest claims from model output and assimilate them as CREDENCES.

A model’s output is a paragraph of assertions – some grounded, some not. This module turns each assertion into a tracked belief with a probability (not a binary “fact” flag) that moves with the STRENGTH of its evidence: a verifiable source (a document, an executable check, a held-out truth, a real measurement) moves it strongly; the model’s own say-so moves it weakly and is capped low. Every belief carries its full evidence_history so the current credence is always reproducible by replaying it, and evidence can be revised or retract()-ed, cascading to whatever depended on it.

Anti-laundering is the load-bearing property: evidence that resolves back to the claim itself, or to another belief that has no independent (non-model-assertion) support of its own, contributes ZERO – a claim cannot bootstrap high credence by citing itself or an equally ungrounded peer.

A claimed tier is not itself evidence (MXR-080-0243): a strong tier only earns its full claimed strength when source_id actually resolves to something real – a document, an artifact, another belief, any genuine substrate item – checked once, at assimilation time, and recorded on the entry (EvidenceEntry.verified) so replay never needs the substrate again. An unresolved or fabricated source_id (missing, made up, or naming nothing in the store) is represented as unverified and earns only MODEL_ASSERTION-strength credence, no matter what tier it claims: a bare string is never, by itself, a receipt.

Resolution is scope-respecting, all the way down (MXR-080-0244): source_id is looked up through an AccessPolicy-authorized view of the caller’s own scope, never a raw global lookup, and every transitive hop of a multi-belief proof chain is resolved through that SAME authorized view – a caller can neither borrow another scope’s private grounding to inflate its own credence nor learn, by probing, whether some other scope’s belief happens to be grounded. An id that exists but is not visible to the caller is indistinguishable from one that does not exist at all.

This is the write side of the knowledge substrate: harvest, credence assimilation, and traceable history. The retrieval side is mixle.substrate.retrieve.

class Claim(text, produced_by=<factory>, quantity=None)[source]

Bases: object

One atomic proposition (or typed quantity) pulled from a model’s output.

Parameters:
class EvidenceEntry(source_id, tier, direction='+', weight=1.0, time=<factory>, verified=True)[source]

Bases: object

One piece of evidence that moved a belief’s credence, in the order it was applied.

verified records whether source_id resolved to something real, through an authorized scoped view, at the moment this entry was assimilated (MXR-080-0243/0244) – computed once, by assimilate(), and carried on the entry itself so credence_from_history() can replay it without ever touching the substrate again. Direct construction (tests, deserializing an already-decided entry) defaults to True, matching direction/weight/time’s own “already-legitimate input” defaults; assimilate() is the untrusted-input boundary and always computes and passes this explicitly rather than relying on the default.

Parameters:
class BeliefItem(id, claim, credence, evidence_history=<factory>, scope='local')[source]

Bases: object

A claim’s current credence plus the full evidence trail that produced it.

Parameters:
  • id (str)

  • claim (Claim)

  • credence (float)

  • evidence_history (list[EvidenceEntry])

  • scope (str)

harvest_knowledge(model_output, *, source, extract=None)[source]

Split model_output into atomic claims, each stamped with source (which model produced it, its confidence, etc). Default extraction is sentence-level (mixle.reason.llm.sentence_claims()); pass extract for a different atomic-proposition splitter.

Parameters:
Return type:

list[Claim]

credence_from_history(evidence_history)[source]

The credence implied by an evidence history alone – a pure function, so replaying a belief’s stored evidence_history through this always reproduces its current credence exactly.

An entry’s claimed tier only counts at its claimed strength when EvidenceEntry.verified is True (MXR-080-0243); an unverified claim of a strong tier contributes at MODEL_ASSERTION-strength instead, and does not count toward has_real_support (so it cannot, by itself, lift a belief past MODEL_ASSERTION_CAP) – otherwise merely CLAIMING a strong tier would escape the cap even though its actual numeric contribution never did.

Parameters:

evidence_history (Sequence[EvidenceEntry])

Return type:

float

assimilate(sub, claim, evidence, *, scope='local', policy=None)[source]

Bayesian-ish update of the belief in claim from evidence – never a binary write.

Finds or creates the belief item (keyed on normalized claim text) and appends each evidence entry ({"source_id", "tier", "direction": "+"/"-", "weight"}); tier must be one of _TIER_STRENGTH ("model_assertion" plus mixle.doe.oracle.VERIFIABILITY_TIERS), and direction, when given, must be "+" or "-" (MXR-080-0242).

Verification (MXR-080-0243): a tier above MODEL_ASSERTION only earns its claimed strength when source_id resolves to a real substrate item through an authorized view of scope (see _resolve()); an unresolved, fabricated, or omitted source_id is recorded as unverified and contributes at MODEL_ASSERTION-strength regardless of what it claims.

Anti-laundering (MXR-080-0244): an entry whose source_id resolves back to THIS belief (a cycle) or to another belief item with no independent (non-model-assertion, verified) support of its own is stored with an effective weight of zero – it cannot move the credence, though it stays in the trail for audit. Resolution – both the verification check above and the laundering check – goes through policy (a fresh, home-scope-plus-PUBLIC-only AccessPolicy when omitted), never a raw global lookup, so citing another scope’s private belief is indistinguishable from citing something that does not exist at all: neither the credence it produces nor anything else observable here can be used to learn whether that other scope’s belief exists or is grounded.

Parameters:
Return type:

BeliefItem

retract(sub, source_id, *, scope=None)[source]

Remove every evidence entry citing source_id, recomputing credence, and CASCADE: if that removal causes a belief to lose its only independent support, also strip citations of THAT belief from whatever cited it, recursively. Returns every belief item touched by the cascade.

Parameters:
  • sub (Substrate)

  • source_id (str)

  • scope (str | None)

Return type:

list[BeliefItem]

retrieve_beliefs(sub, query, *, k=8, min_credence=None, scope=None)[source]

Beliefs relevant to query, optionally thresholded on min_credence and re-ranked by relevance * credence – so a caller can weight by, or hard-filter on, how much the store actually believes each item (never a “fact” vs “non-fact” partition, only credence).

MXR-080-0245: the belief tag and min_credence are filtered over the FULL "record"-kind candidate domain, not a fixed-size prefetch – a store where ordinary (non-belief) records or low-credence beliefs rank higher by raw relevance can no longer crowd out qualifying beliefs that rank lower but still exist. sub.search still does the actual relevance scoring (this module never touches core.py’s ranking); the fix is asking it for every "record"-kind candidate in scope rather than an arbitrary 3*k cut of them.

Parameters:
  • sub (Substrate)

  • query (str)

  • k (int)

  • min_credence (float | None)

  • scope (str | None)

Return type:

list[BeliefItem]