feat(epistemics): record assertions between observations and beliefs

A statement made to a mind is now three things kept apart: the observation
that it arrived, an append-only assertion (attributed actor, stance,
certainty, modality, negation, reported or quoted speech, hypothetical
status, interpretation confidence and notes), and, only for factual
assertions, one piece of evidence for a proposition belief attributed to
whoever actually stands behind it. Reported speech is attributed to the
person reported and weighed as second-hand; hypotheticals, questions and
imperatives create no belief; expressed doubt counts against; a possibly
sarcastic remark is recorded with low interpretation confidence rather
than guessed at. Interpretation is deterministic code; a model may enrich
the claim list but never sets stance or confidence.

Association no longer treats conversational turns as world events:
hypotheticals, questions, requests and consecutive turns by one speaker
cannot seed causal hypotheses.

Adds internal/epistemics, migration 0018, the assertions API, assertions
on belief pages and in belief detail, a shared end-to-end test harness
(tests/harness), end-to-end tests for eight speech patterns, and updates
the milestone test to the new provenance.
This commit is contained in:
Andy Dixon
2026-08-05 19:22:48 +01:00
parent 0071658c93
commit 9b2521bffd
28 changed files with 1447 additions and 325 deletions
+4
View File
@@ -26,6 +26,10 @@
{{if $bd.Families}}<h3 class="small muted">Independent sources</h3><table class="table compact"><thead><tr><th>Family</th><th></th><th class="num">Items</th><th class="num">Primary</th><th class="num">Counts as</th></tr></thead><tbody>{{range $bd.Families}}<tr><td><code>{{.Family}}</code></td><td class="small">{{.Direction}}</td><td class="num">{{.Items}}</td><td class="num">{{.Primary}}</td><td class="num">{{printf "%.2f" .Contribution}}</td></tr>{{end}}</tbody></table><p class="small muted">Within a family the strongest primary item counts in full and further items add a quarter each (capped at 1.5×); derived items count only when the family has no primary item. Diversity counts families: {{$bd.SourcesFor}}.</p>{{end}}
</div>
<div class="card">
{{if $d.Assertions}}<h2>Who said so</h2>
<ul class="plain ev">{{range $d.Assertions}}<li><div><strong>{{.AttributedTo}}</strong> {{.Stance}} it <span class="badge small">{{.Modality}}</span> <span class="badge small">{{.Certainty}}</span>{{if .Reported}} <span class="badge small warn" title="second-hand: relayed by {{.Actor}}">reported by {{.Actor}}</span>{{end}}{{if .Hypothetical}} <span class="badge small">hypothetical</span>{{end}}{{if .Negated}} <span class="badge small">negated</span>{{end}}</div>
<div class="muted small">interpretation confidence {{pct .Interpretation}}{{range .Notes}} · {{.}}{{end}} · {{ago .CreatedAt}}{{if .SourceEvent}} · <a href="/events/{{.SourceEvent}}">message</a>{{end}}</div></li>{{end}}</ul>
<p class="small muted">An assertion records that somebody took a stance. Its confidence is about the reading, not the proposition; the proposition's score is above and rests on the evidence listed.</p>{{end}}
<h2>Evidence against</h2>
<ul class="plain ev">{{range $d.Evidence}}{{if eq .Direction "against"}}<li class="{{if .Retracted}}retracted{{end}}"><div><strong>{{conf .Weight}}</strong> × cred {{conf .Credibility}} <span class="badge">{{.Kind}}</span></div><div>{{.Note}}</div><div class="muted small">{{.Source}} · {{ago .CreatedAt}} {{if and (eq .Kind "belief") .RefID}}· <a href="/minds/{{$m.Slug}}/beliefs/{{.RefID}}">belief</a>{{else if and (eq .Kind "event") .RefID}}· <a href="/events/{{.RefID}}">event</a>{{end}}</div></li>{{end}}{{else}}<li class="muted">None.</li>{{end}}</ul>
</div>