From d4fb3075253eac219049bdcdd300467da1a8f27d Mon Sep 17 00:00:00 2001 From: Andy Dixon Date: Mon, 31 Aug 2026 22:11:19 +0100 Subject: [PATCH] refactor(cognition): one registry builder for daemon, harness and sandboxes The cognitive registry was assembled by hand in three places. Ablation experiments need the daemon, the test harness and replay sandboxes to name the same processes and hooks, so they now share cognition.NewRegistry; hooks are added only when their store exists, which keeps the harness's previous behaviour. --- cmd/noemad/main.go | 6 ++-- internal/cognition/registry.go | 45 +++++++++++++++++++++++++++ internal/replay/replaytest/harness.go | 4 +-- tests/harness/harness.go | 4 +-- 4 files changed, 49 insertions(+), 10 deletions(-) create mode 100644 internal/cognition/registry.go diff --git a/cmd/noemad/main.go b/cmd/noemad/main.go index 1d3c93e..9c88527 100644 --- a/cmd/noemad/main.go +++ b/cmd/noemad/main.go @@ -174,10 +174,8 @@ func run() error { deps.Consolidation = &consolidation.Service{DB: db, Memory: deps.Memory, Beliefs: deps.Beliefs, Events: deps.Events, LLM: deps.LLM, Prompts: deps.Prompts, Minds: deps.Minds, Log: log} deps.Dreaming = &dreaming.Service{DB: db, Memory: deps.Memory, Beliefs: deps.Beliefs, Events: deps.Events, LLM: deps.LLM, Prompts: deps.Prompts, Log: log} deps.Reflection = &reflection.Service{DB: db, Events: deps.Events, Beliefs: deps.Beliefs, Goals: deps.Goals, Memory: deps.Memory, Predictions: deps.Predictions, LLM: deps.LLM, Prompts: deps.Prompts, Log: log} - registry := brain.NewRegistry().AddProcess(cognition.Attend{}).AddProcess(cognition.Retrieve{}).AddProcess(cognition.Associate{}).AddProcess(cognition.Perceive{}). - AddProcess(cognition.GoalMonitor{}).AddProcess(cognition.Curiosity{}).AddProcess(cognition.Metacognition{}).AddProcess(cognition.Act{}). - AddHook(cognition.MotivationHook{Store: deps.Motivation}).AddHook(cognition.NarrativeHook{Store: deps.Narrative}).AddHook(cognition.NotifyHook{Store: deps.Notifications}) - cognition.Handlers{Memory: deps.Memory, Beliefs: deps.Beliefs, Conversations: deps.Conversations, Graph: deps.Graph, Assertions: deps.Assertions}.Register(registry) + registry := cognition.NewRegistry(cognition.Stores{Memory: deps.Memory, Beliefs: deps.Beliefs, Conversations: deps.Conversations, Graph: deps.Graph, Assertions: deps.Assertions, + Motivation: deps.Motivation, Narrative: deps.Narrative, Notifications: deps.Notifications}) brainCfg := brain.Config{DB: db, Events: deps.Events, Minds: deps.Minds, Registry: registry, Pool: scheduler.NewPool(cfg.MaxWorkers), Log: log, Metrics: metrics, Services: brain.Services{Events: deps.Events, Memory: deps.Memory, Beliefs: deps.Beliefs, LLM: deps.LLM, Prompts: deps.Prompts, Goals: deps.Goals, Motivation: deps.Motivation, Predictions: deps.Predictions, Capabilities: deps.Capabilities}} diff --git a/internal/cognition/registry.go b/internal/cognition/registry.go new file mode 100644 index 0000000..22a12d3 --- /dev/null +++ b/internal/cognition/registry.go @@ -0,0 +1,45 @@ +package cognition + +import ( + "github.com/andydixon/noema/internal/beliefs" + "github.com/andydixon/noema/internal/brain" + "github.com/andydixon/noema/internal/conversation" + "github.com/andydixon/noema/internal/epistemics" + "github.com/andydixon/noema/internal/graph" + "github.com/andydixon/noema/internal/memory" + "github.com/andydixon/noema/internal/motivation" + "github.com/andydixon/noema/internal/narrative" + "github.com/andydixon/noema/internal/notifications" +) + +// Stores bundles what the default processes, handlers and hooks write to. +// A nil store disables the parts that depend on it. +type Stores struct { + Memory *memory.Store + Beliefs *beliefs.Store + Conversations *conversation.Store + Graph *graph.Store + Assertions *epistemics.Store + Motivation *motivation.Store + Narrative *narrative.Store + Notifications *notifications.Store +} + +// NewRegistry assembles the cognitive registry. The daemon, the test harness +// and sandbox runtimes all call it, so they run the same cognition and an +// ablation names the same components everywhere. +func NewRegistry(s Stores) *brain.Registry { + r := brain.NewRegistry().AddProcess(Attend{}).AddProcess(Retrieve{}).AddProcess(Associate{}).AddProcess(Perceive{}). + AddProcess(GoalMonitor{}).AddProcess(Curiosity{}).AddProcess(Metacognition{}).AddProcess(Act{}) + if s.Motivation != nil { + r.AddHook(MotivationHook{Store: s.Motivation}) + } + if s.Narrative != nil { + r.AddHook(NarrativeHook{Store: s.Narrative}) + } + if s.Notifications != nil { + r.AddHook(NotifyHook{Store: s.Notifications}) + } + Handlers{Memory: s.Memory, Beliefs: s.Beliefs, Conversations: s.Conversations, Graph: s.Graph, Assertions: s.Assertions}.Register(r) + return r +} diff --git a/internal/replay/replaytest/harness.go b/internal/replay/replaytest/harness.go index f0c88d9..1338576 100644 --- a/internal/replay/replaytest/harness.go +++ b/internal/replay/replaytest/harness.go @@ -54,9 +54,7 @@ func NewHarness(t *testing.T) *Harness { for _, c := range capabilities.Builtins() { caps.Registry.Add(c) } - reg := brain.NewRegistry().AddProcess(cognition.Attend{}).AddProcess(cognition.Retrieve{}).AddProcess(cognition.Associate{}).AddProcess(cognition.Perceive{}). - AddProcess(cognition.GoalMonitor{}).AddProcess(cognition.Curiosity{}).AddProcess(cognition.Metacognition{}).AddProcess(cognition.Act{}) - cognition.Handlers{Memory: mem, Beliefs: bs, Conversations: conversation.NewStore(pool), Graph: graph.NewStore(pool), Assertions: epistemics.NewStore(pool)}.Register(reg) + reg := cognition.NewRegistry(cognition.Stores{Memory: mem, Beliefs: bs, Conversations: conversation.NewStore(pool), Graph: graph.NewStore(pool), Assertions: epistemics.NewStore(pool)}) cfg := brain.Config{DB: pool, Events: es, Minds: ms, Registry: reg, Pool: scheduler.NewPool(2), Log: log, Metrics: observability.NewMetrics(), Services: brain.Services{Events: es, Memory: mem, Beliefs: bs, Goals: goals.NewStore(pool), Motivation: motivation.NewStore(pool), Predictions: predictions.NewStore(pool), Capabilities: caps}} ident := &identity.Capturer{DB: pool, Minds: ms} diff --git a/tests/harness/harness.go b/tests/harness/harness.go index 28c0146..cc1f079 100644 --- a/tests/harness/harness.go +++ b/tests/harness/harness.go @@ -100,9 +100,7 @@ func Start(t *testing.T) *Harness { } group := scheduler.NewGroup(ctx, log) t.Cleanup(func() { group.Stop() }) - registry := brain.NewRegistry().AddProcess(cognition.Attend{}).AddProcess(cognition.Retrieve{}).AddProcess(cognition.Associate{}).AddProcess(cognition.Perceive{}). - AddProcess(cognition.GoalMonitor{}).AddProcess(cognition.Curiosity{}).AddProcess(cognition.Metacognition{}).AddProcess(cognition.Act{}) - cognition.Handlers{Memory: deps.Memory, Beliefs: deps.Beliefs, Conversations: deps.Conversations, Graph: deps.Graph, Assertions: deps.Assertions}.Register(registry) + registry := cognition.NewRegistry(cognition.Stores{Memory: deps.Memory, Beliefs: deps.Beliefs, Conversations: deps.Conversations, Graph: deps.Graph, Assertions: deps.Assertions}) deps.Brain = brain.NewManager(brain.Config{DB: pool, Events: deps.Events, Minds: deps.Minds, Registry: registry, Pool: scheduler.NewPool(2), Log: log, Metrics: deps.Metrics, Services: brain.Services{Events: deps.Events, Memory: deps.Memory, Beliefs: deps.Beliefs, LLM: deps.LLM, Prompts: deps.Prompts, Goals: deps.Goals, Motivation: deps.Motivation, Predictions: deps.Predictions, Capabilities: deps.Capabilities}}, group) if err := deps.Brain.Start(ctx); err != nil {