Commit Graph
21 Commits
Author SHA1 Message Date
Andy Dixon 67a825a995 docs: static documentation site generator and authored pages
Twenty-six pages covering concepts, architecture, every subsystem, an
interface tour with screenshots, the full API route table generated from
openapi.json, the CLI, security and threat model, operations, ADRs,
development history and a glossary. Built into the dixon.cx page skeleton,
unlinked and noindex.
2026-07-07 23:34:55 +01:00
Andy Dixon d9ae91e406 Close the plan: screenshots and a measured performance pass
- docs/screenshots: nineteen pages captured with headless Chromium from a
  running instance; README gains a screenshot section
- tests/perf: opt-in load test (NOEMA_PERF=1) seeding 60k events, 6k
  memories and 1.5k beliefs across two minds, timing sixteen hot reads
  against a 400 ms ceiling and rejecting sequential-scan plans
- migration 0016: indexes the test found missing (memories by mind and
  recency, beliefs by mind and confidence, events by mind and category,
  belief versions by mind and time)
- docs/performance.md records the numbers and how to rerun
2026-07-06 23:18:31 +01:00
Andy Dixon 89580c0a79 Phase 16: hardening and release 0.1.0
- TOTP second factor (RFC 6238, secret encrypted under the master key),
  ten hashed single-use recovery codes, two-step login with a pending token
  bound to the client address, account enrolment/disable, admin reset
- tests/security: prompt-injection corpus never acts or creates evidence-free
  beliefs; roles and CSRF on form and API paths; cross-mind isolation
  (demo scenario 5); stored-XSS escaping and CSP across pages; secrets never
  echoed (API, pages, database, archives); hostile archive import; session
  lifecycle and security headers
- OpenAPI 3.1 document generated from the route table, served at
  /api/v1/openapi.json and kept complete by a test
- gosec clean (justified #nosec annotations, cookie/redirect hardening,
  bounded multipart parsing, UUID packing without narrowing conversions);
  govulncheck clean with toolchain pinned to go1.26.8
- THREAT_MODEL verification pointers, SECURITY.md testing section, README,
  CHANGELOG 0.1.0, docs/RELEASE_NOTES.md, PLAN status
2026-07-05 22:30:32 +01:00
Andy Dixon 072422d916 Phase 15: snapshots, forks, export/import, cognitive replay, experiments
- snapshots: checksummed JSON archive of every mind-scoped state table plus
  identity/personality/config and the event position; stored, downloadable
- fork: restore into a new mind with all ids remapped; event references are
  kept so history before the fork is shared by reference
- export/import: same archive; import is hostile-input validated (size,
  allow-listed tables, row caps, column names, checksum, forced mind_id)
- compare: deterministic counts, belief diffs by proposition, personality
  and config diffs, event mix
- replay: Runtime.Step for synchronous drivers; sandbox fork driven one
  stimulus at a time under a forbidden capability context; recorded model
  responses via a replaying router; steps labelled exact / approximate /
  diverged with recorded-vs-replayed digests
- experiments: definition (overrides, stimuli, expectations, seed, duration),
  background run in a disabled subject mind, stored and exportable results
- migration 0015, API, UI (Snapshots and Replay tabs, Experiments section,
  compare page), noemactl snapshots/compare/replay/experiments, docs
2026-07-03 22:12:31 +01:00
Andy Dixon 2ac8752bac Phase 14: dreaming as an opt-in, budgeted, non-acting idle mode
- dreaming.Service: deterministic memory replay sample keyed by dream id,
  vocabulary-based association of unlinked memory pairs (similar_to edges +
  dream_association events), speculative hypotheses as hypothesis-kind beliefs
  with two weak memory citations (starts ~0.30, asserted <= 0.35)
- Run marks the context forbidden for capabilities before anything else;
  test proves Invoke refuses inside a dream
- per-mind settings: enabled (default off), hours window (wraps midnight),
  interval, model-call / memory / hypothesis caps; global pause switch
- optional model wording via new `dream` prompt (role hypothesise)
- promotion adds operator evidence, rejection retracts the belief; both
  audited and recorded as operator actions
