feat(beliefs): source reliability by domain, never global
A source's track record is kept per (evidence family, belief subject) and updated only by outcomes: predictions derived from a belief resolving, and operators marking a belief wrong. With three or more outcomes in a domain the record adjusts the credibility of that source's new evidence in that domain, and the adjustment is written on the evidence row. Standing in one domain never moves standing in another, and the trust-level credibility constants are never rewritten. Migration 0021 is additive; belief pages show each cited family's record in the belief's domain.
This commit is contained in:
@@ -175,8 +175,12 @@ func (s *Store) Create(ctx context.Context, q storage.Querier, emit Emitter, n N
|
||||
return Result{}, fmt.Errorf("%w: %s", ErrBlocked, c.Statement)
|
||||
}
|
||||
var ev []Evidence
|
||||
var notes []string
|
||||
for _, e := range n.Evidence {
|
||||
ev = append(ev, normalise(e))
|
||||
ne := normalise(e)
|
||||
ne, note := s.applyReliability(ctx, q, n.MindID, strings.TrimSpace(n.Subject), ne, e.Note)
|
||||
ev = append(ev, ne)
|
||||
notes = append(notes, note)
|
||||
}
|
||||
prior := PriorFor(n.Epistemic)
|
||||
bd := Compute(prior, ev)
|
||||
@@ -220,8 +224,8 @@ func (s *Store) Create(ctx context.Context, q storage.Querier, emit Emitter, n N
|
||||
return Result{}, err
|
||||
}
|
||||
res := Result{Belief: b, Breakdown: bd, Events: []events.Event{created}}
|
||||
for _, e := range n.Evidence {
|
||||
if err := s.insertEvidence(ctx, q, b, normalise(e), e.Note, created.ID); err != nil {
|
||||
for i, e := range ev {
|
||||
if err := s.insertEvidence(ctx, q, b, e, notes[i], created.ID); err != nil {
|
||||
return Result{}, err
|
||||
}
|
||||
}
|
||||
@@ -425,7 +429,8 @@ func (s *Store) AddEvidence(ctx context.Context, q storage.Querier, emit Emitter
|
||||
return Result{}, fmt.Errorf("%w: belief is superseded", ErrInvalid)
|
||||
}
|
||||
e := normalise(in)
|
||||
if err := s.insertEvidence(ctx, q, b, e, in.Note, ids.Nil); err != nil {
|
||||
e, note := s.applyReliability(ctx, q, mind, b.Subject, e, in.Note)
|
||||
if err := s.insertEvidence(ctx, q, b, e, note, ids.Nil); err != nil {
|
||||
return Result{}, err
|
||||
}
|
||||
return s.reevaluate(ctx, q, emit, b, reason, causation, correlation, &e, in)
|
||||
@@ -617,6 +622,11 @@ func (s *Store) Retract(ctx context.Context, emit Emitter, mind, id ids.ID, reas
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// An operator saying "wrong" is an outcome for the sources that backed
|
||||
// it, in this belief's domain only: nobody's standing elsewhere moves.
|
||||
if err := s.RecordBeliefOutcome(ctx, tx, mind, id, false); err != nil {
|
||||
return err
|
||||
}
|
||||
ev, err := emit(ctx, tx, events.New{MindID: mind, Type: events.BeliefRetracted, Source: "operator", Summary: fmt.Sprintf("operator %s rejected belief: %s (%s)", by, b.Proposition, reason),
|
||||
Salience: 0.7, Confidence: 1, Evidence: []events.EvidenceRef{{Kind: "belief", ID: string(b.ID)}},
|
||||
Metadata: map[string]any{"belief_id": string(b.ID), "actor": by, "do_not_infer": doNotInfer}, Payload: map[string]any{"belief_id": b.ID, "proposition": b.Proposition, "reason": reason, "previous": map[string]any{"confidence": b.Confidence, "status": b.Status}}})
|
||||
|
||||
Reference in New Issue
Block a user