Reason — chain of thought, deterministic, MoT split
A chain of thought, deterministic, at picojoule grain. A small cascade walks each query through five tiers (arithmetic → named-fact lookup → HDC-style shape match → cited composition → model-class). Each tier is split into a reasoning expert (classify the form) and a generation expert (produce the answer); generation only runs when reasoning matches. Indented rows on the trace are generation hops; left-aligned rows are reasoning hops. Every sub-hop carries its own joule receipt. The exhibit rotates through eight canonical queries that exercise every resolution outcome including the model-class refusal.
view the kernel that wrote this receipt crates/mathground-view/src/cascade.rs
//! A tiny cognitive cascade for the math domain, split mixture-of-
//! transformers-style into per-tier reasoning + generation experts.
//!
//! Demonstrates the same SHAPE that a reasoning VLA emits — a chain of
//! decisions, each tagged with what was tried, what matched, and what it
//! cost — except every hop is deterministic. Each tier is now split into
//! two sub-experts:
//!
//! • Reasoning expert — does this query fit this tier's grammar?
//! (Decides the *form*; cheap; classifies.)
//! • Generation expert — given a recognised form, produce the answer.
//! (Only runs when the reasoning expert matched.)
//!
//! The visible trace expands to one hop per sub-expert that fired. A
//! resolved tier contributes TWO hops (reasoning ✓ → generation ✓); an
//! unmatched tier contributes ONE (reasoning ✗ — no generation needed).
//! Same architectural shape as Cosmos 3's mixture-of-transformers — one
//! reasoning transformer + one expert generation transformer — at zero
//! GPU cost.
//!
//! Tiers (ladder, checked in order; first matching tier resolves):
//!
//! L0-closed — arithmetic / symbolic evaluation.
//! L0-retrieved — exact citation lookup in a fixed table.
//! L0-identifiable — HDC-style shape match against a small atom pool.
//! L1 — citation-backed composition.
//! L2 — model-generated. Reasoning matches (recognises the
//! query as model-class); generation refuses and reports
//! the would-cost — substrate honesty.
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum CascadeTier {
L0Closed,
L0Retrieved,
L0Identifiable,
L1,
L2,
}
impl CascadeTier {
pub fn label(self) -> &'static str {
match self {
CascadeTier::L0Closed => "L0-closed",
CascadeTier::L0Retrieved => "L0-retrieved",
CascadeTier::L0Identifiable => "L0-identifiable",
CascadeTier::L1 => "L1",
CascadeTier::L2 => "L2",
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum SubExpert {
Reasoning,
Generation,
}
impl SubExpert {
pub fn label(self) -> &'static str {
match self {
SubExpert::Reasoning => "reasoning",
SubExpert::Generation => "generation",
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CascadeHop {
pub tier: CascadeTier,
pub expert: SubExpert,
/// Short, human-readable description of what this expert did.
pub action: String,
pub matched: bool,
pub bit_ops: u64,
pub wall_ns_per_op: f64,
/// Set only on the generation hop when generation succeeded.
pub answer: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CascadeTrace {
pub query: String,
pub hops: Vec<CascadeHop>,
pub resolved_at: Option<CascadeTier>,
pub final_answer: Option<String>,
pub total_bit_ops: u64,
}
/// Probe of a single tier — what its reasoning expert decided, what (if
/// anything) its generation expert produced, and the cost of each.
struct TierProbe {
reasoning_matched: bool,
reasoning_action: &'static str,
reasoning_cost: u64,
generation_action: Option<&'static str>,
generation_answer: Option<String>,
generation_cost: u64,
}
// ── L0-closed: arithmetic and basic algebra ───────────────────────────
enum ClosedForm {
BinaryArithmetic,
Factorial,
}
fn probe_l0_closed(query: &str) -> TierProbe {
let q = query.trim();
let parts: Vec<&str> = q.split_whitespace().collect();
let reason_cost = 64u64;
let mut form: Option<ClosedForm> = None;
if parts.len() == 3
&& matches!(parts[1], "+" | "-" | "*" | "/")
&& parts[0].parse::<f64>().is_ok()
&& parts[2].parse::<f64>().is_ok()
{
form = Some(ClosedForm::BinaryArithmetic);
} else if let Some(stripped) = q.strip_suffix('!') {
if let Ok(n) = stripped.trim().parse::<u32>() {
if n <= 12 {
form = Some(ClosedForm::Factorial);
}
}
}
if form.is_none() {
return TierProbe {
reasoning_matched: false,
reasoning_action: "classify as arithmetic / factorial",
reasoning_cost: reason_cost,
generation_action: None,
generation_answer: None,
generation_cost: 0,
};
}
let (answer, action, cost) = match form.unwrap() {
ClosedForm::BinaryArithmetic => {
let a = parts[0].parse::<f64>().unwrap();
let b = parts[2].parse::<f64>().unwrap();
let answer = match parts[1] {
"+" => Some(format!("{}", a + b)),
"-" => Some(format!("{}", a - b)),
"*" => Some(format!("{}", a * b)),
"/" if b != 0.0 => Some(format!("{}", a / b)),
_ => None,
};
(answer, "evaluate arithmetic expression", 32)
}
ClosedForm::Factorial => {
let n: u32 = q.strip_suffix('!').unwrap().trim().parse().unwrap();
let f: u64 = (1..=n as u64).product();
(Some(format!("{f}")), "evaluate factorial", (n as u64) * 32)
}
};
TierProbe {
reasoning_matched: true,
reasoning_action: "classify as arithmetic / factorial",
reasoning_cost: reason_cost,
generation_action: Some(action),
generation_answer: answer,
generation_cost: cost,
}
}
// ── L0-retrieved: named constants and theorems ────────────────────────
const RETRIEVED: &[(&str, &str)] = &[
("pi", "π ≈ 3.141592653589793"),
("e", "e ≈ 2.718281828459045"),
("phi", "φ ≈ 1.618033988749895 (golden ratio)"),
("c", "c = 299 792 458 m/s (speed of light, exact)"),
("h", "h ≈ 6.62607015×10⁻³⁴ J·s (Planck, exact since 2019)"),
("kt ln 2 at 300 k", "kT·ln 2 ≈ 2.870×10⁻²¹ J (Landauer floor)"),
("pythagorean theorem", "a² + b² = c² (for a right triangle, c = hypotenuse)"),
("eulers identity", "e^(iπ) + 1 = 0"),
("eulers formula", "e^(iθ) = cos θ + i sin θ"),
("schwarz inequality", "|⟨u, v⟩| ≤ ‖u‖·‖v‖"),
("law of cosines", "c² = a² + b² − 2 a b cos C"),
("planck-einstein", "E = h ν"),
("entropy of binary distribution", "H(p) = −p log₂ p − (1−p) log₂(1−p)"),
];
// L0-retrieved has TWO sub-strategies. The named-fact table is the
// classic one — exact-key lookup for π, e, the Landauer floor, etc.
// The structural graph (added 2026-06-06 alongside the `mgai-graph`
// crate) is the second one — typed-edge queries like "what uses X" or
// "what cites X". Both resolve at L0 with no model; the trace marks the
// hit with the sub-strategy that fired.
fn build_structural_graph() -> mgai_graph::Graph {
let mut g = mgai_graph::Graph::new();
// Concept nodes (one per labelled entity). Kind = "concept" for
// citation-backed claims; "tool" for libraries; "tier" for
// cascade rungs.
let fft = g.add_node("concept", "FFT");
let twiddle = g.add_node("concept", "twiddle factor");
let attention = g.add_node("concept", "attention");
let softmax = g.add_node("concept", "softmax");
let rmsnorm = g.add_node("concept", "RMSNorm");
let rms = g.add_node("concept", "RMS");
let hdc = g.add_node("concept", "HDC");
let bind = g.add_node("concept", "bind");
let bundle = g.add_node("concept", "bundle");
let permute = g.add_node("concept", "permute");
let cosmos3 = g.add_node("concept", "Cosmos 3");
let mot = g.add_node("concept", "MoT");
let cascade = g.add_node("concept", "cascade");
let l0 = g.add_node("tier", "L0");
let l1 = g.add_node("tier", "L1");
let l2 = g.add_node("tier", "L2");
let tm = g.add_node("org", "Thinking Machines Lab");
let dn = g.add_node("paper", "Defeating Nondeterminism");
let biops = g.add_node("tool", "batch-invariant-ops");
let graphify = g.add_node("tool", "Graphify");
let tree_sitter = g.add_node("tool", "Tree-sitter");
let networkx = g.add_node("tool", "NetworkX");
let leiden = g.add_node("tool", "Leiden");
let mgai_graph = g.add_node("crate", "mgai-graph");
let mgai_hdc = g.add_node("crate", "mgai-hdc");
// "uses" relations.
let _ = g.add_edge(fft, twiddle, "uses");
let _ = g.add_edge(attention, softmax, "uses");
let _ = g.add_edge(rmsnorm, rms, "uses");
let _ = g.add_edge(hdc, bind, "uses");
let _ = g.add_edge(hdc, bundle, "uses");
let _ = g.add_edge(hdc, permute, "uses");
let _ = g.add_edge(cosmos3, mot, "uses");
let _ = g.add_edge(graphify, tree_sitter, "uses");
let _ = g.add_edge(graphify, networkx, "uses");
let _ = g.add_edge(graphify, leiden, "uses");
let _ = g.add_edge(mgai_hdc, bind, "uses");
let _ = g.add_edge(mgai_hdc, bundle, "uses");
// "resolves-via" — cascade composition.
let _ = g.add_edge(cascade, l0, "resolves-via");
let _ = g.add_edge(cascade, l1, "resolves-via");
let _ = g.add_edge(cascade, l2, "resolves-via");
// Authorship + citation.
let _ = g.add_edge(tm, dn, "authored");
let _ = g.add_edge(dn, biops, "cites");
// Pairs: mgai-graph complements mgai-hdc inside the cascade.
let _ = g.add_edge(mgai_graph, mgai_hdc, "complements");
let _ = g.add_edge(mgai_hdc, mgai_graph, "complements");
g
}
/// Pattern recognised: "<edge-kind> <subject>" or
/// "what <edge-kind> <subject>" (e.g. "uses softmax", "what cites
/// Defeating Nondeterminism"). Returns Some((edge_kind, direction,
/// subject_label)) on a clean match.
fn parse_structural_query(q: &str) -> Option<(&'static str, GraphDir, String)> {
let q = q.trim().trim_end_matches('?');
// Strip optional leading "what ".
let body = q.strip_prefix("what ").unwrap_or(q).trim();
// Verbs recognised on either side of a query. Sentence position
// determines the direction:
// "<verb> X" → reverse / edges_in (who/what verbs X?)
// "X <verb>" → forward / edges_out (what does X verb?)
// So "uses softmax" asks for callers of softmax, while "hdc uses"
// asks what hdc uses. Same vocabulary, different shape.
const VERBS: &[&str] = &["uses", "cites", "authored", "resolves-via", "complements"];
for v in VERBS {
// Reverse: verb sits at the front.
if let Some(rest) = body.strip_prefix(&format!("{v} ")) {
let subj = rest.trim().to_string();
if !subj.is_empty() {
return Some((*v, GraphDir::In, subj));
}
}
// Forward: verb sits at the end.
if let Some(rest) = body.strip_suffix(&format!(" {v}")) {
let subj = rest.trim().to_string();
if !subj.is_empty() {
return Some((*v, GraphDir::Out, subj));
}
}
}
None
}
#[derive(Copy, Clone)]
enum GraphDir {
In,
Out,
}
fn graph_query_l0_retrieved(query: &str) -> Option<(String, u64)> {
let q = query.trim().to_lowercase();
let graph = build_structural_graph();
// Cost model: graph build (~25 nodes, ~25 edges → ~50 inserts) +
// edge scans. Both microseconds, anchored to `64 * (nodes + edges)`
// bit-ops.
let bit_ops = 64 * ((graph.node_count() + graph.edge_count()) as u64);
// ── Try the two-hop shape first ──
// Pattern: "<verb1> <verb2> X" → reverse(verb1) ∘ reverse(verb2)
// applied to the subject's node. Reads like "what verb1 things that
// verb2 X?" Example: "uses uses softmax" → "what uses things that
// use softmax?" Returns the union of node labels at the terminal.
if let Some((v1, v2, subject)) = parse_two_hop_query(&q) {
let subj_lower = subject.to_lowercase();
let node = graph.nodes().find(|n| n.label.to_lowercase() == subj_lower)?;
let hits = graph.two_hop_dir(
&node.kind,
&node.label,
v1, mgai_graph::Direction::In,
v2, mgai_graph::Direction::In,
);
let mut labels: Vec<String> = hits
.into_iter()
.filter_map(|nid| graph.node(nid).map(|n| n.label.clone()))
.collect();
if !labels.is_empty() {
labels.sort();
let answer = format!(
"{} ←{}← X ←{}← {}: {}",
subject, v2, v1, "(two-hop)",
labels.join(", ")
);
return Some((answer, bit_ops * 2));
}
}
// ── Single-hop fallback ──
let (verb, dir, subject) = parse_structural_query(&q)?;
let subj_lower = subject.to_lowercase();
let node = graph.nodes().find(|n| n.label.to_lowercase() == subj_lower)?;
let mut labels: Vec<String> = match dir {
GraphDir::In => graph
.edges_in(node.id, verb)
.filter_map(|nid| graph.node(nid).map(|n| n.label.clone()))
.collect(),
GraphDir::Out => graph
.edges_out(node.id, verb)
.filter_map(|nid| graph.node(nid).map(|n| n.label.clone()))
.collect(),
};
if labels.is_empty() {
return None;
}
labels.sort();
let arrow = match dir {
GraphDir::In => "←",
GraphDir::Out => "→",
};
let answer = format!(
"{} {} {}: {}",
subject,
arrow,
verb,
labels.join(", ")
);
Some((answer, bit_ops))
}
/// Parse a two-hop reverse-reverse pattern: "<verb1> <verb2> <subject>".
/// Reads as "what <verb1> things that <verb2> <subject>?" Recognised
/// verbs are the same set as the single-hop parser. Returns
/// `(verb1, verb2, subject)` on match.
fn parse_two_hop_query(q: &str) -> Option<(&'static str, &'static str, String)> {
let q = q.trim().trim_end_matches('?');
let body = q.strip_prefix("what ").unwrap_or(q).trim();
const VERBS: &[&str] = &["uses", "cites", "authored", "resolves-via", "complements"];
for &v1 in VERBS {
let prefix1 = format!("{v1} ");
let Some(rest1) = body.strip_prefix(&prefix1) else { continue };
for &v2 in VERBS {
let prefix2 = format!("{v2} ");
let Some(rest2) = rest1.strip_prefix(&prefix2) else { continue };
let subj = rest2.trim().to_string();
if !subj.is_empty() {
return Some((v1, v2, subj));
}
}
}
None
}
fn probe_l0_retrieved(query: &str) -> TierProbe {
let q = query.trim().to_lowercase();
let reason_cost = (RETRIEVED.len() as u64) * 50;
// ── Sub-strategy A: named-fact table (legacy) ──
if let Some((_, value)) = RETRIEVED.iter().find(|(k, _)| q == *k) {
return TierProbe {
reasoning_matched: true,
reasoning_action: "match against named-fact table",
reasoning_cost: reason_cost,
generation_action: Some("emit cited value"),
generation_answer: Some((*value).to_string()),
generation_cost: 32,
};
}
// ── Sub-strategy B: mgai-graph typed-edge query (added 2026-06-06) ──
if let Some((answer, graph_cost)) = graph_query_l0_retrieved(&q) {
return TierProbe {
reasoning_matched: true,
reasoning_action: "parse structural query + resolve via mgai-graph",
reasoning_cost: reason_cost + 80, // pattern parse
generation_action: Some("emit graph-traversal result"),
generation_answer: Some(answer),
generation_cost: graph_cost,
};
}
TierProbe {
reasoning_matched: false,
reasoning_action: "match against named-fact table + structural graph",
reasoning_cost: reason_cost + 80,
generation_action: None,
generation_answer: None,
generation_cost: 0,
}
}
// ── L0-identifiable: HDC-style margin-gated shape match ───────────────
const IDENTIFIABLE: &[(&str, &str)] = &[
("area of a unit circle", "π r² with r = 1 → π"),
("circumference of a unit circle", "2π r with r = 1 → 2π"),
("area of an equilateral triangle, side 1", "(√3 / 4) · s² with s = 1 → ≈ 0.433"),
("volume of a unit sphere", "(4/3) π r³ with r = 1 → ≈ 4.189"),
("rms of a sine wave amplitude a", "a / √2"),
];
fn probe_l0_identifiable(query: &str) -> TierProbe {
let q = query.trim().to_lowercase();
let q_tokens: std::collections::HashSet<&str> =
q.split_whitespace().filter(|t| t.len() > 1).collect();
let mut scores: Vec<(f64, &str, &str)> = Vec::with_capacity(IDENTIFIABLE.len());
for (key, value) in IDENTIFIABLE {
let k_tokens: std::collections::HashSet<&str> =
key.split_whitespace().filter(|t| t.len() > 1).collect();
let inter: usize = q_tokens.intersection(&k_tokens).count();
let union: usize = q_tokens.union(&k_tokens).count();
let sim = if union == 0 { 0.0 } else { inter as f64 / union as f64 };
scores.push((sim, key, value));
}
scores.sort_by(|a, b| b.0.partial_cmp(&a.0).unwrap_or(std::cmp::Ordering::Equal));
let reason_cost = (IDENTIFIABLE.len() as u64) * 200;
let top = scores.first().copied();
let second_sim = scores.get(1).map(|t| t.0).unwrap_or(0.0);
if let Some((sim, _key, value)) = top {
if sim >= 0.5 && (sim - second_sim) >= 0.15 {
return TierProbe {
reasoning_matched: true,
reasoning_action: "shape-match against atom pool (margin-gated)",
reasoning_cost: reason_cost,
generation_action: Some("emit matched-atom value"),
generation_answer: Some(value.to_string()),
generation_cost: 32,
};
}
}
TierProbe {
reasoning_matched: false,
reasoning_action: "shape-match against atom pool (margin-gated)",
reasoning_cost: reason_cost,
generation_action: None,
generation_answer: None,
generation_cost: 0,
}
}
// ── L1: cited composition ─────────────────────────────────────────────
fn probe_l1(query: &str) -> TierProbe {
let q = query.trim().to_lowercase();
let reason_cost = 200u64;
if let Some(rest) = q.strip_prefix("compose ") {
let parts: Vec<&str> = rest.split(" times ").collect();
if parts.len() == 2 {
let l_probe = probe_l0_retrieved(parts[0]);
let r_probe = probe_l0_retrieved(parts[1]);
if let (Some(lv), Some(rv)) = (l_probe.generation_answer, r_probe.generation_answer) {
let answer = format!("compose({}, {}) — both cited from L0-retrieved", lv, rv);
return TierProbe {
reasoning_matched: true,
reasoning_action: "recognise `compose X times Y` form",
reasoning_cost: reason_cost,
generation_action: Some("retrieve both cites and compose"),
generation_answer: Some(answer),
generation_cost: 400,
};
}
}
}
TierProbe {
reasoning_matched: false,
reasoning_action: "recognise `compose X times Y` form",
reasoning_cost: reason_cost,
generation_action: None,
generation_answer: None,
generation_cost: 0,
}
}
// ── L2: model-generated (we don't ship one) ───────────────────────────
fn probe_l2(_query: &str) -> TierProbe {
// Reasoning expert: anything that reached this tier is by definition a
// would-need-a-model query — reasoning always matches. The generation
// expert refuses and reports the would-cost (~10⁹ bit-ops for a small
// local model's single short generation).
TierProbe {
reasoning_matched: true,
reasoning_action: "classify as model-class (escapes lower tiers)",
reasoning_cost: 64,
generation_action: Some("refuse: substrate does not ship a model"),
generation_answer: None,
generation_cost: 1_000_000_000,
}
}
// ── Walker ────────────────────────────────────────────────────────────
pub struct TimeFn {
pub now_ns: fn() -> f64,
}
fn record_probe(
tier: CascadeTier,
probe: TierProbe,
hops: &mut Vec<CascadeHop>,
total_bit_ops: &mut u64,
time: &TimeFn,
) -> (bool, Option<String>) {
// Reasoning hop — always recorded.
let t_r = (time.now_ns)();
let dt_r = ((time.now_ns)() - t_r).max(0.0);
let wall_ns_per_op = if probe.reasoning_cost > 0 {
dt_r / probe.reasoning_cost as f64
} else {
dt_r
};
*total_bit_ops = total_bit_ops.saturating_add(probe.reasoning_cost);
hops.push(CascadeHop {
tier,
expert: SubExpert::Reasoning,
action: probe.reasoning_action.into(),
matched: probe.reasoning_matched,
bit_ops: probe.reasoning_cost,
wall_ns_per_op,
answer: None,
});
if !probe.reasoning_matched {
return (false, None);
}
// Generation hop — only when reasoning matched.
let t_g = (time.now_ns)();
let dt_g = ((time.now_ns)() - t_g).max(0.0);
let gen_wall = if probe.generation_cost > 0 {
dt_g / probe.generation_cost as f64
} else {
dt_g
};
*total_bit_ops = total_bit_ops.saturating_add(probe.generation_cost);
let answer = probe.generation_answer.clone();
hops.push(CascadeHop {
tier,
expert: SubExpert::Generation,
action: probe
.generation_action
.map(|s| s.to_string())
.unwrap_or_default(),
matched: answer.is_some(),
bit_ops: probe.generation_cost,
wall_ns_per_op: gen_wall,
answer: answer.clone(),
});
(answer.is_some(), answer)
}
/// Walk the cascade for `query`. Each tier first runs its reasoning expert,
/// then (if reasoning matched) its generation expert. A tier "resolves" the
/// query only when generation also produces an answer; otherwise the cascade
/// continues with the next tier. L2's generation always refuses → no
/// resolution.
pub fn walk(query: &str, time: &TimeFn) -> CascadeTrace {
let mut hops = Vec::new();
let mut total_bit_ops: u64 = 0;
let mut resolved_at: Option<CascadeTier> = None;
let mut final_answer: Option<String> = None;
let probes: [(CascadeTier, fn(&str) -> TierProbe); 5] = [
(CascadeTier::L0Closed, probe_l0_closed),
(CascadeTier::L0Retrieved, probe_l0_retrieved),
(CascadeTier::L0Identifiable, probe_l0_identifiable),
(CascadeTier::L1, probe_l1),
(CascadeTier::L2, probe_l2),
];
for (tier, probe_fn) in probes {
let probe = probe_fn(query);
let (gen_ok, ans) = record_probe(tier, probe, &mut hops, &mut total_bit_ops, time);
if gen_ok {
resolved_at = Some(tier);
final_answer = ans;
break;
}
}
CascadeTrace {
query: query.into(),
hops,
resolved_at,
final_answer,
total_bit_ops,
}
}
#[cfg(test)]
mod tests {
use super::*;
fn now() -> f64 {
use std::sync::atomic::{AtomicU64, Ordering};
static CLOCK: AtomicU64 = AtomicU64::new(0);
CLOCK.fetch_add(100, Ordering::Relaxed) as f64
}
fn time() -> TimeFn {
TimeFn { now_ns: now }
}
#[test]
fn l0_retrieved_graph_query_resolves_at_l0() {
// The structural sub-strategy: "uses softmax" — who uses softmax?
// Built-in graph: attention uses softmax.
let t = walk("uses softmax", &time());
assert_eq!(t.resolved_at, Some(CascadeTier::L0Retrieved));
let ans = t.final_answer.as_deref().unwrap_or("");
assert!(
ans.contains("attention"),
"expected 'attention' in answer, got: {ans}"
);
}
#[test]
fn l0_retrieved_graph_query_handles_forward_direction() {
// Forward query: "HDC uses" — what does HDC use?
let t = walk("hdc uses", &time());
assert_eq!(t.resolved_at, Some(CascadeTier::L0Retrieved));
let ans = t.final_answer.as_deref().unwrap_or("");
// HDC uses bind, bundle, permute — all three should appear.
assert!(ans.contains("bind"));
assert!(ans.contains("bundle"));
assert!(ans.contains("permute"));
}
#[test]
fn l0_retrieved_two_hop_resolves_at_l0() {
// "uses uses bind" → what uses things that use bind?
// Built-in graph: HDC uses bind; mgai-hdc uses bind. Nothing
// uses HDC or mgai-hdc, so the result is empty → single-hop
// fallback also misses → query doesn't resolve at L0-retrieved.
// The clean test is one where the two-hop SHOULD hit:
// "complements complements mgai-graph" — what complements
// things that complement mgai-graph? mgai-hdc complements
// mgai-graph; mgai-graph complements mgai-hdc → the answer is
// mgai-graph itself.
let t = walk("complements complements mgai-graph", &time());
assert_eq!(t.resolved_at, Some(CascadeTier::L0Retrieved));
let ans = t.final_answer.as_deref().unwrap_or("");
assert!(
ans.contains("mgai-graph"),
"expected 'mgai-graph' in two-hop answer, got: {ans}"
);
}
#[test]
fn l0_retrieved_named_fact_table_still_works() {
// Backward-compat: the original named-fact lookup ("pi") still
// resolves at L0-retrieved after the graph sub-strategy was added.
let t = walk("pi", &time());
assert_eq!(t.resolved_at, Some(CascadeTier::L0Retrieved));
assert!(t.final_answer.as_deref().unwrap_or("").contains("π"));
}
#[test]
fn unparseable_query_falls_through_l0_retrieved() {
// "what is the meaning of life" matches neither named-fact nor
// any structural pattern; L0-retrieved doesn't resolve.
let t = walk("what is the meaning of life", &time());
assert_ne!(t.resolved_at, Some(CascadeTier::L0Retrieved));
}
#[test]
fn l0_closed_match_emits_reasoning_then_generation() {
let t = walk("2 + 2", &time());
assert_eq!(t.resolved_at, Some(CascadeTier::L0Closed));
assert_eq!(t.final_answer.as_deref(), Some("4"));
assert_eq!(t.hops.len(), 2);
assert_eq!(t.hops[0].tier, CascadeTier::L0Closed);
assert_eq!(t.hops[0].expert, SubExpert::Reasoning);
assert!(t.hops[0].matched);
assert_eq!(t.hops[1].tier, CascadeTier::L0Closed);
assert_eq!(t.hops[1].expert, SubExpert::Generation);
assert!(t.hops[1].matched);
assert_eq!(t.hops[1].answer.as_deref(), Some("4"));
}
#[test]
fn unmatched_tier_emits_reasoning_only() {
// "pi" doesn't match L0-closed; reasoning at L0-closed records a
// single hop with matched=false.
let t = walk("pi", &time());
let l0_closed_hops: Vec<&CascadeHop> = t.hops.iter().filter(|h| h.tier == CascadeTier::L0Closed).collect();
assert_eq!(l0_closed_hops.len(), 1);
assert_eq!(l0_closed_hops[0].expert, SubExpert::Reasoning);
assert!(!l0_closed_hops[0].matched);
// Resolution on L0-retrieved → reasoning + generation = 2 hops there.
let l0_retrieved_hops: Vec<&CascadeHop> = t
.hops
.iter()
.filter(|h| h.tier == CascadeTier::L0Retrieved)
.collect();
assert_eq!(l0_retrieved_hops.len(), 2);
assert_eq!(t.resolved_at, Some(CascadeTier::L0Retrieved));
}
#[test]
fn factorial_resolves_at_l0_closed() {
let t = walk("6!", &time());
assert_eq!(t.resolved_at, Some(CascadeTier::L0Closed));
assert_eq!(t.final_answer.as_deref(), Some("720"));
assert_eq!(t.hops.len(), 2);
}
#[test]
fn l0_identifiable_resolves_unit_circle() {
let t = walk("circumference of a unit circle", &time());
assert_eq!(t.resolved_at, Some(CascadeTier::L0Identifiable));
assert!(t.final_answer.unwrap().contains("2π"));
}
#[test]
fn l2_reasoning_matches_but_generation_refuses() {
let t = walk("what is the meaning of life?", &time());
assert_eq!(t.resolved_at, None);
// L2 reasoning hop matches (recognises the query as model-class),
// L2 generation hop is recorded as not-matched (refused).
let l2_hops: Vec<&CascadeHop> = t.hops.iter().filter(|h| h.tier == CascadeTier::L2).collect();
assert_eq!(l2_hops.len(), 2);
assert_eq!(l2_hops[0].expert, SubExpert::Reasoning);
assert!(l2_hops[0].matched);
assert_eq!(l2_hops[1].expert, SubExpert::Generation);
assert!(!l2_hops[1].matched);
assert_eq!(l2_hops[1].bit_ops, 1_000_000_000);
}
#[test]
fn replay_is_deterministic_across_tier_split() {
let a = walk("pythagorean theorem", &time());
let b = walk("pythagorean theorem", &time());
assert_eq!(a.resolved_at, b.resolved_at);
assert_eq!(a.final_answer, b.final_answer);
assert_eq!(a.total_bit_ops, b.total_bit_ops);
assert_eq!(a.hops.len(), b.hops.len());
for (ha, hb) in a.hops.iter().zip(b.hops.iter()) {
assert_eq!(ha.tier, hb.tier);
assert_eq!(ha.expert, hb.expert);
assert_eq!(ha.matched, hb.matched);
assert_eq!(ha.bit_ops, hb.bit_ops);
assert_eq!(ha.answer, hb.answer);
}
}
#[test]
fn compose_resolves_at_l1_with_two_l0_retrieved_cites() {
let t = walk("compose pi times e", &time());
assert_eq!(t.resolved_at, Some(CascadeTier::L1));
let l1_hops: Vec<&CascadeHop> = t.hops.iter().filter(|h| h.tier == CascadeTier::L1).collect();
assert_eq!(l1_hops.len(), 2);
assert!(l1_hops[1].answer.as_ref().unwrap().contains("compose("));
}
}
This is the exact Rust file compiled into the WASM module the page just loaded. Every line that runs on your device is here. The receipt is a function of this code, not a bespoke benchmark.
About this exhibit
The cascade is the substrate's primary primitive. A small ladder of tiers — closed-form, retrieved, identifiable, cited, model-class — is walked for every query. Every tier is split into a reasoning sub-expert (classify the form) and a generation sub-expert (produce the answer in that form). Generation only fires when reasoning matches.
The visible trace IS the chain of thought. Each hop is a deterministic function; the whole trace is replayable from the query alone; no model weights are involved. Every hop carries its own picojoule receipt.
At /exhibits you can see the eight kernels (FFT, Lorenz, heat, etc.) that L0-closed evaluators would dispatch to inside a richer cascade. This exhibit shows the routing logic above them.