Status: Proposed Date: 2026-03-03 Authors: RuVector Team Deciders: ruv Supersedes: N/A Related: ADR-076 (AGI Capability Wiring Architecture), ADR-075 (RVF AGI Stack Brain Integration), ADR-068 (Domain Expansion Transfer Learning)
The mcp-brain-server at pi.ruv.io is a production axum REST API on Cloud Run with 238+ shared memories, Phase 8 AGI subsystems (SONA, GWT, DeltaStream, DomainExpansionEngine), an RVF security stack, and a hybrid keyword+cosine+graph+reputation scoring pipeline. Current read latency is 60-80ms and write latency is 150ms at 40-concurrent p90=172ms.
Despite this sophistication, several capability gaps remain:
-
No temporal pattern matching on embedding evolution. The DeltaStream records embedding deltas over time, but there is no way to find memories whose embedding trajectories are similar to each other. Two knowledge nodes may evolve the same way (both drifting toward security topics, for instance) but the system cannot detect this.
-
No deadline-aware background task scheduling. AGI subsystems (SONA tick, GWT decay, delta compaction) run ad-hoc inside request handlers or on status checks. There is no priority-based scheduler guaranteeing that critical maintenance (e.g., compaction before Firestore timeout) completes before less urgent work (e.g., pattern re-indexing).
-
No dynamical systems analysis of knowledge drift. The DriftMonitor computes coefficient-of-variation but cannot classify whether the knowledge graph is converging to a stable attractor, oscillating in a limit cycle, or exhibiting chaotic drift. Lyapunov exponent analysis would provide this.
-
No formal invariant verification. Memory operations have implicit invariants (witness chain integrity, embedding dimension consistency, quality score monotonicity under upvotes) that are checked procedurally. Linear Temporal Logic (LTL) verification would provide formal guarantees.
-
No recursive meta-cognition with safety bounds. The DomainExpansionEngine does Thompson Sampling meta-learning but cannot recursively reason about its own learning strategy. Self-modification (changing exploration parameters based on accumulated regret) is manually tuned.
-
No high-performance brain-to-brain transport. Federation currently uses HTTP/1.1 REST via reqwest. A future multi-brain mesh needs multiplexed, 0-RTT transport for real-time knowledge synchronization.
The midstream platform provides six crates that address each gap precisely.
Integrate all six midstream crates into mcp-brain-server in a phased rollout, each behind an independent feature flag (env var). Every crate maps to a specific gap identified in Section 1 and wires into existing handlers without disrupting the current scoring pipeline.
| Crate | Gap Addressed | Integration Target |
|---|---|---|
temporal-compare |
Embedding evolution similarity | search_memories() DTW-based trajectory matching |
nanosecond-scheduler |
Background task scheduling | SONA tick, GWT decay, delta compaction, LTL checks |
temporal-attractor-studio |
Dynamical systems drift analysis | Knowledge drift classification (chaotic vs stable) |
temporal-neural-solver |
Formal invariant verification | LTL properties on memory operations |
strange-loop |
Recursive meta-cognition | Self-modifying meta-learning atop DomainExpansionEngine |
quic-multistream |
Brain-to-brain federation | Future multi-brain mesh transport |
Midstream crates compose on top of existing AGI subsystems rather than replacing them:
Layer 4 (Midstream Meta): strange-loop (recursive self-improvement)
Layer 3 (Midstream Analysis): temporal-attractor-studio + temporal-neural-solver
Layer 2 (Midstream Infra): nanosecond-scheduler + temporal-compare
Layer 1 (Phase 8 AGI): SONA + GWT + DeltaStream + DomainExpansionEngine
Layer 0 (Core): Firestore + KnowledgeGraph + RVF + Embeddings
No midstream crate touches Layer 0 directly. All access goes through Layer 1 state via AppState.
Following ADR-076's precedent, midstream scoring signals are small and additive:
Existing scoring pipeline (unchanged):
keyword_boost + cosine_sim + graph_ppr + reputation + vote_quality
+ SONA pattern boost (0.15)
+ GWT attention boost (0.1)
+ Meta curiosity boost (0.05)
New midstream additions:
+ temporal_compare DTW similarity boost: dtw_score * 0.08
+ attractor stability boost: stability_bonus * 0.03
+ strange_loop confidence boost: confidence * 0.02
Total midstream contribution is bounded to 0.13, well below the existing AGI layer total of 0.30. This ensures midstream can never dominate ranking.
All periodic background tasks (previously scattered across handlers) consolidate under nanosecond-scheduler:
| Task | Priority | Deadline | Current Location | New Location |
|---|---|---|---|---|
| SONA tick | Medium(50) | 50ms | status() handler |
Scheduler (10s interval) |
| GWT decay/compete | Medium(50) | 20ms | search_memories() |
Scheduler (5s interval) |
| DeltaStream compaction | Low(25) | 200ms | Never (unbounded growth) | Scheduler (60s interval) |
| LTL invariant checks | Low(25) | 100ms | Never | Scheduler (30s interval) |
| Attractor analysis | Background(10) | 500ms | Never | Scheduler (120s interval) |
| Strange-loop reflection | Background(10) | 1000ms | Never | Scheduler (300s interval) |
This removes AGI maintenance work from the request hot path, directly reducing read latency.
share_memory() flow:
1. [existing] PII strip, embed, witness chain, RVF container
2. [existing] Push VectorDelta to DeltaStream
3. [existing] Record "contribute" decision in MetaLearningEngine
4. [NEW: Phase 9a] Append embedding to TemporalComparator trajectory buffer
5. [NEW: Phase 9c] Push PhasePoint to AttractorAnalyzer (category-scoped)
6. [NEW: Phase 9d] Add state to TemporalNeuralSolver (witness_valid, dim_correct)
7. [existing] Add to graph, store in Firestore
Steps 4-6 are non-blocking appends to in-memory buffers. No additional latency on the write path.
search_memories() flow:
1. [existing] Embed query, fetch candidates, keyword+cosine scoring
2. [existing] RankingEngine attention adjustments
3. [existing] GWT salience competition
4. [existing] SONA pattern re-ranking
5. [existing] Meta-learning curiosity bonus
6. [NEW: Phase 9a] Temporal trajectory similarity boost (DTW)
7. [NEW: Phase 9c] Attractor stability boost
8. [NEW: Phase 9e] Strange-loop confidence boost
9. [existing] Final sort, truncate to limit
10. [existing] SONA trajectory recording
Steps 6-8 use read locks only and add bounded scoring signals.
vote_memory() flow:
1. [existing] Quality update, reputation, poisoning check
2. [existing] Push vote delta to DeltaStream
3. [existing] Feed vote as reward to MetaLearningEngine
4. [NEW: Phase 9e] Feed vote as reward signal to StrangeLoop (meta-level feedback)
5. [NEW: Phase 9d] Record vote_quality_increased proposition in LTL solver
Steps 4-5 are fire-and-forget writes to in-memory state.
status() flow:
1. [existing] Graph stats, quality, drift, DP, SONA, GWT, temporal, meta stats
2. [NEW: Phase 9b] Scheduler stats (tasks completed, missed deadlines, avg latency)
3. [NEW: Phase 9c] Attractor classification (point/limit_cycle/strange) per category
4. [NEW: Phase 9d] LTL invariant health (properties verified, violations detected)
5. [NEW: Phase 9e] Strange-loop meta-knowledge summary (depth, confidence)
6. [NEW: Phase 9f] Federation transport stats (if quic-multistream active)
| Field | Type | Crate | Description |
|---|---|---|---|
temporal_comparator |
Arc<RwLock<temporal_compare::TemporalComparator<f32>>> |
temporal-compare | DTW/LCS/EditDistance on embedding sequences |
scheduler |
Arc<RwLock<nanosecond_scheduler::RealtimeScheduler<SchedulerPayload>>> |
nanosecond-scheduler | Priority-based background task executor |
attractor_analyzers |
Arc<RwLock<HashMap<String, temporal_attractor_studio::AttractorAnalyzer>>> |
temporal-attractor-studio | Per-category dynamical systems analysis |
ltl_solver |
Arc<RwLock<temporal_neural_solver::TemporalNeuralSolver>> |
temporal-neural-solver | LTL property verification engine |
strange_loop |
Arc<RwLock<strange_loop::StrangeLoop>> |
strange-loop | Meta-cognitive recursive learning |
quic_stats |
Arc<RwLock<Option<QuicFederationStats>>> |
quic-multistream | Federation transport statistics (Phase 9f only) |
/// Payload for scheduled background tasks.
#[derive(Debug, Clone)]
pub enum SchedulerPayload {
SonaTick,
GwtDecay,
DeltaCompact { max_entries: usize },
LtlCheck,
AttractorAnalyze { category: String },
StrangeLoopReflect,
}/// Statistics from quic-multistream federation transport.
#[derive(Debug, Clone, Default, Serialize)]
pub struct QuicFederationStats {
pub active_peers: usize,
pub active_streams: usize,
pub bytes_sent: u64,
pub bytes_received: u64,
pub avg_rtt_ms: f64,
}Returns temporal trajectory similarity analysis for a given memory.
Query Parameters:
memory_id(required): UUID of the memory to find similar trajectories foralgorithm(optional):dtw|lcs|edit_distance(default:dtw)threshold(optional): minimum similarity (default: 0.7)limit(optional): max results (default: 5)
Response:
{
"query_memory_id": "550e8400-e29b-41d4-a716-446655440000",
"algorithm": "dtw",
"similar_trajectories": [
{
"memory_id": "660e8400-e29b-41d4-a716-446655440001",
"distance": 0.12,
"similarity": 0.88,
"alignment_length": 15
}
],
"recurring_patterns": [
{
"pattern_length": 8,
"occurrences": 3,
"confidence": 0.92
}
]
}Returns background task scheduler statistics.
Response:
{
"total_scheduled": 1247,
"total_completed": 1240,
"missed_deadlines": 2,
"avg_latency_ns": 45000,
"tasks_by_priority": {
"critical": 0,
"high": 12,
"medium": 820,
"low": 408,
"background": 7
},
"next_deadline_ms": 4200
}Returns dynamical systems analysis of knowledge drift per category.
Query Parameters:
category(optional): specific category to analyze (default: all)
Response:
{
"categories": {
"architecture": {
"attractor_type": "point_attractor",
"lyapunov_exponents": [-0.32, -0.18, -0.05],
"is_stable": true,
"is_chaotic": false,
"confidence": 0.94,
"trajectory_length": 45,
"mean_velocity": 0.023
},
"security": {
"attractor_type": "strange_attractor",
"lyapunov_exponents": [0.12, -0.04, -0.21],
"is_stable": false,
"is_chaotic": true,
"confidence": 0.78,
"trajectory_length": 32,
"mean_velocity": 0.089
}
},
"global_stability": "mixed"
}Returns LTL invariant verification status.
Response:
{
"properties_defined": 5,
"properties_verified": 4,
"violations": [
{
"property": "globally(embedding_dim_128)",
"satisfied": false,
"confidence": 0.99,
"counterexample": "memory abc123 has dim=64 at state 17"
}
],
"last_check_ms": 12,
"total_states_checked": 238
}Returns strange-loop meta-cognitive status.
Response:
{
"meta_depth": 2,
"knowledge_items": 7,
"top_patterns": [
{
"level": 1,
"pattern": "security_memories_converge_faster",
"confidence": 0.87,
"applications": ["adjust_curiosity_weight", "increase_security_exploration"]
}
],
"self_modifications_applied": 3,
"safety_constraints_active": 2,
"is_self_modification_enabled": true
}Returns QUIC federation transport statistics (Phase 9f only).
Response:
{
"transport": "quic-h3",
"active_peers": 0,
"active_streams": 0,
"bytes_sent": 0,
"bytes_received": 0,
"avg_rtt_ms": 0.0,
"zero_rtt_supported": true,
"status": "standby"
}All midstream subsystems are gated by environment variables, read once at startup via RvfFeatureFlags::from_env(). All default to disabled (opt-in) because midstream crates add new dependencies and should be validated incrementally.
| Env Var | Default | Controls |
|---|---|---|
MIDSTREAM_TEMPORAL_COMPARE |
false |
DTW trajectory matching in search |
MIDSTREAM_SCHEDULER |
false |
Background task scheduler |
MIDSTREAM_ATTRACTOR |
false |
Dynamical systems drift analysis |
MIDSTREAM_LTL |
false |
LTL invariant verification |
MIDSTREAM_STRANGE_LOOP |
false |
Recursive meta-cognition |
MIDSTREAM_QUIC |
false |
QUIC federation transport |
// Add to existing RvfFeatureFlags struct:
pub midstream_temporal_compare: bool,
pub midstream_scheduler: bool,
pub midstream_attractor: bool,
pub midstream_ltl: bool,
pub midstream_strange_loop: bool,
pub midstream_quic: bool,// Add to from_env():
midstream_temporal_compare: std::env::var("MIDSTREAM_TEMPORAL_COMPARE")
.map(|v| v == "true" || v == "1")
.unwrap_or(false),
midstream_scheduler: std::env::var("MIDSTREAM_SCHEDULER")
.map(|v| v == "true" || v == "1")
.unwrap_or(false),
midstream_attractor: std::env::var("MIDSTREAM_ATTRACTOR")
.map(|v| v == "true" || v == "1")
.unwrap_or(false),
midstream_ltl: std::env::var("MIDSTREAM_LTL")
.map(|v| v == "true" || v == "1")
.unwrap_or(false),
midstream_strange_loop: std::env::var("MIDSTREAM_STRANGE_LOOP")
.map(|v| v == "true" || v == "1")
.unwrap_or(false),
midstream_quic: std::env::var("MIDSTREAM_QUIC")
.map(|v| v == "true" || v == "1")
.unwrap_or(false),- Deploy with all flags
false-- baseline performance unchanged - Enable
MIDSTREAM_SCHEDULER=truefirst (moves AGI maintenance off hot path) - Enable
MIDSTREAM_TEMPORAL_COMPARE=true(new search signal) - Enable
MIDSTREAM_ATTRACTOR=true(drift analysis) - Enable
MIDSTREAM_LTL=true(invariant checking) - Enable
MIDSTREAM_STRANGE_LOOP=true(meta-cognition) - Enable
MIDSTREAM_QUIC=trueonly when peer brains exist
The full scoring pipeline after midstream integration, showing exact order and coefficients:
search_memories() scoring pipeline:
1. Base hybrid score (existing, unchanged):
IF keyword_match:
score = 1.0 + keyword_boost * 0.85 + vec_sim * 0.05
+ graph_ppr * 0.04 + reputation * 0.03 + vote_boost * 0.03
ELSE:
score = vec_sim * 0.45 + graph_ppr * 0.25
+ reputation * 0.15 + vote_boost * 0.15
2. RankingEngine adjustments (existing, unchanged):
score = similarity_weight(0.85) * score
+ quality_weight(0.10) * quality_mean
+ recency_weight(0.05) * recency_factor
3. GWT attention (existing, unchanged):
score += 0.10 for workspace competition winners
score += sparse_activation * 0.05 for K-WTA
4. SONA pattern (existing, unchanged):
score += avg(cosine(mem, pattern) * pattern_quality) * 0.15
5. Meta-learning curiosity (existing, unchanged):
score += novelty_score * 0.05
6. [NEW] Temporal trajectory similarity (Phase 9a):
IF MIDSTREAM_TEMPORAL_COMPARE enabled AND query has temporal context:
dtw_score = temporal_comparator.find_similar(query_trajectory, threshold=0.7)
score += dtw_score * 0.08 for memories with similar evolution paths
7. [NEW] Attractor stability bonus (Phase 9c):
IF MIDSTREAM_ATTRACTOR enabled:
attractor = attractor_analyzers[memory.category].analyze()
IF attractor.is_stable AND attractor.confidence > 0.8:
score += 0.03 // prefer memories in stable knowledge regions
8. [NEW] Strange-loop confidence bonus (Phase 9e):
IF MIDSTREAM_STRANGE_LOOP enabled:
meta_knowledge = strange_loop.learn_at_level(0, query_context)
IF any meta_knowledge has confidence > 0.9:
score += meta_knowledge.confidence * 0.02
9. Final sort (single unstable_sort_by descending score)
10. Truncate to limit
| Layer | Max Contribution | Source |
|---|---|---|
| Keyword boost | 3.0 | ADR-076 (unchanged) |
| Vector similarity | 0.45 | Core scoring |
| Graph PPR | 0.25 | Core scoring |
| Reputation + votes | 0.30 | Core scoring |
| RankingEngine | ~1.0 | Quality/recency blend |
| GWT attention | 0.15 | ADR-076 |
| SONA patterns | 0.15 | ADR-076 |
| Meta curiosity | 0.05 | ADR-076 |
| Temporal compare | 0.08 | Phase 9a (new) |
| Attractor stability | 0.03 | Phase 9c (new) |
| Strange-loop | 0.02 | Phase 9e (new) |
| Midstream total | 0.13 | Sum of new layers |
Dependency: None (standalone crate)
Wiring:
- Add
temporal_comparator: Arc<RwLock<TemporalComparator<f32>>>to AppState - Initialize with
TemporalComparator::new(1000, 500)(cache 1000 comparisons, max 500-step sequences) - In
share_memory(): after DeltaStream push, append embedding to per-memory trajectory buffer in comparator - In
search_memories(): after SONA re-ranking, usefind_similar_generic()to boost memories with similar embedding evolution trajectories (DTW distance < 0.3 threshold) - Add
GET /v1/temporal/trajectoriesendpoint - Gate all with
MIDSTREAM_TEMPORAL_COMPAREenv var
Data flow:
share_memory() -> embedding -> temporal_comparator.trajectory_buffer[memory_id].push(embedding)
search_memories() -> query_trajectory -> find_similar_generic(candidates, query, 0.7) -> score += dtw * 0.08
Latency budget: +3ms read path (DTW on cached trajectories), +0ms write path (buffer append)
Dependency: None (standalone), but should be enabled before other phases to manage their background tasks
Wiring:
- Add
scheduler: Arc<RwLock<RealtimeScheduler<SchedulerPayload>>>to AppState - Initialize with EDF (Earliest Deadline First) policy
- Spawn a
tokio::spawnloop that callsscheduler.next_task()and dispatches:SonaTick->state.sona.read().tick()GwtDecay->state.workspace.write().compete()DeltaCompact->state.delta_stream.write().compact(max_entries)LtlCheck->state.ltl_solver.write().verify(invariants)AttractorAnalyze->state.attractor_analyzers.write()[cat].analyze()StrangeLoopReflect->state.strange_loop.write().learn_at_level(0, data)
- Remove SONA tick from
status()handler (moved to scheduler) - Add
GET /v1/scheduler/statsendpoint - Gate with
MIDSTREAM_SCHEDULERenv var
Scheduler task registration at startup:
// Register recurring tasks with appropriate priorities and intervals
let mut sched = scheduler.write();
sched.schedule(SchedulerPayload::SonaTick, deadline_10s, Priority::Medium(50));
sched.schedule(SchedulerPayload::GwtDecay, deadline_5s, Priority::Medium(50));
sched.schedule(SchedulerPayload::DeltaCompact { max_entries: 10_000 },
deadline_60s, Priority::Low(25));Latency budget: -5ms read path (SONA tick removed from status), +0ms (scheduler runs in background task)
Dependency: Phase 9b (scheduler runs attractor analysis in background)
Wiring:
- Add
attractor_analyzers: Arc<RwLock<HashMap<String, AttractorAnalyzer>>>to AppState - Initialize one
AttractorAnalyzer::new(128, 1000)per known category (embedding_dim=128, max_trajectory=1000) - In
share_memory(): after DeltaStream push, callanalyzer.add_point(PhasePoint { coordinates: embedding, timestamp })for the memory's category - Background (via scheduler): every 120s, call
analyzer.analyze()for each category to getAttractorInfo - In
search_memories(): ifattractor.is_stable && confidence > 0.8, add+0.03stability bonus to memories in that category - In
status(): reportattractor_typeandis_chaoticper category - Add
GET /v1/attractorendpoint - Gate with
MIDSTREAM_ATTRACTORenv var
Attractor classification interpretation:
PointAttractor(all Lyapunov exponents < 0): knowledge is converging -- stable domain, prefer these memoriesLimitCycle(one exponent = 0, rest < 0): knowledge oscillates -- possibly seasonal patternsStrangeAttractor(at least one exponent > 0): chaotic evolution -- flag for human review, reduce score weight
Latency budget: +1ms read path (HashMap lookup + cached AttractorInfo read), +0ms write path (point append)
Dependency: Phase 9b (scheduler runs LTL checks in background)
Wiring:
- Add
ltl_solver: Arc<RwLock<TemporalNeuralSolver>>to AppState - Initialize with
TemporalNeuralSolver::new(10_000, 100, Strictness::Medium)(max 10K trace, 100ms timeout) - Define invariant properties at startup:
use temporal_neural_solver::formula::*;
// Property 1: Embedding dimension is always 128
let dim_128 = globally(atom("embedding_dim_128"));
// Property 2: Quality score never decreases after upvote
let quality_monotone = globally(
implies(atom("upvote_applied"), finally(atom("quality_increased")))
);
// Property 3: Witness chain is always present when RVF enabled
let witness_present = globally(
implies(atom("rvf_enabled"), atom("witness_chain_present"))
);
// Property 4: PII stripping happens before embedding
let pii_before_embed = globally(
implies(atom("has_pii"), until(atom("pii_stripped"), atom("embedded")))
);
// Property 5: No memory exists in both graph and negative cache
let no_blacklisted_in_graph = globally(
not(and(atom("in_graph"), atom("in_negative_cache")))
);- In
share_memory(): pushTemporalStatewith propositions{embedding_dim_128: dim==128, witness_chain_present: chain.is_some(), ...} - In
vote_memory(): pushTemporalStatewith{upvote_applied: true, quality_increased: new > old} - Background (via scheduler): every 30s, verify all properties and log violations
- Add
GET /v1/invariantsendpoint - Gate with
MIDSTREAM_LTLenv var
On violation: log at WARN level, increment violation counter, but do not block operations. LTL verification is observational, not enforcement.
Latency budget: +0ms read path (verification runs in background only), +0.5ms write path (state push)
Dependency: Phase 9b (scheduler), Phase 9c (attractor data feeds meta-learning), DomainExpansionEngine (existing)
Wiring:
- Add
strange_loop: Arc<RwLock<StrangeLoop>>to AppState - Initialize with:
let config = StrangeLoopConfig {
max_meta_depth: 3, // Max 3 levels of recursive reflection
enable_self_modification: true,
safety_check: true,
};
let mut sl = StrangeLoop::new(config);
// Safety constraints
sl.add_safety_constraint(always_safe()); // Never produce unsafe state
sl.add_safety_constraint(eventually_terminates()); // Always halt
// Custom: curiosity weight must stay in [0.01, 0.20]
sl.add_safety_constraint(custom_constraint(
"curiosity_bounds",
|state| state.curiosity_weight >= 0.01 && state.curiosity_weight <= 0.20
));
// Custom: meta-depth must not exceed config limit
sl.add_safety_constraint(custom_constraint(
"depth_limit",
|state| state.current_depth <= 3
));-
Background (via scheduler): every 300s, run
learn_at_level(0, trajectory_data)where trajectory_data comes from:- SONA trajectory stats (patterns found, quality distribution)
- DomainExpansion regret history (per-category regret)
- Attractor stability classification (from Phase 9c)
-
Meta-knowledge application: when
MetaKnowledgeitems have confidence > 0.9, apply modifications:adjust_curiosity_weight(delta)-> modify DomainExpansionEngine's exploration factoradjust_sona_pattern_boost(delta)-> modify SONA scoring coefficient (0.15 +/- 0.03)flag_category_for_review(category)-> mark chaotic categories for human attention
-
In
search_memories(): if strange-loop has high-confidence meta-knowledge about the query category, addconfidence * 0.02boost -
In
vote_memory(): feed vote as reward to strange-loop at level 0 (meta-reward: "did the meta-knowledge improve search quality?") -
Add
GET /v1/meta/strange-loopendpoint -
Gate with
MIDSTREAM_STRANGE_LOOPenv var
Self-modification bounds (enforced by safety constraints):
- Curiosity weight: [0.01, 0.20] (cannot disable exploration or make it dominate)
- SONA pattern boost: [0.05, 0.25] (cannot disable patterns or make them dominate)
- Meta-depth: maximum 3 (prevents infinite recursion)
- Modification rate: maximum 1 modification per 300s cycle (prevents oscillation)
Latency budget: +1ms read path (cached meta-knowledge lookup), +0ms write path (async reward recording)
Dependency: All prior phases (federation transports the full brain state including midstream data)
Wiring:
- Add
quic_stats: Arc<RwLock<Option<QuicFederationStats>>>to AppState - When
MIDSTREAM_QUIC=true, initialize QUIC listener alongside the existing HTTP server:
// Separate listener for QUIC federation (port 4433 default)
let quic_port: u16 = std::env::var("QUIC_PORT")
.unwrap_or_else(|_| "4433".to_string())
.parse()?;-
Define stream priority mapping:
Critical: Memory write replication (consistency)High: Search query federation (latency-sensitive)Normal: Vote synchronizationLow: Background state sync (attractor data, meta-knowledge)
-
0-RTT for returning peer brains (session resumption avoids TLS handshake on reconnect)
-
Multiplexed bi-directional streams: each memory category gets its own stream for parallel sync
-
In
status(): reportquic_statsif transport is active -
Add
GET /v1/federation/statsendpoint -
Gate with
MIDSTREAM_QUICenv var
Latency budget: +0ms for existing endpoints (QUIC runs on separate port/task), +2ms for federated search (0-RTT + multiplexing)
Add to crates/mcp-brain-server/Cargo.toml under [dependencies]:
# Midstream Platform (ADR-077)
temporal-compare = "0.1"
nanosecond-scheduler = "0.1"
temporal-attractor-studio = "0.1"
temporal-neural-solver = "0.1"
strange-loop = "0.1"
quic-multistream = { version = "0.1", optional = true }Add feature flags for optional heavy dependencies:
[features]
default = []
quic-federation = ["quic-multistream"]quic-multistream is the only optional dependency because it pulls in quinn/rustls which significantly increases compile time and binary size. All other midstream crates are lightweight and always compiled (gated at runtime via env vars).
| Component | Current | With Midstream | Delta |
|---|---|---|---|
| Embedding + candidate fetch | 15ms | 15ms | +0ms |
| Keyword + cosine scoring | 10ms | 10ms | +0ms |
| Graph PPR | 8ms | 8ms | +0ms |
| RankingEngine | 2ms | 2ms | +0ms |
| GWT attention | 5ms | 5ms (moved to bg) | +0ms |
| SONA patterns | 3ms | 3ms | +0ms |
| Meta curiosity | 1ms | 1ms | +0ms |
| Temporal compare | - | 3ms | +3ms |
| Attractor lookup | - | 1ms | +1ms |
| Strange-loop lookup | - | 1ms | +1ms |
| Sort + truncate | 1ms | 1ms | +0ms |
| Total | ~45ms | ~50ms | +5ms |
Total read latency stays well under the 100ms budget. The scheduler actually reduces worst-case latency by removing SONA tick from the status handler.
| Component | Current | With Midstream | Delta |
|---|---|---|---|
| PII + embed + witness + RVF | 80ms | 80ms | +0ms |
| DeltaStream push | 0.5ms | 0.5ms | +0ms |
| Meta-learning record | 0.5ms | 0.5ms | +0ms |
| Temporal buffer append | - | 0.1ms | +0.1ms |
| Attractor point push | - | 0.1ms | +0.1ms |
| LTL state push | - | 0.5ms | +0.5ms |
| Graph + Firestore | 60ms | 60ms | +0ms |
| Total | ~141ms | ~142ms | +0.7ms |
| Component | Estimate | Notes |
|---|---|---|
| TemporalComparator | ~2MB | 1000 cached comparisons, 500-step sequences |
| RealtimeScheduler | <1MB | Priority queue of ~20 recurring tasks |
| AttractorAnalyzers (8 categories) | ~4MB | 8 * 1000-point trajectories * 128-dim |
| TemporalNeuralSolver | ~1MB | 10K trace buffer |
| StrangeLoop | <1MB | 3 meta-levels, bounded knowledge store |
| QuicFederationStats | <1KB | Statistics struct only (transport runs separately) |
| Total | ~8MB | On top of existing ~10MB AGI state |
The scheduler runs all background tasks on a single tokio::spawn loop. Worst-case CPU per cycle:
| Task | Frequency | CPU/cycle | Annual CPU-hours |
|---|---|---|---|
| SONA tick | 10s | 2ms | 6.3h |
| GWT decay | 5s | 1ms | 6.3h |
| Delta compact | 60s | 10ms | 5.3h |
| LTL check | 30s | 5ms | 5.3h |
| Attractor analyze | 120s | 50ms | 13.1h |
| Strange-loop reflect | 300s | 100ms | 10.5h |
| Total | - | - | 46.8h/year |
At Cloud Run pricing ($0.000024/vCPU-second), annual background cost is approximately $4.04.
The strange-loop crate's self-modification capability is the highest-risk component. The following safety envelope is enforced:
Hard limits (cannot be overridden):
- Maximum meta-depth: 3 levels (prevents infinite recursion)
always_safe()constraint: no modification can produce a state where scoring coefficients sum to > 1.0eventually_terminates()constraint: everylearn_at_level()call must complete within 1000ms
Soft limits (can be tuned via env vars):
STRANGE_LOOP_MAX_DEPTH(default: 3, range: 1-5)STRANGE_LOOP_MODIFICATION_RATE(default: 1 per 300s, range: 1 per 60s to 1 per 3600s)STRANGE_LOOP_CURIOSITY_MIN(default: 0.01)STRANGE_LOOP_CURIOSITY_MAX(default: 0.20)
Rollback mechanism: If a self-modification causes any LTL property (Phase 9d) to fail in the next check cycle, the modification is automatically reverted and the strange-loop's modification capability is suspended for 1 hour (with WARN log).
The five core invariant properties are defined in Section 8 (Phase 9d). Additional properties can be added at runtime via the scheduler, but existing properties cannot be removed without a code change.
Verification semantics: Properties are checked over the trace buffer (last 10K state transitions), not over all-time history. This bounds verification time and avoids false positives from pre-midstream state.
DTW trajectory matching could theoretically leak information about a contributor's knowledge evolution pattern. Mitigation:
- Trajectory buffers are category-scoped, not contributor-scoped
- Embeddings in trajectories have already been DP-noised (if
RVF_DP_ENABLED=true) - The
find_similar_genericAPI returns distance scores only, not raw trajectories
If the scheduler misses a deadline (e.g., under high load), the task is still executed but:
missed_deadlinescounter is incremented (visible in/v1/scheduler/stats)- If
missed_deadlines > 10in any 60s window, emit WARN log - If
missed_deadlines > 50in any 60s window, disable lowest-priority tasks (Background(10)) for 5 minutes
- Temporal pattern matching enables discovery of memories with similar evolution trajectories, surfacing non-obvious relationships that cosine similarity alone misses
- Deadline-aware scheduling removes AGI maintenance work from the request hot path, reducing p99 read latency by ~5ms
- Dynamical systems analysis upgrades drift monitoring from simple CV thresholds to Lyapunov-exponent-based attractor classification, enabling early detection of chaotic knowledge domains
- LTL verification provides formal guarantees on system invariants, catching subtle bugs (dimension mismatches, witness chain gaps) that procedural checks might miss
- Recursive meta-cognition allows the brain server to self-tune exploration and scoring parameters based on accumulated evidence, reducing manual tuning burden
- QUIC transport (future) enables sub-millisecond brain-to-brain federation with 0-RTT resumption, a prerequisite for real-time multi-brain mesh
- All features are independently feature-gated with runtime env vars, zero risk to existing behavior when disabled
- Total latency impact of +5ms on reads and +0.7ms on writes stays well within the 100ms read budget
- Six additional crate dependencies increase compile time by an estimated 30-45 seconds (quic-multistream alone adds ~20s due to quinn/rustls)
- ~8MB additional memory footprint for in-memory trajectory buffers, analyzer state, and solver traces
- Increased operational complexity: six new env vars, six new endpoints, scheduler monitoring
- strange-loop self-modification introduces a novel failure mode: if safety constraints are misconfigured, the system could oscillate between parameter settings
- LTL verification has false-positive risk on edge cases where the trace buffer wraps around and loses historical context
- temporal-compare DTW on high-dimensional (128-dim) sequences may be slower than expected if trajectory lengths grow beyond 100 steps; mitigation: cap max_sequence_length at 500
- nanosecond-scheduler is designed for sub-microsecond scheduling, but tokio's cooperative scheduling has ~1ms granularity; actual scheduling precision will be millisecond-level, not nanosecond
- temporal-attractor-studio Lyapunov exponent estimation requires sufficient trajectory data (minimum ~30 points per category); new categories will show
insufficient_datauntil populated - temporal-neural-solver LTL verification confidence degrades if state transitions are sparse; the 30s check interval may verify the same state repeatedly during low-traffic periods
- strange-loop meta-learning effectiveness depends on diverse input signals; if traffic is dominated by a single category, meta-knowledge will be narrowly scoped
- quic-multistream requires TLS certificates for peer authentication; certificate management adds operational burden for multi-brain deployments
- Crate version stability: all midstream crates are at
0.1.x; API changes in minor versions could require brain server updates
cargo check -p mcp-brain-servercompiles with zero errors after adding all six dependenciescargo check -p mcp-brain-server --features quic-federationcompiles with quic-multistream enabled
- All Phase 1-8 tests continue to pass with all midstream flags disabled (default)
/v1/statusreturns all existing fields unchanged when midstream flags are off
- Enabling any single midstream flag does not affect behavior of other subsystems
- Disabling a midstream flag mid-operation (via restart) gracefully drops in-memory state without errors
GET /v1/temporal/trajectories?memory_id=<valid-uuid>returns valid JSON withsimilar_trajectoriesarrayGET /v1/scheduler/statsreturns valid JSON withtotal_scheduled >= 0GET /v1/attractorreturns valid JSON with per-categoryattractor_typefieldGET /v1/invariantsreturns valid JSON withproperties_defined >= 5GET /v1/meta/strange-loopreturns valid JSON withmeta_depth <= 3GET /v1/federation/statsreturns valid JSON withstatus: "standby"when no peers connected
- With all midstream flags enabled, total midstream score contribution never exceeds 0.13 for any single memory
- Search results with midstream enabled are a superset-reordering of results without midstream (no memories added or removed, only rank changes)
strange-loopwithmax_meta_depth: 3never recurses beyond level 3 (test with artificial depth-forcing input)- Self-modification that would set curiosity weight outside [0.01, 0.20] is rejected by safety constraint
- LTL violation triggers WARN log but does not block the violating operation
- Scheduler deadline miss increments counter without dropping the task
search_memorieswith all midstream flags enabled completes in < 100ms for 238 memories (p99)share_memorywith all midstream flags enabled completes in < 200ms (p99)- Background scheduler CPU usage stays under 1% of a single vCPU at steady state
- Memory footprint with all midstream state initialized stays under 20MB total (existing + midstream)
- 40-concurrent search requests with all midstream flags enabled: p90 < 200ms, p99 < 300ms
- No scheduler deadline misses under 40-concurrent sustained load for 60 seconds
All existing API contracts are unchanged. New endpoints are additive. Midstream scoring signals are additive and bounded. No breaking changes to any existing client.
No Firestore schema changes required. All midstream state is in-memory only. Persistence of midstream state (attractor histories, LTL traces, meta-knowledge) is a future consideration for a follow-up ADR.
The Dockerfile at crates/mcp-brain-server/Dockerfile needs no changes for Phases 9a-9e (pure Rust crates). Phase 9f (quic-multistream) requires exposing an additional UDP port in the Cloud Run service configuration:
# cloudbuild.yaml addition for Phase 9f only
ports:
- containerPort: 8080 # existing HTTP
- containerPort: 4433 # QUIC federation (UDP)
protocol: UDPNote: Cloud Run currently has limited UDP support. Phase 9f may require migration to GKE or a hybrid deployment model.