feat(beliefs): temporal scope and validity; state changes supersede rather than contradict

Beliefs gain a temporal scope (persistent, transient or unknown, classified
deterministically from the proposition), an observation time and, for
transient states, a validity interval. When a newer belief conflicts with
an older transient one observed at least a minute earlier, the older belief
is closed (valid_until set, status superseded, a supersedes link, a version
and an event saying 'state changed') with its score untouched: 'the door
was open at 10:00' stays true of 10:00 when it is closed at 10:05.
Simultaneous conflicting reports and persistent propositions contradict as
before. Introspection lists superseded states with their validity.
Migration 0020 is additive.
This commit is contained in:
Andy Dixon
2026-08-09 21:42:19 +01:00
parent b661496128
commit 7821d89cf5
9 changed files with 256 additions and 8 deletions
+13 -1
View File
@@ -123,7 +123,8 @@ func (h Handlers) perceive(ctx context.Context, c *brain.Cycle, t workspace.Thou
Note: actor + " doubts it", Derivation: beliefs.DerivationAssertion, Family: beliefs.FamilyForActor(actor), RootIDs: []string{srcID}})
}
var err error
res, err = h.Beliefs.Create(ctx, c.Tx, emitter(c), beliefs.New{MindID: mind.ID, Proposition: in.Proposition, Epistemic: concepts.Claim, Source: "conversation", OriginEvent: perc.ID, Causation: perc.ID, Correlation: c.State.CycleID, Evidence: ev,
observed := c.State.Now
res, err = h.Beliefs.Create(ctx, c.Tx, emitter(c), beliefs.New{MindID: mind.ID, Proposition: in.Proposition, Epistemic: concepts.Claim, Source: "conversation", OriginEvent: perc.ID, Causation: perc.ID, Correlation: c.State.CycleID, Evidence: ev, ObservedAt: &observed,
Detail: map[string]any{"attributed_to": attributed, "reported": in.Reported, "interpretation_confidence": in.Confidence}})
if err != nil {
c.Emit(events.New{Type: events.Metacognition, Source: "brain.perceive", Summary: "claim not recorded: " + err.Error(), Salience: 0.3, Confidence: 1, Metadata: map[string]any{"check": "claim_rejected"}})
@@ -304,6 +305,17 @@ func (h Handlers) addKnowledge(ctx context.Context, c *brain.Cycle, in *Intent,
in.Uncertainty = fmt.Sprintf("The strongest relevant belief is only at %.2f.", maxConf)
}
}
// Historical truth is not overwritten by the present: say what was
// true and when, alongside what is believed now.
if past, _ := h.Beliefs.History(ctx, mind, topic, 3); len(past) > 0 {
for _, b := range past {
from := "earlier"
if b.ValidFrom != nil {
from = b.ValidFrom.Format("15:04 on 2 Jan")
}
in.Points = append(in.Points, fmt.Sprintf("Earlier: %s (true from %s until %s, then superseded).", b.Proposition, from, b.ValidUntil.Format("15:04 on 2 Jan")))
}
}
}
if h.Memory != nil {
if hits, _ := h.Memory.Retrieve(ctx, mind, memory.Query{Text: topic, Limit: 4, Now: c.State.Now, Semantic: true}); len(hits) > 0 {