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 namedWorldModel/CoreState/EnhancedContext/PendingAction/ActivityType. Those concepts were retired by the 26.7.x governance-topology refactor and replaced by theloop_graphlayer andgraph_topologyprompt 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=humanenforced 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=humannot bypassable) - Victory-claim watchers -- triggered on team / loop completion
- Built-in
loop-auditoragent -- 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 viainit_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/Originre-exports +init_global/global.src/loop_graph/store.rs-- SQLite persistence (nodes / edges /origin=humanenforcement).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--GraphTopologyLayerinjecting the topology into the system prompt.
See Also
- Architecture Overview -- the 1-2-3-4 model and where loop_graph fits
- Prompt Builder -- prompt layer registry
- Loop / Goal / Strategy -- three independent subsystems
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
- Architecture 1-2-3-4 Model -- stable skeleton
- Architectural Redlines R1-R10 -- hard constraints
Workflow
Declarative, reusable workflow templates — the workflow half of the agent-workflow spectrum; compile to a coord_tasks DAG, executed by TeamDispatcher.
Proactive Task Scheduling
Daemon background tasks: cron / heartbeat services; runtimes capability ledger; wake queue and storm-prevention guards; no `src/daemon/`.