Aleph
Architecture

loop_graph Governance Topology

The loop_graph governance topology layered over the core, and its relationship with the graph_topology prompt layer.

This page replaces the older "World Model" section. The source tree does not contain src/daemon/worldmodel/, nor types named WorldModel / CoreState / EnhancedContext / PendingAction / ActivityType. Those concepts were retired by the 26.7.x governance-topology refactor and replaced by the loop_graph layer and graph_topology prompt layer described below.

Overview

loop_graph is the governance topology layer layered over the Aleph core. It provides a closed set of topology edges that answer the four single-loop failure modes topologically (Goodhart, reference blindness, ring conflict, measurement decay):

  • anchor — irrefutable measurements
  • frozen — rules enforced elsewhere
  • root — human-supplied definitions of "better" (origin=human enforced by the store)
  • watches — pairing / supervision edges
  • owns_reference — reference ownership
  • arbitrates — conflict adjudication
  • audits — closed-set audit action log

Source: src/loop_graph/ (mod.rs / service.rs / store.rs / templates.rs / types.rs). The store is installed once at boot via init_global(Arc<LoopGraphStore>) (OnceCell); an uninitialized process reads as "no graph subsystem" (fail-soft).

Boundary (R7/R9/R10): this module is scaffolding only -- topology storage, structural lint, fact rendering. Every semantic verdict ("is this win cheap?" / "is this reference wrong?" / "which side of a conflict yields?") is an ordinary LLM turn steered by templates.rs and the loop-governance skill. It lives OUTSIDE src/harness/ and adds zero per-turn cost when the graph is empty. Dreaming and every other optimizer have no write path here -- the topology is the held-out layer that watches them.

graph_topology Prompt Layer

graph_topology is not a standalone module -- it is a PromptLayer in src/thinker/layers/graph_topology.rs:

pub struct GraphTopologyLayer;

impl PromptLayer for GraphTopologyLayer {
    fn name(&self) -> &'static str { "graph_topology" }
    fn priority(&self) -> u32 { 1754 }                  // sits before standing_goal
    fn paths(&self) -> &'static [AssemblyPath] {
        &[AssemblyPath::Basic, AssemblyPath::Cached]
    }
    fn stability(&self) -> LayerStability { LayerStability::Dynamic }
    fn supports_mode(&self, mode: PromptMode) -> bool { mode != PromptMode::Minimal }

    fn inject(&self, output: &mut String, input: &LayerInput) {
        let Some(ctx) = input.context else { return };
        let Some(topology) = ctx.graph_topology.as_deref() else { return };
        if topology.is_empty() { return };
        output.push_str("<loop_graph_context>\n");
        output.push_str(&crate::thinker::xml_util::escape_xml(topology));
        output.push_str("</loop_graph_context>\n\n");
    }
}

A governed session is TOLD its place in the governance topology every turn -- who watches it, who owns its reference (and the proposal-note path for changing it), which anchors ground it, and the human root reference verbatim. The model never has to "remember" the graph.

Cache discipline: the rendered content comes from graph rows only -- no clocks, no counters -- so an unchanged graph leaves the prompt byte-identical. Ungoverned sessions (None) emit nothing: zero cost for everyone outside the graph.

Relationship with the 1-2-3-4 Model

┌─────────────────────────────────────────────────────────────────┐
│   1. Core (alephcore)                                            │
│      ├── harness/        Think→Act loop                          │
│      ├── thinker/        Prompt assembly (includes              │
│      │                   GraphTopologyLayer)                     │
│      └── ...                                                       │
│                                                                   │
│   ▲ loop_graph layered on top of 1 (does NOT change 1-2-3-4)    │
│   │   - topology storage + lint + fact rendering                 │
│   │   - semantic verdicts delegated to an LLM turn               │
│   ▼                                                               │
│   loop_graph/  (src/loop_graph/)                                  │
│      ├── store.rs       LoopGraphStore (SQLite)                   │
│      ├── service.rs     GraphService                              │
│      ├── templates.rs   Template prompts                          │
│      └── types.rs       NodeKind / EdgeKind / Origin             │
└─────────────────────────────────────────────────────────────────┘

The graph does not participate in completion judgment -- it only describes relationships; it never tells the harness when to stop. AgentHarness still decides to stop on TurnState::Done / max_iterations / ToolLoopVerifier / the consecutive-failure cap.

Multi-Agent × Graph Fusion

  • Team nodes (NodeKind::Team) -- fuse the multi-agent system into the graph
  • Audit ring -- closed-set audit action log
  • Objective ACLs -- authorized by graph node identity (with origin=human not bypassable)
  • Victory-claim watchers -- triggered on team / loop completion
  • Built-in loop-auditor agent -- audit / supervision default to independent-context evidence

Configuration

The graph is a process-global singleton (OnceCell<Arc<LoopGraphStore>>) and is not configured via TOML. Its lifecycle follows the store database:

  • Boot: LoopGraphStore::open(&dir) is installed via init_global(...).
  • Runtime: any process code reads via loop_graph::global().
  • Tests: loop_graph::set_global_for_test(store).

Code Location

  • src/loop_graph/mod.rs -- LoopGraphStore + NodeKind / EdgeKind / Origin re-exports + init_global / global.
  • src/loop_graph/store.rs -- SQLite persistence (nodes / edges / origin=human enforcement).
  • src/loop_graph/service.rs -- GraphService (writes / lint).
  • src/loop_graph/templates.rs -- template prompts (for the LLM turn).
  • src/thinker/layers/graph_topology.rs -- GraphTopologyLayer injecting the topology into the system prompt.

See Also


26.7.x Addendum

loop_graph Is a Layer, Not a Replacement

26.7.21+: loop_graph does not change the 1-2-3-4 model -- it layers on top of the core, adding governance topology (team nodes / audit ring / objective ACL / victory-claim watchers) to the multi-agent system. The harness does not know the graph exists.

graph_topology -- The Only Form Into the Prompt

26.7.21+: the graph is never "queried" by the harness (that would break cache discipline); instead, GraphTopologyLayer renders the current topology into a <loop_graph_context> segment every turn, and the model reads it.

See Also

On this page