- migration 0014, API, Dreams tab and page, noemactl dreams, docs/dreaming.md
2026-07-01 21:12:13 +01:00
Andy Dixon 89edbb7c06 Phase 13: integrations (research folder, git, Prometheus, signed webhooks)
Adds the integration layer that turns external sources into provenance-tagged
observations without ever executing what it reads.

- research folder poller: os.OpenRoot, text allowlist, binary/archive/symlink
  rejection, content fingerprints, duplicate tracking
- git poller: bare shallow mirror with hooks disabled and ext protocol refused,
  commit observations, co-change pairs
- Prometheus poller: threshold crossings and relative-change detection
- webhooks: HMAC over timestamp.body, +/-300s window, replay cache, 256 KiB cap,
  per-IP rate limit; refused entirely without a secret
- capabilities read_metrics (allow) and repository.read (ask), scoped to the
  invoking mind's integrations
- migrations 0013, API, UI pages, noemactl integrations, docs/integrations.md
2026-06-29 21:04:50 +01:00
Andy Dixon b35dbe0299 security: add the capability and policy layer as the only path to action
Phase 12 (ADR-0005). Capabilities are registered in code with parameter
schemas, risk classes and default effects; sudo_shell and delete_database
are locked to DENY and cannot be relaxed. Policies are scoped globally or
per mind with capability, target glob, action kind and optional hour
window; evaluation is deterministic, most specific wins, and ties go to
the stricter effect. Invoke is the single entry point: it refuses
dreaming and replay contexts, validates parameters (unknown keys, non
http URLs and path traversal rejected), evaluates policy and session
grants, hashes the exact request and records a policy_decision event.
ALLOW executes with timeout and panic isolation and turns textual output
into a tool-trust observation; ASK creates an approval request bound to
the hash with an alert notification; DENY is counted and recorded.

Operators approve once, approve for a time-boxed session grant, deny
with a note, or modify parameters (re-validated, re-hashed, original
kept in the append-only decision log). The self-model's capability list
is recomputed from effective policy on start and on every policy change.
The act process maps fetch requests to http.fetch and the action handler
invokes through the layer; replies report capabilities and outcomes.

Policy matrix and approval centre pages, dashboard count, API, CLI
(approvals, policy, invoke) and docs/capabilities.md.
2026-06-29 20:28:05 +01:00
Andy Dixon 99a89ba847 feat: add the relationship graph with extraction, corrections and explorer
Phase 11. Entities are mind-scoped nodes with canonical matching,
aliases and deterministic kind guessing (hostnames and hyphenated ids
are systems, capitalised names people, file suffixes documents).
Relationships carry a relation from the shared vocabulary, confidence,
source, reinforcement count and the event that produced them; links tie
entities to memories, beliefs, events, goals and predictions.

The perceive and attend handlers upsert the entities a message or
observation mentions and record co-mention edges cited to the event, so
the graph grows only from what was actually seen. Operators can merge
("these are the same": edges and links move, the old name becomes an
alias, the old id still resolves), record that two entities are
different, correct kinds and add typed edges; every correction is an
operator action and a corrections row.

The explorer renders a bounded subgraph on a canvas with a small
force-directed layout in plain JavaScript, with kind filters, focus on
a neighbourhood and a side panel per entity. API, entity page, CLI and
docs/graph.md.
2026-06-29 19:28:55 +01:00
Andy Dixon 703d080d13 feat: add metacognition, reflection, consolidation, narrative and notifications
Phase 10. Metacognition is a cognitive process with deterministic
self-checks (insufficient evidence, single-source reliance, model output
without evidence, repeated failed hypotheses, stale contradictions,
calibration overconfidence); its warnings compete for attention and,
when admitted, add counter-evidence or open an investigation goal.

Reflection reviews the period since the last run (prediction errors,
rejected beliefs, corrections, status changes, completed goals,
contradictions, calibration), turns repeated failures into procedural
lessons written once, and records a reflection event; a model may only
word the prose within the mind's budget.

