feat: add immutable cognitive event store, live streams and event explorer

Phase 3. Events are the append-only record of everything a mind does
(ADR-0002). pkg/events defines the closed type vocabulary, categories,
evidence references and the observation payload with explicit trust
levels. The store validates and appends inside the caller's transaction,
publishes to a bounded fan-out bus only after commit, queries by seq
cursor with type/category/source/salience/confidence/time/search
filters, and walks provenance: cause, parents, children, cited evidence,
derived events and correlation groups. Durable per-consumer cursors never
move backwards.

Server-Sent Events streams (per mind and global) subscribe before
replaying history after Last-Event-ID so nothing is missed, apply the
same filter vocabulary live, and heartbeat. Operators can inject
observations tagged with operator trust for demos and tests.

UI: live thought stream with filters and paging, forensic event page
with causal chain and evidence navigation, dashboard important events.
Personality and status changes now leave operator_action events in the
mind's own history. CLI: event inspect/list/tail, observe.
This commit is contained in:
Andy Dixon
2026-06-17 20:02:22 +01:00
parent fb34f08f40
commit 85d769b245
29 changed files with 1866 additions and 25 deletions
+6 -1
View File
@@ -1,11 +1,16 @@
{{define "content"}}
<div class="pagehead"><h1>Dashboard</h1><p class="muted">System overview. Minds, cognition and approvals appear here as they come online.</p></div>
<section class="grid cols-3">
<div class="card stat"><div class="stat-label">Running minds</div><div class="stat-value">{{.Data.Minds}}</div><div class="muted small">No minds yet. Create one under Minds.</div></div>
<div class="card stat"><div class="stat-label">Active minds</div><div class="stat-value">{{len .Data.Minds}}</div><div class="muted small">{{range .Data.Minds}}<a href="/minds/{{.Slug}}">{{.DisplayName}}</a> {{else}}No minds yet. Create one under Minds.{{end}}</div></div>
<div class="card stat"><div class="stat-label">System health</div><div class="stat-value">{{if .Data.Status.Database.OK}}<span class="ok">Healthy</span>{{else}}<span class="danger">Degraded</span>{{end}}</div><div class="muted small">Database {{if .Data.Status.Database.OK}}connected{{else}}unavailable{{end}} · up {{duration .Data.Status.UptimeSeconds}}</div></div>
<div class="card stat"><div class="stat-label">Outstanding approvals</div><div class="stat-value">0</div><div class="muted small">Capability layer arrives in a later phase.</div></div>
</section>
<section class="grid cols-2">
<div class="card">
<h2>Recent important events <span class="muted small">salience ≥ 0.6, all minds</span></h2>
{{if .Data.Events}}<table class="table compact"><tbody>{{range .Data.Events}}<tr><td class="nowrap muted small mono">{{.OccurredAt.Local.Format "15:04:05"}}</td><td><span class="etype cat-{{.Category}}">{{.Type}}</span></td><td><a href="/events/{{.ID}}">{{.Summary}}</a></td><td class="small muted">{{index $.Data.MindNames .MindID}}</td></tr>{{end}}</tbody></table>
{{else}}<p class="muted">Nothing yet.</p>{{end}}
</div>
<div class="card">
<h2>Recent administrative activity</h2>
{{if .Data.Audit}}