-- ============================================================================
-- GEP-NATIVE MCP CONTROL LAYER
-- Entropy-Guided Motor Control for Autonomous Tool Execution
--
-- Author: Gary W. Floyd / Lumiea Systems Research Division
-- Based on: Guided Entropy Principle (GEP) framework
-- Date: December 2025
--
-- Purpose: Database-driven tool execution control using GEP routing
-- DB decides → MCP executes → DB records → State updates
--
-- Features:
-- - Entropy-weighted tool selection and routing
-- - Dynamic gating thresholds (adaptive, not static)
-- - Alignment-based execution control
-- - Append-only audit trail with full GEP context
-- - EMA-based state tracking and learning
-- - Session rate limiting and violation tracking
-- - Semantic intent matching with pgvector
-- ============================================================================
-- ============================================================================
-- INSTALLATION INSTRUCTIONS
-- ============================================================================
--
-- Prerequisites:
-- 1. PostgreSQL 14+ installed
-- 2. pgvector extension available: https://github.com/pgvector/pgvector
-- Install: CREATE EXTENSION vector;
--
-- Quick Start:
-- psql -U postgres -f gep_mcp_control_layer.sql
--
-- Or step-by-step:
-- 1. Create database: CREATE DATABASE gep_mcp_v2;
-- 2. Connect: \c gep_mcp_v2
-- 3. Enable pgvector: CREATE EXTENSION vector;
-- 4. Run this script: \i gep_mcp_control_layer.sql
--
-- Configuration:
-- - Adjust EMA smoothing factor (v_alpha) in log_and_update() function
-- - Modify threshold multipliers in tool_policy table
-- - Set rate limits per tool in tool_policy
--
-- ============================================================================
-- Drop existing database if present (CAUTION: destroys all data)
-- DROP DATABASE IF EXISTS gep_mcp_v2;
CREATE DATABASE gep_mcp_v2;
\c gep_mcp_v2;
-- Enable required extensions
CREATE EXTENSION IF NOT EXISTS vector;
CREATE EXTENSION IF NOT EXISTS "uuid-ossp";
CREATE SCHEMA IF NOT EXISTS gep;
-- ============================================================================
-- CORE TABLES
-- ============================================================================
-- ---------------------------------------------------------------------------
-- TOOL REGISTRY: What exists + its entropy signature
-- ---------------------------------------------------------------------------
CREATE TABLE gep.tool_registry (
tool_id BIGSERIAL PRIMARY KEY,
name TEXT UNIQUE NOT NULL,
description TEXT NOT NULL DEFAULT '',
protocol TEXT NOT NULL CHECK (protocol IN ('local_exec','http','jsonrpc','ssh','mcp')),
endpoint TEXT NOT NULL,
enabled BOOLEAN NOT NULL DEFAULT TRUE,
-- GEP: Behavioral signature
base_entropy DOUBLE PRECISION NOT NULL DEFAULT 0.40, -- H₀: inherent unpredictability
entropy_variance DOUBLE PRECISION NOT NULL DEFAULT 0.15, -- σ(E): how stable is this tool
alignment_req DOUBLE PRECISION NOT NULL DEFAULT 0.70, -- A_min: minimum operator alignment
-- Risk classification
risk_level SMALLINT NOT NULL DEFAULT 2 CHECK (risk_level BETWEEN 0 AND 5),
side_effect_class TEXT NOT NULL DEFAULT 'read' CHECK (side_effect_class IN ('read','write','destructive')),
idempotent BOOLEAN NOT NULL DEFAULT TRUE, -- Can we safely retry?
-- Metadata
tags TEXT[] NOT NULL DEFAULT '{}',
owner TEXT NOT NULL DEFAULT 'nexus',
version TEXT NOT NULL DEFAULT '1.0.0',
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
COMMENT ON TABLE gep.tool_registry IS 'Registry of available tools with GEP behavioral signatures';
COMMENT ON COLUMN gep.tool_registry.base_entropy IS 'Inherent entropy H₀: tool unpredictability baseline (0..1)';
COMMENT ON COLUMN gep.tool_registry.entropy_variance IS 'Expected entropy variance σ(E) for this tool';
COMMENT ON COLUMN gep.tool_registry.alignment_req IS 'Minimum operator alignment A_min required for execution';
-- ---------------------------------------------------------------------------
-- TOOL STATE: Rolling GEP metrics (EMA-tracked)
-- ---------------------------------------------------------------------------
CREATE TABLE gep.tool_state (
tool_id BIGINT PRIMARY KEY REFERENCES gep.tool_registry(tool_id) ON DELETE CASCADE,
-- GEP core metrics (0..1 normalized)
entropy_ema DOUBLE PRECISION NOT NULL DEFAULT 0.20, -- E(t): current entropy
entropy_baseline DOUBLE PRECISION NOT NULL DEFAULT 0.20, -- E_base: learned baseline
entropy_p50 DOUBLE PRECISION NOT NULL DEFAULT 0.20, -- percentiles for outlier detection
entropy_p90 DOUBLE PRECISION NOT NULL DEFAULT 0.40,
entropy_p99 DOUBLE PRECISION NOT NULL DEFAULT 0.60,
-- Performance metrics
success_ema DOUBLE PRECISION NOT NULL DEFAULT 0.95,
latency_ms_ema DOUBLE PRECISION NOT NULL DEFAULT 1000,
latency_p95 DOUBLE PRECISION NOT NULL DEFAULT 3000,
-- Alignment tracking
alignment_ema DOUBLE PRECISION NOT NULL DEFAULT 0.80, -- A(t): avg operator alignment
alignment_p10 DOUBLE PRECISION NOT NULL DEFAULT 0.60, -- min acceptable alignment
-- Usage stats
uses_total BIGINT NOT NULL DEFAULT 0,
failures_total BIGINT NOT NULL DEFAULT 0,
blocks_total BIGINT NOT NULL DEFAULT 0,
last_used_at TIMESTAMPTZ,
last_failure_at TIMESTAMPTZ,
-- GEP-specific: entropy flow tracking
entropy_trend_1h DOUBLE PRECISION[] DEFAULT '{}', -- sliding window for trend analysis
delta_s_sum DOUBLE PRECISION NOT NULL DEFAULT 0.0, -- cumulative ΔS
updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
COMMENT ON TABLE gep.tool_state IS 'Rolling GEP metrics tracked via EMA for each tool';
COMMENT ON COLUMN gep.tool_state.entropy_ema IS 'Exponential moving average of tool entropy E(t)';
COMMENT ON COLUMN gep.tool_state.delta_s_sum IS 'Cumulative entropy change ΔS for this tool';
-- ---------------------------------------------------------------------------
-- POLICY: Constraints + GEP thresholds
-- ---------------------------------------------------------------------------
CREATE TABLE gep.tool_policy (
policy_id BIGSERIAL PRIMARY KEY,
tool_id BIGINT NOT NULL REFERENCES gep.tool_registry(tool_id) ON DELETE CASCADE,
-- Hard constraints (enforced by MCP)
allowed_scopes JSONB NOT NULL DEFAULT '{}'::jsonb,
deny_scopes JSONB NOT NULL DEFAULT '{}'::jsonb,
max_runtime_ms INTEGER NOT NULL DEFAULT 30000,
max_output_bytes INTEGER NOT NULL DEFAULT 200000,
rate_limit_per_min INTEGER NOT NULL DEFAULT 60,
sandbox_profile JSONB NOT NULL DEFAULT '{"mode":"restricted_user"}'::jsonb,
-- GEP gating thresholds (dynamic, not static)
-- These are MULTIPLIERS on the learned baseline, not absolute values
throttle_threshold_multiplier DOUBLE PRECISION NOT NULL DEFAULT 1.5, -- E > baseline * 1.5
stepup_threshold_multiplier DOUBLE PRECISION NOT NULL DEFAULT 2.0, -- E > baseline * 2.0
block_threshold_multiplier DOUBLE PRECISION NOT NULL DEFAULT 2.5, -- E > baseline * 2.5
-- Alignment gates
min_alignment_allow DOUBLE PRECISION NOT NULL DEFAULT 0.70,
min_alignment_write DOUBLE PRECISION NOT NULL DEFAULT 0.80,
min_alignment_destruct DOUBLE PRECISION NOT NULL DEFAULT 0.90,
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
COMMENT ON TABLE gep.tool_policy IS 'Execution policies with adaptive GEP thresholds';
COMMENT ON COLUMN gep.tool_policy.throttle_threshold_multiplier IS 'Multiplier on baseline entropy for throttling';
-- ---------------------------------------------------------------------------
-- SESSION STATE: Per-session entropy + alignment tracking
-- ---------------------------------------------------------------------------
CREATE TABLE gep.session_state (
session_id TEXT PRIMARY KEY,
operator_id TEXT NOT NULL,
-- Current GEP state
entropy_current DOUBLE PRECISION NOT NULL DEFAULT 0.20,
alignment_current DOUBLE PRECISION NOT NULL DEFAULT 0.85,
-- Session behavior
intent_vector vector(384), -- semantic embedding of recent intents
tool_call_count INTEGER NOT NULL DEFAULT 0,
violation_count INTEGER NOT NULL DEFAULT 0,
-- Rate limiting
calls_last_minute INTEGER NOT NULL DEFAULT 0,
last_call_at TIMESTAMPTZ,
-- Entropy flow for this session
entropy_history DOUBLE PRECISION[] DEFAULT '{}', -- last 20 values
delta_s_session DOUBLE PRECISION NOT NULL DEFAULT 0.0,
-- Session context
context_summary TEXT,
risk_level SMALLINT NOT NULL DEFAULT 2,
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
CREATE INDEX idx_session_operator ON gep.session_state(operator_id, updated_at DESC);
COMMENT ON TABLE gep.session_state IS 'Per-session GEP state tracking and rate limiting';
-- ---------------------------------------------------------------------------
-- INTENT → TOOL MAPPING (semantic routing)
-- ---------------------------------------------------------------------------
CREATE TABLE gep.intent_map (
intent_id BIGSERIAL PRIMARY KEY,
tool_id BIGINT NOT NULL REFERENCES gep.tool_registry(tool_id) ON DELETE CASCADE,
-- Intent matching
intent_pattern TEXT NOT NULL, -- regex or keyword match
intent_embedding vector(384), -- semantic vector
priority SMALLINT NOT NULL DEFAULT 100,
-- GEP: Expected entropy for this intent type
expected_entropy DOUBLE PRECISION NOT NULL DEFAULT 0.25,
entropy_variance DOUBLE PRECISION NOT NULL DEFAULT 0.10,
-- Match stats
match_count BIGINT NOT NULL DEFAULT 0,
success_rate DOUBLE PRECISION NOT NULL DEFAULT 0.95,
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
CREATE INDEX idx_intent_embedding ON gep.intent_map
USING ivfflat (intent_embedding vector_cosine_ops) WITH (lists = 100);
COMMENT ON TABLE gep.intent_map IS 'Semantic intent to tool mapping with expected entropy';
-- ---------------------------------------------------------------------------
-- EVENTS: Append-only truth layer with full GEP context
-- ---------------------------------------------------------------------------
CREATE TABLE gep.tool_events (
event_id UUID PRIMARY KEY,
ts TIMESTAMPTZ NOT NULL DEFAULT now(),
-- Context
session_id TEXT NOT NULL,
operator_id TEXT NOT NULL,
tool_id BIGINT REFERENCES gep.tool_registry(tool_id),
intent TEXT NOT NULL,
intent_embedding vector(384),
-- GEP decision state
entropy_before DOUBLE PRECISION NOT NULL,
entropy_after DOUBLE PRECISION,
alignment_before DOUBLE PRECISION NOT NULL,
delta_s DOUBLE PRECISION,
-- Decision
action TEXT NOT NULL CHECK (action IN ('ALLOW','THROTTLE','STEP_UP','BLOCK')),
decision_reason TEXT NOT NULL,
decision_score DOUBLE PRECISION, -- composite GEP score used for routing
-- Execution
input_digest TEXT NOT NULL,
input_nonce TEXT NOT NULL, -- replay prevention
output_digest TEXT,
outcome TEXT CHECK (outcome IN ('ok','fail','timeout','blocked','throttled')),
latency_ms INTEGER,
-- Validation
output_validated BOOLEAN,
validation_errors TEXT,
-- Metadata
constraints_applied JSONB,
notes TEXT
);
CREATE UNIQUE INDEX idx_nonce_recent ON gep.tool_events(input_nonce)
WHERE ts > now() - interval '5 minutes';
CREATE INDEX idx_events_ts ON gep.tool_events(ts DESC);
CREATE INDEX idx_events_tool_ts ON gep.tool_events(tool_id, ts DESC);
CREATE INDEX idx_events_session ON gep.tool_events(session_id, ts DESC);
CREATE INDEX idx_events_operator ON gep.tool_events(operator_id, ts DESC);
COMMENT ON TABLE gep.tool_events IS 'Immutable audit trail of all tool execution decisions and outcomes';
COMMENT ON COLUMN gep.tool_events.delta_s IS 'Entropy change ΔS = E_after - E_before';
-- ---------------------------------------------------------------------------
-- OUTPUT VALIDATION SCHEMAS
-- ---------------------------------------------------------------------------
CREATE TABLE gep.output_schema (
tool_id BIGINT PRIMARY KEY REFERENCES gep.tool_registry(tool_id) ON DELETE CASCADE,
expected_format TEXT NOT NULL CHECK (expected_format IN ('json','text','binary','exit_code')),
schema_definition JSONB, -- JSON Schema for validation
max_size_bytes INTEGER NOT NULL DEFAULT 200000,
hash_algorithm TEXT NOT NULL DEFAULT 'sha256'
);
COMMENT ON TABLE gep.output_schema IS 'Expected output format and validation rules per tool';
-- ============================================================================
-- HELPER FUNCTIONS
-- ============================================================================
-- ---------------------------------------------------------------------------
-- Auto-update updated_at timestamp
-- ---------------------------------------------------------------------------
CREATE OR REPLACE FUNCTION gep.touch_updated_at()
RETURNS trigger AS $$
BEGIN
NEW.updated_at = now();
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
DROP TRIGGER IF EXISTS trg_tool_registry_touch ON gep.tool_registry;
CREATE TRIGGER trg_tool_registry_touch
BEFORE UPDATE ON gep.tool_registry
FOR EACH ROW EXECUTE FUNCTION gep.touch_updated_at();
DROP TRIGGER IF EXISTS trg_tool_state_touch ON gep.tool_state;
CREATE TRIGGER trg_tool_state_touch
BEFORE UPDATE ON gep.tool_state
FOR EACH ROW EXECUTE FUNCTION gep.touch_updated_at();
DROP TRIGGER IF EXISTS trg_session_state_touch ON gep.session_state;
CREATE TRIGGER trg_session_state_touch
BEFORE UPDATE ON gep.session_state
FOR EACH ROW EXECUTE FUNCTION gep.touch_updated_at();
-- ============================================================================
-- CORE GEP DECISION FUNCTION
-- ============================================================================
CREATE OR REPLACE FUNCTION gep.gep_route_and_gate(
p_session_id TEXT,
p_operator_id TEXT,
p_intent TEXT,
p_intent_embedding vector(384),
p_entropy_current DOUBLE PRECISION,
p_alignment_current DOUBLE PRECISION,
p_context JSONB DEFAULT '{}'::jsonb
)
RETURNS TABLE(
tool_id BIGINT,
tool_name TEXT,
action TEXT,
decision_score DOUBLE PRECISION,
constraints JSONB,
reason TEXT
) AS $$
DECLARE
v_tool gep.tool_registry%ROWTYPE;
v_state gep.tool_state%ROWTYPE;
v_policy gep.tool_policy%ROWTYPE;
v_session gep.session_state%ROWTYPE;
v_action TEXT;
v_reason TEXT;
v_score DOUBLE PRECISION;
-- GEP thresholds (computed from learned baselines)
v_entropy_throttle DOUBLE PRECISION;
v_entropy_stepup DOUBLE PRECISION;
v_entropy_block DOUBLE PRECISION;
v_alignment_required DOUBLE PRECISION;
v_semantic_sim DOUBLE PRECISION;
BEGIN
-- -------------------------------------------------------------------------
-- STEP 1: Session rate limiting + state check
-- -------------------------------------------------------------------------
SELECT * INTO v_session FROM gep.session_state WHERE session_id = p_session_id;
IF NOT FOUND THEN
-- Initialize new session
INSERT INTO gep.session_state(session_id, operator_id, entropy_current, alignment_current)
VALUES (p_session_id, p_operator_id, p_entropy_current, p_alignment_current);
v_session.calls_last_minute := 0;
v_session.violation_count := 0;
ELSE
-- Check if session is in violation state
IF v_session.violation_count >= 3 THEN
tool_id := NULL;
tool_name := NULL;
action := 'BLOCK';
decision_score := 0.0;
constraints := '{}'::jsonb;
reason := 'Session blocked: too many violations';
RETURN NEXT;
RETURN;
END IF;
-- Rate limit check (sliding window)
IF v_session.last_call_at > now() - interval '1 minute' THEN
IF v_session.calls_last_minute >= 120 THEN -- hard global limit
tool_id := NULL;
tool_name := NULL;
action := 'THROTTLE';
decision_score := 0.0;
constraints := jsonb_build_object('retry_after', 60);
reason := 'Session rate limit exceeded';
RETURN NEXT;
RETURN;
END IF;
ELSE
-- Reset counter
UPDATE gep.session_state SET calls_last_minute = 0 WHERE session_id = p_session_id;
v_session.calls_last_minute := 0;
END IF;
END IF;
-- -------------------------------------------------------------------------
-- STEP 2: Find best tool using GEP routing
-- -------------------------------------------------------------------------
SELECT
tr.*,
(1.0 - (im.intent_embedding <=> p_intent_embedding)) AS semantic_sim
INTO v_tool, v_semantic_sim
FROM gep.intent_map im
JOIN gep.tool_registry tr ON tr.tool_id = im.tool_id
WHERE tr.enabled = TRUE
AND (1.0 - (im.intent_embedding <=> p_intent_embedding)) >= 0.65 -- min similarity
ORDER BY
-- GEP ROUTING SCORE: minimize entropy cost, maximize alignment confidence
(
-- Semantic match weight (0..1)
(1.0 - (im.intent_embedding <=> p_intent_embedding)) * 0.30
-- Success probability (0..1) - join with tool_state
+ COALESCE((SELECT success_ema FROM gep.tool_state WHERE tool_id = tr.tool_id), 0.90) * 0.25
-- Entropy penalty: prefer tools with low current entropy
+ (1.0 - COALESCE((SELECT entropy_ema FROM gep.tool_state WHERE tool_id = tr.tool_id), 0.30)) * 0.25
-- Alignment confidence: prefer tools we know well
+ LEAST(1.0, COALESCE((SELECT alignment_ema FROM gep.tool_state WHERE tool_id = tr.tool_id), 0.75) / tr.alignment_req) * 0.15
-- Latency penalty: prefer fast tools
+ (1.0 - LEAST(1.0, COALESCE((SELECT latency_ms_ema FROM gep.tool_state WHERE tool_id = tr.tool_id), 1000) / 10000.0)) * 0.05
) DESC,
tr.risk_level ASC, -- tie-breaker: prefer safer tools
tr.tool_id ASC
LIMIT 1;
IF NOT FOUND THEN
tool_id := NULL;
tool_name := NULL;
action := 'BLOCK';
decision_score := 0.0;
constraints := '{}'::jsonb;
reason := 'No enabled tool matches intent (semantic similarity < 0.65)';
RETURN NEXT;
RETURN;
END IF;
-- Get tool state
SELECT * INTO v_state FROM gep.tool_state WHERE tool_id = v_tool.tool_id;
IF NOT FOUND THEN
-- Initialize default state
INSERT INTO gep.tool_state(tool_id) VALUES (v_tool.tool_id);
SELECT * INTO v_state FROM gep.tool_state WHERE tool_id = v_tool.tool_id;
END IF;
-- Store the routing score
v_score := (
v_semantic_sim * 0.30
+ COALESCE(v_state.success_ema, 0.90) * 0.25
+ (1.0 - COALESCE(v_state.entropy_ema, 0.30)) * 0.25
+ LEAST(1.0, COALESCE(v_state.alignment_ema, 0.75) / v_tool.alignment_req) * 0.15
+ (1.0 - LEAST(1.0, COALESCE(v_state.latency_ms_ema, 1000) / 10000.0)) * 0.05
);
-- -------------------------------------------------------------------------
-- STEP 3: Load policy + compute dynamic thresholds
-- -------------------------------------------------------------------------
SELECT * INTO v_policy FROM gep.tool_policy WHERE tool_id = v_tool.tool_id LIMIT 1;
IF NOT FOUND THEN
-- Default policy
v_entropy_throttle := v_state.entropy_baseline * 1.5;
v_entropy_stepup := v_state.entropy_baseline * 2.0;
v_entropy_block := v_state.entropy_baseline * 2.5;
v_alignment_required := 0.70;
ELSE
-- Dynamic thresholds based on learned baseline
v_entropy_throttle := v_state.entropy_baseline * v_policy.throttle_threshold_multiplier;
v_entropy_stepup := v_state.entropy_baseline * v_policy.stepup_threshold_multiplier;
v_entropy_block := v_state.entropy_baseline * v_policy.block_threshold_multiplier;
-- Alignment requirement depends on side effects
v_alignment_required := CASE v_tool.side_effect_class
WHEN 'read' THEN v_policy.min_alignment_allow
WHEN 'write' THEN v_policy.min_alignment_write
WHEN 'destructive' THEN v_policy.min_alignment_destruct
END;
END IF;
-- -------------------------------------------------------------------------
-- STEP 4: GEP GATING DECISION
-- -------------------------------------------------------------------------
IF p_alignment_current < v_alignment_required THEN
v_action := 'BLOCK';
v_reason := format(
'Alignment violation: A=%.3f < required %.3f for %s operations',
p_alignment_current, v_alignment_required, v_tool.side_effect_class
);
ELSIF p_entropy_current >= v_entropy_block
AND p_alignment_current < (v_alignment_required + 0.10) THEN
v_action := 'BLOCK';
v_reason := format(
'Entropy violation: E=%.3f ≥ block_threshold=%.3f (baseline=%.3f × %.1f) + low alignment',
p_entropy_current, v_entropy_block, v_state.entropy_baseline,
COALESCE(v_policy.block_threshold_multiplier, 2.5)
);
ELSIF p_entropy_current >= v_entropy_stepup THEN
v_action := 'STEP_UP';
v_reason := format(
'Elevated entropy: E=%.3f ≥ stepup_threshold=%.3f (baseline=%.3f × %.1f) - confirmation required',
p_entropy_current, v_entropy_stepup, v_state.entropy_baseline,
COALESCE(v_policy.stepup_threshold_multiplier, 2.0)
);
ELSIF p_entropy_current >= v_entropy_throttle THEN
v_action := 'THROTTLE';
v_reason := format(
'Moderate entropy: E=%.3f ≥ throttle_threshold=%.3f (baseline=%.3f × %.1f) - throttled execution',
p_entropy_current, v_entropy_throttle, v_state.entropy_baseline,
COALESCE(v_policy.throttle_threshold_multiplier, 1.5)
);
ELSIF v_tool.risk_level >= 4 AND p_alignment_current < 0.85 THEN
v_action := 'STEP_UP';
v_reason := format(
'High-risk tool (level %s) requires elevated alignment: A=%.3f < 0.85',
v_tool.risk_level, p_alignment_current
);
ELSE
v_action := 'ALLOW';
v_reason := format(
'Within bounds: E=%.3f < throttle=%.3f, A=%.3f ≥ required=%.3f',
p_entropy_current, v_entropy_throttle, p_alignment_current, v_alignment_required
);
END IF;
-- -------------------------------------------------------------------------
-- STEP 5: Build constraint package
-- -------------------------------------------------------------------------
tool_id := v_tool.tool_id;
tool_name := v_tool.name;
action := v_action;
decision_score := v_score;
constraints := jsonb_build_object(
'allowed_scopes', COALESCE(v_policy.allowed_scopes, '{}'::jsonb),
'deny_scopes', COALESCE(v_policy.deny_scopes, '{}'::jsonb),
'max_runtime_ms', CASE
WHEN v_action = 'THROTTLE' THEN COALESCE(v_policy.max_runtime_ms, 30000) / 2
ELSE COALESCE(v_policy.max_runtime_ms, 30000)
END,
'max_output_bytes', COALESCE(v_policy.max_output_bytes, 200000),
'rate_limit_per_min', COALESCE(v_policy.rate_limit_per_min, 60),
'sandbox_profile', COALESCE(v_policy.sandbox_profile, '{"mode":"restricted_user"}'::jsonb),
'risk_level', v_tool.risk_level,
'side_effect_class', v_tool.side_effect_class,
'idempotent', v_tool.idempotent,
'protocol', v_tool.protocol,
'endpoint', v_tool.endpoint,
'gep_context', jsonb_build_object(
'entropy_before', p_entropy_current,
'alignment_before', p_alignment_current,
'entropy_baseline', v_state.entropy_baseline,
'entropy_throttle', v_entropy_throttle,
'entropy_stepup', v_entropy_stepup,
'entropy_block', v_entropy_block,
'alignment_required', v_alignment_required,
'routing_score', v_score,
'semantic_similarity', v_semantic_sim
)
);
reason := v_reason;
RETURN NEXT;
END;
$$ LANGUAGE plpgsql STABLE;
COMMENT ON FUNCTION gep.gep_route_and_gate IS 'GEP motor neuron: entropy-weighted routing + adaptive gating';
-- ============================================================================
-- EVENT LOGGING WITH GEP STATE UPDATES
-- ============================================================================
CREATE OR REPLACE FUNCTION gep.log_and_update(
p_event_id UUID,
p_session_id TEXT,
p_operator_id TEXT,
p_intent TEXT,
p_intent_embedding vector(384),
p_tool_id BIGINT,
p_action TEXT,
p_input_digest TEXT,
p_input_nonce TEXT,
p_outcome TEXT,
p_latency_ms INTEGER,
p_entropy_before DOUBLE PRECISION,
p_entropy_after DOUBLE PRECISION,
p_alignment_before DOUBLE PRECISION,
p_output_digest TEXT DEFAULT NULL,
p_output_validated BOOLEAN DEFAULT NULL,
p_validation_errors TEXT DEFAULT NULL,
p_constraints JSONB DEFAULT '{}'::jsonb,
p_notes TEXT DEFAULT NULL
)
RETURNS VOID AS $$
DECLARE
v_delta_s DOUBLE PRECISION;
v_alpha DOUBLE PRECISION := 0.05; -- EMA smoothing factor (configurable)
v_success INTEGER;
BEGIN
-- Compute ΔS (entropy change)
v_delta_s := COALESCE(p_entropy_after, p_entropy_before) - p_entropy_before;
v_success := CASE WHEN p_outcome = 'ok' THEN 1 ELSE 0 END;
-- -------------------------------------------------------------------------
-- 1. Append to immutable event log
-- -------------------------------------------------------------------------
INSERT INTO gep.tool_events(
event_id, ts, session_id, operator_id, tool_id,
intent, intent_embedding,
entropy_before, entropy_after, alignment_before, delta_s,
action, decision_reason, decision_score,
input_digest, input_nonce, output_digest,
outcome, latency_ms,
output_validated, validation_errors,
constraints_applied, notes
) VALUES (
p_event_id, now(), p_session_id, p_operator_id, p_tool_id,
p_intent, p_intent_embedding,
p_entropy_before, p_entropy_after, p_alignment_before, v_delta_s,
p_action, '', 0.0,
p_input_digest, p_input_nonce, p_output_digest,
p_outcome, p_latency_ms,
p_output_validated, p_validation_errors,
p_constraints, p_notes
);
-- -------------------------------------------------------------------------
-- 2. Update tool_state with EMA
-- -------------------------------------------------------------------------
INSERT INTO gep.tool_state(tool_id)
VALUES (p_tool_id)
ON CONFLICT (tool_id) DO NOTHING;
UPDATE gep.tool_state
SET
-- Usage counters
uses_total = uses_total + 1,
failures_total = failures_total + (1 - v_success),
blocks_total = blocks_total + CASE WHEN p_action = 'BLOCK' THEN 1 ELSE 0 END,
last_used_at = now(),
last_failure_at = CASE WHEN v_success = 0 THEN now() ELSE last_failure_at END,
-- GEP metrics: EMA updates
entropy_ema = CASE
WHEN p_entropy_after IS NOT NULL THEN
LEAST(1.0, GREATEST(0.0, entropy_ema * (1.0 - v_alpha) + p_entropy_after * v_alpha))
ELSE entropy_ema
END,
alignment_ema = LEAST(1.0, GREATEST(0.0,
alignment_ema * (1.0 - v_alpha) + p_alignment_before * v_alpha
)),
success_ema = LEAST(1.0, GREATEST(0.0,
success_ema * (1.0 - v_alpha) + v_success * v_alpha
)),
latency_ms_ema = CASE
WHEN p_latency_ms IS NOT NULL THEN
latency_ms_ema * (1.0 - v_alpha) + p_latency_ms * v_alpha
ELSE latency_ms_ema
END,
-- Cumulative ΔS
delta_s_sum = delta_s_sum + v_delta_s,
-- Rolling entropy window (keep last 60 values)
entropy_trend_1h = (
ARRAY[p_entropy_after] ||
entropy_trend_1h[1:LEAST(59, array_length(entropy_trend_1h, 1))]
)
WHERE tool_id = p_tool_id;
-- -------------------------------------------------------------------------
-- 3. Update session_state
-- -------------------------------------------------------------------------
UPDATE gep.session_state
SET
tool_call_count = tool_call_count + 1,
calls_last_minute = CASE
WHEN last_call_at > now() - interval '1 minute' THEN calls_last_minute + 1
ELSE 1
END,
last_call_at = now(),
violation_count = CASE
WHEN p_outcome IN ('fail', 'blocked') THEN violation_count + 1
WHEN p_outcome = 'ok' AND violation_count > 0 THEN GREATEST(0, violation_count - 1)
ELSE violation_count
END,
entropy_current = COALESCE(p_entropy_after, p_entropy_before),
alignment_current = p_alignment_before,
entropy_history = (
ARRAY[COALESCE(p_entropy_after, p_entropy_before)] ||
entropy_history[1:LEAST(19, array_length(entropy_history, 1))]
),
delta_s_session = delta_s_session + v_delta_s
WHERE session_id = p_session_id;
-- -------------------------------------------------------------------------
-- 4. Periodically update percentiles (every 100 calls)
-- -------------------------------------------------------------------------
PERFORM 1 FROM gep.tool_state
WHERE tool_id = p_tool_id AND uses_total % 100 = 0;
IF FOUND THEN
-- Recompute percentiles from recent history
WITH recent_entropy AS (
SELECT entropy_after
FROM gep.tool_events
WHERE tool_id = p_tool_id
AND entropy_after IS NOT NULL
AND ts > now() - interval '7 days'
ORDER BY ts DESC
LIMIT 1000
)
UPDATE gep.tool_state
SET
entropy_baseline = (SELECT percentile_cont(0.50) WITHIN GROUP (ORDER BY entropy_after) FROM recent_entropy),
entropy_p50 = (SELECT percentile_cont(0.50) WITHIN GROUP (ORDER BY entropy_after) FROM recent_entropy),
entropy_p90 = (SELECT percentile_cont(0.90) WITHIN GROUP (ORDER BY entropy_after) FROM recent_entropy),
entropy_p99 = (SELECT percentile_cont(0.99) WITHIN GROUP (ORDER BY entropy_after) FROM recent_entropy)
WHERE tool_id = p_tool_id;
END IF;
END;
$$ LANGUAGE plpgsql;
COMMENT ON FUNCTION gep.log_and_update IS 'Log execution event and update GEP state metrics via EMA';
-- ============================================================================
-- SEED DATA: Example tools with GEP profiles
-- ============================================================================
-- Low-entropy read operations
INSERT INTO gep.tool_registry(name, description, protocol, endpoint,
base_entropy, entropy_variance, alignment_req,
risk_level, side_effect_class, idempotent, tags)
VALUES
('sys_health', 'Read system health metrics', 'local_exec', '/opt/nexus/tools/sys_health.sh',
0.15, 0.05, 0.60, 1, 'read', TRUE, ARRAY['ops','monitoring']),
('journal_tail', 'Tail systemd journal', 'local_exec', '/opt/nexus/tools/journal_tail.sh',
0.25, 0.10, 0.65, 2, 'read', TRUE, ARRAY['ops','logs']),
('db_query', 'Execute read-only database query', 'local_exec', '/opt/nexus/tools/db_query.sh',
0.30, 0.15, 0.70, 2, 'read', TRUE, ARRAY['data','query'])
ON CONFLICT (name) DO NOTHING;
-- Medium-entropy write operations
INSERT INTO gep.tool_registry(name, description, protocol, endpoint,
base_entropy, entropy_variance, alignment_req,
risk_level, side_effect_class, idempotent, tags)
VALUES
('config_update', 'Update service configuration', 'local_exec', '/opt/nexus/tools/config_update.sh',
0.45, 0.20, 0.80, 3, 'write', TRUE, ARRAY['ops','config']),
('db_insert', 'Insert data into database', 'local_exec', '/opt/nexus/tools/db_insert.sh',
0.50, 0.25, 0.80, 3, 'write', FALSE, ARRAY['data','write'])
ON CONFLICT (name) DO NOTHING;
-- High-entropy destructive operations
INSERT INTO gep.tool_registry(name, description, protocol, endpoint,
base_entropy, entropy_variance, alignment_req,
risk_level, side_effect_class, idempotent, tags)
VALUES
('iptables_apply', 'Apply firewall ruleset', 'local_exec', '/opt/nexus/tools/iptables_apply.sh',
0.70, 0.30, 0.90, 5, 'destructive', FALSE, ARRAY['sec','network']),
('service_restart', 'Restart system service', 'local_exec', '/opt/nexus/tools/service_restart.sh',
0.65, 0.25, 0.85, 4, 'destructive', TRUE, ARRAY['ops','service'])
ON CONFLICT (name) DO NOTHING;
-- Create policies with GEP-aware thresholds
INSERT INTO gep.tool_policy(tool_id, max_runtime_ms, rate_limit_per_min,
throttle_threshold_multiplier, stepup_threshold_multiplier, block_threshold_multiplier,
min_alignment_allow, min_alignment_write, min_alignment_destruct)
SELECT
tool_id,
CASE
WHEN side_effect_class = 'destructive' THEN 10000
WHEN side_effect_class = 'write' THEN 30000
ELSE 30000
END,
CASE
WHEN side_effect_class = 'destructive' THEN 5
WHEN side_effect_class = 'write' THEN 30
ELSE 120
END,
CASE
WHEN side_effect_class = 'destructive' THEN 1.2
WHEN side_effect_class = 'write' THEN 1.5
ELSE 2.0
END,
CASE
WHEN side_effect_class = 'destructive' THEN 1.5
WHEN side_effect_class = 'write' THEN 2.0
ELSE 2.5
END,
CASE
WHEN side_effect_class = 'destructive' THEN 1.8
WHEN side_effect_class = 'write' THEN 2.5
ELSE 3.0
END,
0.70, 0.80, 0.90
FROM gep.tool_registry
WHERE name IN ('sys_health', 'journal_tail', 'db_query', 'config_update', 'db_insert', 'iptables_apply', 'service_restart')
ON CONFLICT DO NOTHING;
-- Seed intent mappings (NOTE: intent_embedding requires actual vectors from your encoder)
-- For now, placeholder NULL vectors - populate these from Python using your SentenceTransformer
INSERT INTO gep.intent_map(tool_id, intent_pattern, priority, expected_entropy, entropy_variance, intent_embedding)
VALUES
((SELECT tool_id FROM gep.tool_registry WHERE name='sys_health'),
'check.*health|status.*system|system.*status', 100, 0.15, 0.05, NULL),
((SELECT tool_id FROM gep.tool_registry WHERE name='journal_tail'),
'show.*logs?|tail.*journal|view.*logs?', 100, 0.25, 0.10, NULL),
((SELECT tool_id FROM gep.tool_registry WHERE name='iptables_apply'),
'apply.*firewall|update.*iptables|firewall.*rules', 100, 0.70, 0.30, NULL)
ON CONFLICT DO NOTHING;
-- ============================================================================
-- UTILITY VIEWS
-- ============================================================================
-- Recent events with GEP metrics
CREATE OR REPLACE VIEW gep.v_recent_events AS
SELECT
e.event_id,
e.ts,
e.session_id,
e.operator_id,
t.name AS tool_name,
e.intent,
e.action,
e.outcome,
e.latency_ms,
e.entropy_before,
e.entropy_after,
e.delta_s,
e.alignment_before,
e.decision_score,
e.decision_reason
FROM gep.tool_events e
LEFT JOIN gep.tool_registry t ON t.tool_id = e.tool_id
ORDER BY e.ts DESC
LIMIT 100;
-- Tool performance summary
CREATE OR REPLACE VIEW gep.v_tool_performance AS
SELECT
t.tool_id,
t.name,
t.side_effect_class,
t.risk_level,
s.uses_total,
s.failures_total,
s.blocks_total,
ROUND(s.success_ema::numeric, 3) AS success_rate,
ROUND(s.entropy_ema::numeric, 3) AS current_entropy,
ROUND(s.entropy_baseline::numeric, 3) AS baseline_entropy,
ROUND(s.alignment_ema::numeric, 3) AS avg_alignment,
ROUND(s.latency_ms_ema::numeric, 0) AS avg_latency_ms,
s.last_used_at
FROM gep.tool_registry t
LEFT JOIN gep.tool_state s ON s.tool_id = t.tool_id
WHERE t.enabled = TRUE
ORDER BY s.uses_total DESC NULLS LAST;
-- ============================================================================
-- PERMISSIONS (adjust for your security model)
-- ============================================================================
-- Create roles
DO $$
BEGIN
IF NOT EXISTS (SELECT 1 FROM pg_roles WHERE rolname = 'nexus_mcp') THEN
CREATE ROLE nexus_mcp LOGIN PASSWORD 'change_me_in_production';
END IF;
IF NOT EXISTS (SELECT 1 FROM pg_roles WHERE rolname = 'nexus_readonly') THEN
CREATE ROLE nexus_readonly LOGIN PASSWORD 'change_me_readonly';
END IF;
END
$$;
-- MCP role: full access to functions, limited table access
GRANT USAGE ON SCHEMA gep TO nexus_mcp;
GRANT SELECT ON ALL TABLES IN SCHEMA gep TO nexus_mcp;
GRANT INSERT ON gep.tool_events, gep.session_state TO nexus_mcp;
GRANT UPDATE ON gep.tool_state, gep.session_state TO nexus_mcp;
GRANT EXECUTE ON ALL FUNCTIONS IN SCHEMA gep TO nexus_mcp;
-- Read-only role: analytics and monitoring
GRANT USAGE ON SCHEMA gep TO nexus_readonly;
GRANT SELECT ON ALL TABLES IN SCHEMA gep TO nexus_readonly;
-- ============================================================================
-- COMPLETION MESSAGE
-- ============================================================================
DO $$
BEGIN
RAISE NOTICE '';
RAISE NOTICE '========================================================================';
RAISE NOTICE 'GEP-NATIVE MCP CONTROL LAYER v2.0 - Installation Complete';
RAISE NOTICE '========================================================================';
RAISE NOTICE '';
RAISE NOTICE 'Database: gep_mcp_v2';
RAISE NOTICE 'Schema: gep';
RAISE NOTICE '';
RAISE NOTICE 'Core tables created:';
RAISE NOTICE ' - tool_registry: % tools', (SELECT count(*) FROM gep.tool_registry);
RAISE NOTICE ' - tool_state: % initialized', (SELECT count(*) FROM gep.tool_state);
RAISE NOTICE ' - tool_policy: % policies', (SELECT count(*) FROM gep.tool_policy);
RAISE NOTICE ' - intent_map: % mappings', (SELECT count(*) FROM gep.intent_map);
RAISE NOTICE '';
RAISE NOTICE 'Functions available:';
RAISE NOTICE ' - gep.gep_route_and_gate(): GEP motor neuron routing';
RAISE NOTICE ' - gep.log_and_update(): Event logging with state updates';
RAISE NOTICE '';
RAISE NOTICE 'Next steps:';
RAISE NOTICE ' 1. Update intent_embedding vectors using Python SentenceTransformer';
RAISE NOTICE ' 2. Create your tool scripts in /opt/nexus/tools/';
RAISE NOTICE ' 3. Configure connection string in Python MCP client';
RAISE NOTICE ' 4. Review and adjust EMA smoothing factor (v_alpha) in log_and_update()';
RAISE NOTICE ' 5. Customize threshold multipliers in tool_policy table';
RAISE NOTICE '';
RAISE NOTICE 'Security:';
RAISE NOTICE ' - Change default passwords for nexus_mcp and nexus_readonly roles';
RAISE NOTICE ' - Review permissions in PERMISSIONS section';
RAISE NOTICE '';
RAISE NOTICE 'Documentation: See comments in SQL and accompanying Python integration code';
RAISE NOTICE '========================================================================';
RAISE NOTICE '';
END
$$;