Consolidation clusters unconsolidated episodes by shared stemmed terms,
creates a belief whose confidence is computed from the episodes as
evidence and a semantic memory linked to each episode by derived_from,
and records jobs with inputs and outputs. Wording may come from the
consolidate prompt within a per-run model budget; the job says which.
Operators can run, pause and reject; originals are never touched.

The narrative hook keeps a five-part first-person narrative built from
state and stored with narrative_updated events. The notification hook
applies explicit thresholded rules, aggregates repeats within a cooldown
and records suppressions with reasons. A scheduled job runs
consolidation and reflection per mind, switching the runtime mode while
it works. API, Background tab, notifications page with unread badge,
overview narrative and warnings, CLI commands, docs/cognition.md.
2026-06-28 22:19:38 +01:00
Andy Dixon 9eb873cbe6 feat: add goals, drives, affect state, predictions and curiosity
Phase 9. Goals form a mind-scoped tree with kind, priority, progress and
blockers; their deterministic relevance to a candidate feeds the
goal_relevance attention feature and a goal monitor raises stalled goals
and observations that touch one. Drives are a closed set of eight
scalars with operator-configured ranges and personality-derived
baselines; there is no self-preservation, replication or acquisition
drive and no way to add one at runtime. Affect is ten scalars moved by an
explicit rule table over events and decaying towards baseline; both
modulate attention weights each cycle and the effective weights are
recorded with every cycle and shown beside the configured ones.

Predictions carry a window and machine-checkable criteria (event terms
occurring or staying absent, a belief reaching a confidence, or operator
judgement). A resolver job judges them deterministically, keeps an
append-only outcome history for calibration (accuracy, Brier score,
confidence buckets, overconfidence flag), emits prediction_error events
scaled by how confident the miss was, and feeds the outcome back into the
linked belief as evidence. Causal hypotheses derive predictions
automatically. Curiosity turns misses, contradictions and unexplained
observations into questions that compete for attention and become
investigation goals when admitted.

Brain gains after-cycle hooks and goal/motivation state. API, UI (goals,
prediction dashboard, cognitive state panel, effective weights) and CLI
(goal, prediction, state). Demo scenario 4 verified end to end.
2026-06-27 20:41:03 +01:00
Andy Dixon 777e8f50b5 feat: add conversation with grounded replies, sample mind and M1 acceptance test
Phase 8, completing milestone M1. A user message is stored and appended
as an observation event carrying trust, actor, channel and reference. The
perceive process analyses it deterministically (intent, introspection
kind, entities, claims, urgency) and, within the per-cycle model
allowance, enriches it through the perceive prompt. Its handler writes a
perception event, an episodic memory with participants, turns claims into
beliefs whose evidence is the message, and builds a response intent from
state: beliefs and memories for the topic, evidence rows for why-questions,
the uncertain band, contested beliefs and their links, recent learning,
status changes, and honest declines for subsystems that do not exist yet
or for requests with no capabilities. The respond prompt phrases the
intent when a model is assigned; otherwise the reply is a direct
rendering of the intent. response_generated cites the message, the
perception, every belief and memory used, the episode and the model call.

API: conversations, messages with optional wait, one-shot ask; chat UI
with live refresh and a per-reply intent view. Sample mind Dani as a
strictly decoded seed document with an import endpoint and noemactl mind
import. tests/m1 drives all fourteen milestone steps including restart.
2026-06-25 19:19:24 +01:00
Andy Dixon d9c6ffa30f feat: add provider-neutral LLM layer with secrets, budgets, recording and prompts
Phase 7 (ADR-0004). Cognitive code asks the router for a role; the
router maps roles to configured models with ordered fallbacks, applies
global and per-mind daily token budgets and a concurrency limit, records
every call (request, response, usage, latency, cost, seed, request hash)
and can serve recordings back for exact replay. Providers are raw HTTP
clients for OpenAI-compatible, Anthropic and Ollama endpoints, with
embedding support for the embed role wired into memory retrieval.

