# Architecture

Protocol layers, runtime components, data flows, persistence tiers, and active constraints — v0.1.0

Protocol Layers
Declarative
Layer
Nickel
.ontology/core.ncl.ontology/state.ncladrs/adr-NNN.nclreflection/schemas/reflection/modes/reflection/forms/reflection/qa.ncl.ontoref/config.ncl
Strong types, contracts, enums. Fails at definition time. No runtime evaluation — nickel export produces JSON consumed by all layers above.
Knowledge
Graph
.ontology/
4 axioms2 tensions12 practicesnodes + edgesinvariantsgatesdimensions
The project knows what it knows. Actor-agnostic. Machine-queryable. ontoref uses its own protocol — the .ontology/ here describes ontoref itself.
Operational
Layer
Nushell
adr.nubacklog.nucoder.nudescribe.nusync.nuconfig.nuregister.nuforms.nu+8 more
Typed Nushell pipelines over structured data — no text streams. 16 modules, each responsible for one operational domain. DAG modes validated before execution.
Entry
Point
Bash → Nu
./ontorefactor detectionadvisory lockingNICKEL_IMPORT_PATH./ontoref -V
Single entry point per project. Detects actor (developer / agent / CI) from flag, env var, or TTY. Acquires mkdir-based POSIX advisory lock per resource. Dispatches to Nu.
Runtime
Layer
Rust + axum
ontoref-daemonontoref-ontologyontoref-reflectionaxum HTTP APITera templatesMCP serverDashMap cachenotify watcherdrift observersearch enginenotification storeactor registrysession storeSurrealDB (optional)
Optional persistent daemon. Caches nickel export results (path+mtime keyed). Serves HTTP UI (10 pages) + MCP server (19 tools). Actor registry with DashMap sessions. Notification barrier (pre_commit, drift, ontology_drift). Full-text search engine across nodes/ADRs/modes. Never a protocol requirement.
Adoption
Layer
Per-project
templates/ontology/templates/ontoref-config.ncltemplates/scripts-ontorefadopt_ontoref modeONTOREF_PROJECT_ROOT
Each project maintains its own .ontology/ data. One ontoref checkout serves multiple projects via ONTOREF_PROJECT_ROOT. Zero lock-in — files are plain NCL.
Request Flows
CLI path — developer or agent via shell
Actor
developer · agent · CI
→
./ontoref
bash wrapper
→
ontoref.nu
Nu dispatcher
→
daemon
cache / notify
→
nickel export
.ontology/ · adrs/
→
reflection/
qa.ncl · backlog.ncl
MCP / AI agent path — Claude Code or any MCP client
AI Agent
Claude · any MCP client
→
MCP server
stdio · HTTP /mcp
→
19 tools
read · write · query
→
NCL files
git-versioned
Pre-commit barrier — notification-gated commit path
git commit
pre-commit hook fires
→
GET /notifications
/pending?token=X&project=Y
→
pending?
pre_commit · drift · ontology_drift
→
block
until acked in UI / POST /notifications/ack
→
pass
fail-open if daemon unreachable
Daemon Components

### HTTP API · /ui/{slug}

- GET/ui/{slug}/Dashboard — overview, actors, cache stats
- GET/ui/{slug}/graphD3 ontology graph (nodes by pole, edges)
- GET/ui/{slug}/searchSearch across nodes/ADRs/modes
- GET/ui/{slug}/sessionsLive actor registry
- GET/ui/{slug}/notificationsNotification feed + ack UI
- GET/ui/{slug}/backlogBacklog with priority/status
- GET/ui/{slug}/qaQ&A knowledge store
- GET/ui/{slug}/actionsQuick actions catalog
- GET/ui/{slug}/modesReflection modes browser
- GET/ui/{slug}/composeAgent task composer (live sharing)
- GET/actorsActor sessions list
- GET/search?q=&project=Search JSON endpoint
- GET/notifications/pendingPre-commit hook polling
- POST/notifications/ackAck one or all notifications
- POST/{slug}/notifications/emitEmit custom notification
- POST/{slug}/notifications/{id}/actionTrigger notification action
- POST/compose/sendDispatch mode to ./ontoref server-side
- POST/actions/runExecute quick action by id
- POST/qa/addAppend Q&A entry to NCL
- POST/qa/deleteRemove entry by id
- POST/qa/updateMutate question + answer
- GET/qa-jsonExport all Q&A entries
- POST/backlog/addAdd backlog item
- POST/backlog/statusUpdate backlog item status
- GET/backlog-jsonExport backlog as JSON
- GET/healthCache stats + uptime + SurrealDB status

### MCP Server · 19 tools

- ontoref_help— list all tools and usage
- ontoref_list_projects— enumerate loaded projects
- ontoref_set_project— set session default project
- ontoref_project_status— full project dashboard
- ontoref_describe— architecture overview
- ontoref_search— free-text across nodes/ADRs/modes
- ontoref_get— fetch node by id
- ontoref_get_node— full ontology node with edges
- ontoref_list_adrs— list ADRs by status filter
- ontoref_get_adr— full ADR with constraints
- ontoref_list_modes— list reflection modes
- ontoref_get_mode— mode DAG contract
- ontoref_get_backlog— backlog filtered by status
- ontoref_backlog— add / update_status
- ontoref_constraints— all architectural constraints
- ontoref_qa_list— list Q&A with optional filter
- ontoref_qa_add— append to reflection/qa.ncl
- ontoref_action_list— quick actions from config.ncl
- ontoref_action_add— create mode + register action

### Sessions & Actor Registry

- ActorRegistrybacked by DashMap<String, ActorSession>
- tokenrandom string, unique per session
- actor_typedeveloper · agent · CI
- registered_atISO timestamp, set on registration
- last_seenupdated on each API call
- current_modelast active reflection mode
- serializablesnapshot for disk persistence
- pre-commit CIregisters as ci actor on hook fire

### Compose / Live Sharing

- /ui/{slug}/composerenders mode form schemas as interactive HTML
- POST /compose/senddispatches ./ontoref {mode} {params} on server
- shared contextmultiple actors see same composed task live
- /ui/{slug}/manageproject registry CRUD (multi-project mode)

### Notification Store & Search

- NotificationStorein-memory queue per (project, token)
- pre_commitblocks git commits until acked by actor
- driftschema drift between codebase and ontology
- ontology_driftfrom passive observer — missing/stale/drift/broken counts
- fail-openif daemon unreachable, pre-commit hook passes
- ack workflowPOST /notifications/ack (one or all); action buttons in UI

### Search Engine

- indexesontology nodes (id, name, description)
- indexesADRs (title, context, decision)
- indexesreflection modes (name, description, steps)
- SearchResultkind · id · title · snippet · score
- used byUI search page + MCP ontoref_search tool

### NCL Files — Mutations

- reflection/qa.nclQaStore — typed entries, git-versioned; written only via crates/ontoref-daemon/src/ui/qa_ncl.rs (ADR-003 hard constraint)
- reflection/backlog.nclBacklogStore — items with status (Open/InProgress/Done/Cancelled) and priority (Critical/High/Medium/Low)
- .ontoref/config.nclquick_actions catalog, log level, NATS toggle
- reflection/modes/*.nclnew mode files created by ontoref_action_add

### Drift Observer

- watchescrates/ · .ontology/ · adrs/ · reflection/modes/
- debounce15 seconds after last filesystem event
- runssync scan → sync diff (read-only, never applies changes)
- emitsontology_drift { missing, stale, drift, broken } to NotificationStore

### SurrealDB (optional --db feature)

- connectionWebSocket to --db-url ws://...; 5s timeout at startup; fail-open
- seedsontology tables from local NCL files on startup and on file changes (via notify watcher)
- persistsactor sessions, seeded ontology tables, search index, notification history — survives daemon restarts
- without --dbDashMap-backed in-memory cache only; process-lifetime; actor sessions and search index are ephemeral

Persistence Tiers

### In-Memory — Always Active

DashMap-backed, process-lifetime — no flags required

- DashMap cache — NCL export results, path+mtime keyed
- NotificationStore — per (project, token) notification queue
- ActorRegistry — live session DashMap
- SessionStore — token → ActorSession map
- Search index — in-process full-text over loaded NCL data
- All state is lost on daemon restart
- Serializable snapshots can be written to disk as JSON/NCL

### SurrealDB — Optional `--db` Flag

WebSocket connection, fail-open — survives daemon restarts

- Actor sessions — token, type, registered_at, last_seen, mode
- Seeded ontology tables — nodes, ADRs, modes from NCL files
- Search index — persisted search index for nodes/ADRs/modes
- Notification history — acked and dismissed notifications
- Enabled with `--db-url ws://...` + `--db-namespace`
- If SurrealDB is unreachable at startup, daemon still starts using in-memory tier

Active Constraints (ADR-003 · ADR-002 · ADR-001)
qa-write-via-mutation-module
All mutations to reflection/qa.ncl must go through `crates/ontoref-daemon/src/ui/qa_ncl.rs` — no direct file writes from other call sites.
qa-schema-typed
`reflection/qa.ncl` must conform to the QaStore contract from `reflection/schemas/qa.ncl` — nickel typecheck must pass.
mcp-qa-tools-no-apply-drift
MCP tools `ontoref_qa_list` and `ontoref_qa_add` must never trigger sync apply steps or modify `.ontology/` files.
protocol-not-runtime (axiom)
ontoref-daemon is optional runtime support — not a protocol requirement. The protocol functions without it. Every module falls back to direct subprocess.
notification-barrier-fail-open
The pre-commit hook must not block git commits when the daemon is unreachable. If `GET /notifications/pending` fails (connection error, timeout), the hook must pass immediately.
ontology-crate-zero-stratumiops-deps (ADR-001)
`ontoref-ontology` must never depend on `stratum-graph`, `stratum-state`, or `stratum-orchestrator`. The ontology crate is the protocol's minimal adoption surface and must build standalone.