Secrets are references only: env:, file:, or enc: values encrypted with
AES-256-GCM under NOEMA_MASTER_KEY; keys are resolved at call time and
never rendered, logged or exported. Outbound HTTP refuses private and
loopback addresses at dial time unless a provider explicitly allows it,
bounds redirects and caps bodies. Provider errors are scrubbed.

Prompts are named, versioned rows with system and user templates and an
optional JSON schema; untrusted text enters only through delimited data
blocks. Six defaults are seeded and never overwritten. The UI adds the
LLM page (providers, models, role matrix, usage, errors, budgets), a
provider page with connectivity test, and a prompt manager with editor,
test runner, history, restore, clone and diff. CLI: provider, prompt.
2026-06-23 23:43:33 +01:00
Andy Dixon 0b790f34c7 fix: let fresh causal hypotheses compete with fading recalls
Association candidates scored below decayed workspace residents and were
always rejected in a small workspace. Raise their novelty, consequence
and operator-priority features so a new hypothesis outranks a stale
recall; confidence of the resulting belief is unchanged (still computed
from the two co-occurring observations).
2026-06-23 20:37:01 +01:00
Andy Dixon 73e5753a91 feat: add beliefs with evidence-derived confidence, contradictions and corrections
Phase 6. Beliefs are propositions with a prior set by epistemic kind and a
confidence computed from typed evidence: sigmoid(logit(prior) + slope ×
(support × diversity − opposition)), where support from a single source
is discounted so repetition cannot manufacture certainty, and bounds keep
the mind away from absolute certainty. Every evaluation stores its
breakdown and appends a version row protected by the append-only
trigger; the belief page shows the arithmetic, evidence for and against,
alternatives, contradictions and history.

Contradiction detection is deterministic first (negation plus token
overlap): a hit emits contradiction_detected, links both beliefs and
makes each counter-evidence for the other so both trend to contested.
Operators can assert beliefs (their statement is the evidence), add
evidence, mark a belief wrong (pinned rejected, history kept) and forbid
an inference; do-not-infer corrections block matching hypotheses.
Retracting a memory retracts the evidence that cited it and re-evaluates
the beliefs concerned.

The associate process proposes low-confidence causal hypotheses from
co-occurring notable observations, and the hypothesis handler turns
admitted ones into beliefs with automatic alternatives, closing demo
scenarios 1 and 2 without any model call.
2026-06-21 22:14:12 +01:00
Andy Dixon 03631e5685 feat: add long-term memory systems with fused retrieval and memory explorer
Phase 5 (ADR-0003). pkg/concepts fixes the epistemic vocabulary
(observation, fact, memory, claim, hypothesis, belief, prediction,
assumption, inference, opinion), memory kinds and relation names.

internal/memory stores episodic, semantic, procedural and
autobiographical memories in one mind-scoped table with trust-derived
credibility, importance, salience and decaying activation. Retrieval
fuses full-text rank (any-term by default), optional pgvector similarity,
recency, activation, importance and credibility, and returns the
component scores so every recall can be explained. Decay lowers
activation and never deletes; retraction and supersession keep rows for
provenance. Relationships are constrained to one mind at insert time.
Embeddings live in a conditional pgvector table keyed by model so vector
spaces are never mixed; without an embedder the system degrades to text
and graph retrieval.

Attention gates encoding: the attend handler turns admitted observations
into episodic memories (operator changes become autobiographical ones)
with memory_created events; the retrieve process proposes recalled
memories as candidates and admitted recalls are reinforced with
memory_retrieved events carrying their scoring components.

Memory explorer UI (search with component breakdown, timeline, filters,
operator knowledge entry), memory detail with provenance, relationships,
citing events and an inaccurate-memory correction; API; noemactl memory
commands; decay and embed-missing background jobs.
2026-06-20 23:47:50 +01:00
Andy Dixon e9c1b25c80 feat: implement global workspace, working memory and the cognitive cycle
Phase 4 (ADR-0001). internal/attention scores thought candidates as a
normalised weighted sum over ten named features with a per-term
breakdown, ranked by (score, id) so ordering is total and replayable.
internal/workspace holds the capacity-limited workspace (refresh by
subject, decayed competition, explained admit/reject outcomes) and the
decaying working memory.

internal/brain runs one runtime per active mind: debounced wake-ups from
the event bus (own output never re-triggers), a settle window so
concurrently committing events are not skipped, bounded concurrent
Observe calls with per-process isolation and timeouts, deterministic
scoring, a loop detector that suppresses recurring thoughts and raises a
metacognition warning, executive dispatch by thought kind, and one
transaction per cycle whose events are published only after commit.
Every candidate, selection, attention shift and broadcast is an event
with provenance back to the triggering observation. Operators can run a
cycle, pause, resume, reset transient state and change attention
weights live; the manager reconciles runtimes with mind status.

cognition/attend is the first process: deterministic candidates from
external events using an urgency lexicon, novelty against context and
trust-based operator priority.
2026-06-18 22:54:07 +01:00
Andy Dixon 85d769b245 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.
2026-06-17 20:02:22 +01:00
Andy Dixon fb34f08f40 feat: add mind model with versioned personality, templates and self-model
Phase 2. Minds are rows with a slug, status (active/disabled/archived),
cognitive configuration and a pointer to the current personality version.
Personalities are structured (identity, values, traits, communication,
behaviour, free text) with a deterministic Brief() used by prompts and the
editor preview. Every change appends a personality_versions row protected
by the append-only trigger; restore copies an old version forward.
Templates carry reusable personalities; minds record their overrides so a
template can be re-applied without losing mind-specific edits. The
self-model starts with structural limitations the mind cannot drop
(no policy changes, no influence over shutdown, no cross-mind access).

API, UI (list, overview, editor with sliders/diff/history/import/export,
template editor) and noemactl mind/template commands. All mutations are
audited with field-level diffs.
2026-06-15 22:17:01 +01:00
Andy Dixon a002a2c100 feat: add authentication, audit log, HTTP API and base web UI
Phase 1 foundation. Local auth per ADR-0006: Argon2id passwords, opaque
hashed session tokens with idle/absolute expiry, CSRF token plus Origin
check on cookie sessions, per-IP token bucket and per-account exponential
lockout, three roles enforced by middleware, personal API tokens for
noemactl. Audit log writer used by every admin mutation.

API: request ids, panic recovery, strict CSP and security headers, body
limits, single JSON error envelope, health/ready/status, users, sessions,
tokens, audit, token-protected /metrics.

UI: embedded html/template pages (login, first-run setup, dashboard,
system, users, account, audit, interpretation boundary), light/dark
theme, dependency-free app.js with CSRF-aware fetch and SSE helper.

Binaries: noemad with graceful shutdown, migrations at start, bootstrap
admin from environment, supervised background tasks; noemactl with
status, migrate, user create and meaningful exit codes.
2026-06-15 20:22:19 +01:00
Andy Dixon 6374e174c6 feat: add configuration, logging, metrics, scheduler and storage foundation
- config: defaults -> JSON file -> NOEMA_* env with validation and redaction
- observability: slog with secret-redacting handler; Prometheus registry with
  the metric set from the plan (events, workspace, memory, LLM, tools, queues)
- scheduler: supervised Group and bounded Pool so no goroutine is unowned
- storage: pgx pool with statement timeout, embedded migration runner
  (advisory lock, checksums, up/down/status), per-test schema helper
- migrations/0001: append-only guard trigger, users, sessions, api tokens,
  recovery codes, audit log, settings
- pkg/ids: UUIDv7 with monotonic counter
2026-06-14 23:08:37 +01:00
andy 3de6e53ab0 chore: initialise Noema repository
Foundation for the persistent, inspectable cognitive runtime: README,
implementation plan with phases and risk register, architecture,
security model, threat model, contributing guide, eight ADRs covering
the global workspace, event immutability, memory representation, LLM
abstraction, capability system, authentication, frontend and storage.
Includes Makefile, env example, compose stack (pgvector) and Dockerfile
skeleton, plus a record of the development environment assumptions.
2026-06-12 19:56:53 +01:00