Shared memory and context tools for agentic work.
Code Rooms
use crate::{IngestAdapter, IngestStats};
use m1nd_core::error::M1ndResult;
use m1nd_core::graph::{Graph, NodeProvenanceInput};
use m1nd_core::types::{EdgeDirection, FiniteF32, NodeType};
use regex::Regex;
use std::collections::{HashMap, HashSet};
use std::path::{Path, PathBuf};
use std::time::{Instant, SystemTime, UNIX_EPOCH};
use walkdir::WalkDir;
#[derive(Clone, Debug)]
struct L1ghtNodeRecord {
id: String,
label: String,
node_type: NodeType,
tags: Vec<String>,
last_modified: f64,
change_frequency: f32,
source_path: String,
line_start: Option<u32>,
line_end: Option<u32>,
excerpt: Option<String>,
namespace: String,
canonical: bool,
}
struct L1ghtEdgeRecord {
source: String,
target: String,
relation: String,
weight: f32,
direction: EdgeDirection,
inhibitory: bool,
causal_strength: f32,
#[derive(Default)]
struct HeaderMeta {
protocol: Option<String>,
node: Option<String>,
state: Option<String>,
color: Option<String>,
glyph: Option<String>,
completeness: Option<String>,
proof: Option<String>,
/// Provenance stamped by the `memorize` writer (Move 1): when this memory was
/// written (Unix millis) and which agent authored it. Absent on legacy files —
/// honestly "unknown", never faked.
created: Option<String>,
source_agent: Option<String>,
/// The brain a claim was born in (`Origin-Brain:` frontmatter, MEDULLA-PRD §6):
/// a project root, or the literal `medulla` for doctrine-born claims. Absent on
/// legacy files — honestly "unknown", never faked (MED-INV-4).
origin_brain: Option<String>,
depends_on: Vec<String>,
next: Vec<String>,
pub struct L1ghtIngestAdapter {
impl L1ghtIngestAdapter {
pub fn new(namespace: Option<String>) -> Self {
let namespace = namespace
.unwrap_or_else(|| "light".to_string())
.trim()
.to_lowercase();
let namespace = if namespace.is_empty() {
"light".to_string()
} else {
namespace
};
Self { namespace }
pub fn looks_like_l1ght(text: &str) -> bool {
if text.contains("Protocol: L1GHT/") {
return true;
let mut hits = 0;
for marker in [
"[⍂ entity:",
"[⍐ state:",
"[⍌ event:",
"[𝔻 confidence:",
"[𝔻 ambiguity:",
"[𝔻 evidence:",
"[⟁ depends_on:",
"[⟁ binds_to:",
"[⟁ tests:",
"[RED blocker:",
"[AMBER warning:",
] {
if text.contains(marker) {
hits += 1;
hits >= 2
fn accepted_extension(path: &Path) -> bool {
matches!(
path.extension().and_then(|ext| ext.to_str()).map(|ext| ext.to_ascii_lowercase()),
Some(ext) if matches!(ext.as_str(), "md" | "markdown")
)
fn collect_files(&self, root: &Path) -> Vec<PathBuf> {
if root.is_file() {
return if Self::accepted_extension(root) {
vec![root.to_path_buf()]
vec![]
// Prune hidden (dot-prefixed) directories and files below the root, mirroring
// the code walker's `.hidden(true)` pruning (walker.rs). This is what keeps
// supersession's retained `agent-memory/.history/` (outdated prior beliefs)
// and `.locks/` out of the reloaded graph — the leading dot is the mechanism.
// The root itself is never pruned (depth 0), so an explicitly-passed dotdir
// still ingests.
WalkDir::new(root)
.into_iter()
.filter_entry(|entry| {
entry.depth() == 0
|| !entry
.file_name()
.to_str()
.map(|name| name.starts_with('.'))
.unwrap_or(false)
})
.filter_map(Result::ok)
.filter(|entry| entry.file_type().is_file() && Self::accepted_extension(entry.path()))
.map(|entry| entry.into_path())
.collect()
fn slugify(raw: &str) -> String {
let mut out = String::with_capacity(raw.len());
let mut prev_dash = false;
for ch in raw.chars() {
if ch.is_ascii_alphanumeric() {
out.push(ch.to_ascii_lowercase());
prev_dash = false;
} else if !prev_dash {
out.push('-');
prev_dash = true;
let trimmed = out.trim_matches('-');
if trimmed.is_empty() {
"entry".to_string()
trimmed.to_string()
fn file_timestamp(path: &Path) -> f64 {
std::fs::metadata(path)
.ok()
.and_then(|meta| meta.modified().ok())
.and_then(|time| time.duration_since(UNIX_EPOCH).ok())
.map(|duration| duration.as_secs_f64())
.unwrap_or_else(|| {
SystemTime::now()
.duration_since(UNIX_EPOCH)
.unwrap_or(0.0)
/// Parse a confidence value from an epistemic marker. Accepts a numeric
/// form (`0.6`, `0.85`) or a word-based form (`low`/`medium`/`high`/`certain`,
/// plus a few synonyms). Unrecognized text falls back to 0.5 (neutral).
fn parse_confidence(text: &str) -> f32 {
let t = text.trim().trim_end_matches(['.', ',', ';']);
if let Ok(v) = t.parse::<f32>() {
return v;
match t.to_ascii_lowercase().as_str() {
"certain" | "confirmed" | "verified" => 0.95,
"high" | "strong" | "likely" => 0.8,
"medium" | "moderate" | "partial" => 0.5,
"low" | "weak" | "tentative" => 0.3,
"speculative" | "guess" | "unverified" => 0.15,
_ => 0.5,
fn excerpt(text: &str) -> Option<String> {
let trimmed = text.trim();
None
Some(trimmed.chars().take(220).collect())
fn push_node(
nodes: &mut Vec<L1ghtNodeRecord>,
seen: &mut HashSet<String>,
mut record: L1ghtNodeRecord,
prov_tags: &[String],
) {
// Stamp the file's provenance (Created/Source-Agent, parsed from the
// frontmatter) onto every node from that file, so any recall hit — file,
// section, or claim node — carries the authored-age + source labels.
// Absent on legacy files: `prov_tags` is empty, so nothing is added.
record.tags.extend(prov_tags.iter().cloned());
if seen.insert(record.id.clone()) {
nodes.push(record);
fn push_edge(
edges: &mut Vec<L1ghtEdgeRecord>,
seen: &mut HashSet<(String, String, String, u8)>,
record: L1ghtEdgeRecord,
let key = match record.direction {
EdgeDirection::Bidirectional => {
if record.source <= record.target {
(
record.source.clone(),
record.target.clone(),
record.relation.clone(),
1,
EdgeDirection::Forward => (
0,
),
if seen.insert(key) {
edges.push(record);
fn parse_header(lines: &[&str]) -> HeaderMeta {
let mut meta = HeaderMeta::default();
let mut current_list: Option<&str> = None;
for line in lines {
let trimmed = line.trim();
if trimmed == "---" {
continue;
if let Some(value) = trimmed.strip_prefix("Protocol:") {
meta.protocol = Some(value.trim().to_string());
current_list = None;
} else if let Some(value) = trimmed.strip_prefix("Node:") {
meta.node = Some(value.trim().to_string());
} else if let Some(value) = trimmed.strip_prefix("State:") {
meta.state = Some(value.trim().to_string());
} else if let Some(value) = trimmed.strip_prefix("Color:") {
meta.color = Some(value.trim().to_string());
} else if let Some(value) = trimmed.strip_prefix("Glyph:") {
meta.glyph = Some(value.trim().to_string());
} else if let Some(value) = trimmed.strip_prefix("Completeness:") {
meta.completeness = Some(value.trim().to_string());
} else if let Some(value) = trimmed.strip_prefix("Proof:") {
meta.proof = Some(value.trim().to_string());
} else if let Some(value) = trimmed.strip_prefix("Created:") {
meta.created = Some(value.trim().to_string());
} else if let Some(value) = trimmed.strip_prefix("Source-Agent:") {
meta.source_agent = Some(value.trim().to_string());
} else if let Some(value) = trimmed.strip_prefix("Origin-Brain:") {
meta.origin_brain = Some(value.trim().to_string());
} else if trimmed == "Depends on:" {
current_list = Some("depends_on");
} else if trimmed == "Next:" {
current_list = Some("next");
} else if let Some(value) = trimmed.strip_prefix("- ") {
match current_list {
Some("depends_on") => meta.depends_on.push(value.trim().to_string()),
Some("next") => meta.next.push(value.trim().to_string()),
_ => {}
meta
fn parse_file(
&self,
root: &Path,
path: &Path,
node_seen: &mut HashSet<String>,
edge_seen: &mut HashSet<(String, String, String, u8)>,
) -> M1ndResult<()> {
let text = std::fs::read_to_string(path)?;
if !Self::looks_like_l1ght(&text) {
return Ok(());
let rel_path = path
.strip_prefix(root)
.unwrap_or(path)
.to_string_lossy()
.replace('\\', "/");
let file_slug = Self::slugify(&rel_path);
let file_id = format!("light::{}::file::{}", self.namespace, file_slug);
let timestamp = Self::file_timestamp(path);
let file_label = path
.and_then(|name| name.to_str())
.unwrap_or(&rel_path)
.to_string();
let lines: Vec<&str> = text.lines().collect();
let header_meta = Self::parse_header(&lines[..lines.len().min(40)]);
// Provenance tags (Created/Source-Agent) parsed from the frontmatter, to
// be stamped on every node from this file so recall can label the hit.
// Mirrors how `light:confidence:<v>` is already encoded as a tag.
let mut prov_tags: Vec<String> = Vec::new();
if let Some(created) = &header_meta.created {
prov_tags.push(format!("light:created:{}", created.trim()));
if let Some(source_agent) = &header_meta.source_agent {
prov_tags.push(format!("light:source_agent:{}", source_agent.trim()));
// Origin-Brain (MEDULLA-PRD §6): WHERE the claim was born, stamped so recall
// can label which brain a hit came from. Absent → no tag (honest "unknown").
if let Some(origin_brain) = &header_meta.origin_brain {
prov_tags.push(format!("light:origin_brain:{}", origin_brain.trim()));
Self::push_node(
nodes,
node_seen,
L1ghtNodeRecord {
id: file_id.clone(),
label: file_label.clone(),
node_type: NodeType::File,
tags: vec!["light".into(), format!("namespace:{}", self.namespace)],
last_modified: timestamp,
change_frequency: 0.7,
source_path: rel_path.clone(),
line_start: None,
line_end: None,
excerpt: Some(file_label.clone()),
namespace: self.namespace.clone(),
canonical: true,
},
&prov_tags,
);
let section_re = Regex::new(r"^##\s+(.+?)\s*$").unwrap();
let tag_re = Regex::new(r"\[(?P<tag>[^\]]+)\]").unwrap();
let mut current_parent = file_id.clone();
let mut last_claim_id: Option<String> = None;
let mut section_counts: HashMap<String, usize> = HashMap::new();
// Index (into `nodes`) of the most recent section node — the anchor that
// prose body lines fold into (see the prose capture in the line loop).
let mut current_section_node: Option<usize> = None;
for (key, value) in [
("protocol", header_meta.protocol.clone()),
("node", header_meta.node.clone()),
("state", header_meta.state.clone()),
("color", header_meta.color.clone()),
("glyph", header_meta.glyph.clone()),
("completeness", header_meta.completeness.clone()),
("proof", header_meta.proof.clone()),
if let Some(value) = value {
let meta_id = format!("light::{}::meta::{}::{}", self.namespace, file_slug, key);
id: meta_id.clone(),
label: value.clone(),
node_type: NodeType::Concept,
tags: vec!["light".into(), format!("light:{}", key)],
change_frequency: 0.55,
excerpt: Self::excerpt(&value),
let relation = match key {
"protocol" => "defines_protocol",
"state" => "has_state",
"glyph" => "has_glyph",
"color" => "has_color",
_ => "has_metadata",
Self::push_edge(
edges,
edge_seen,
L1ghtEdgeRecord {
source: file_id.clone(),
target: meta_id,
relation: relation.into(),
weight: 1.0,
direction: EdgeDirection::Forward,
inhibitory: false,
causal_strength: 0.85,
for dep in header_meta.depends_on {
let dep_id = format!(
"light::{}::dep::{}::{}",
self.namespace,
file_slug,
Self::slugify(&dep)
id: dep_id.clone(),
label: dep.clone(),
node_type: NodeType::Reference,
tags: vec!["light".into(), "light:dependency".into()],
change_frequency: 0.45,
excerpt: Self::excerpt(&dep),
target: dep_id,
relation: "depends_on".into(),
causal_strength: 0.9,
for next in header_meta.next {
let next_id = format!(
"light::{}::next::{}::{}",
Self::slugify(&next)
id: next_id.clone(),
label: next.clone(),
tags: vec!["light".into(), "light:next".into()],
change_frequency: 0.5,
excerpt: Self::excerpt(&next),
target: next_id,
relation: "next_binding".into(),
weight: 0.95,
causal_strength: 0.82,
for (idx, line) in lines.iter().enumerate() {
let line_no = idx as u32 + 1;
if let Some(caps) = section_re.captures(trimmed) {
let heading = caps.get(1).unwrap().as_str().trim();
let slug = Self::slugify(heading);
let count = section_counts.entry(slug.clone()).or_insert(0);
*count += 1;
let section_id = format!(
"light::{}::section::{}::{}-{}",
self.namespace, file_slug, slug, count
let before = nodes.len();
id: section_id.clone(),
label: heading.to_string(),
node_type: NodeType::Module,
tags: vec!["light".into(), "light:section".into()],
line_start: Some(line_no),
line_end: Some(line_no),
excerpt: Self::excerpt(heading),
current_section_node = if nodes.len() > before {
Some(nodes.len() - 1)
target: section_id.clone(),
relation: "contains_section".into(),
causal_strength: 0.8,
current_parent = section_id;
} else if !trimmed.starts_with('#') && trimmed != "---" && !tag_re.is_match(trimmed) {
// Prose body lines — the claim text `memorize` renders between a
// section heading and its markers. Previously dropped entirely,
// which left a memorized claim's MEANING outside every searchable
// surface (label-only recall — retrieval battery C1/C4). Fold the
// prose into the owning section node's excerpt so the body reaches
// the embedding text (`SemanticEngine::build_embeddings` embeds
// label + excerpt). Frontmatter lines are inert here: they precede
// any `##` section, so `current_section_node` is still None.
if let Some(i) = current_section_node {
let node = &mut nodes[i];
let merged = match node.excerpt.take() {
// The freshly-pushed section excerpt is just the heading
// (== label): replace it — the label already carries it.
Some(prev) if prev != node.label => format!("{prev} {trimmed}"),
_ => trimmed.to_string(),
node.excerpt = Self::excerpt(&merged);
for caps in tag_re.captures_iter(trimmed) {
let raw = caps.name("tag").unwrap().as_str().trim();
// Determine if this is an epistemic (𝔻) marker.
let is_epistemic = raw.starts_with('𝔻');
// Compute relation, edge weight, and causal strength.
let (relation, edge_weight, edge_causal): (&str, f32, f32) =
if raw.starts_with('⍂') && raw.contains("entity:") {
("declares_entity", 0.9, 0.7)
} else if raw.starts_with('⍐') && raw.contains("state:") {
("declares_state", 0.9, 0.7)
} else if raw.starts_with('⍌') && raw.contains("event:") {
("declares_event", 0.9, 0.7)
} else if raw.starts_with('⟁') && raw.contains("depends_on:") {
("depends_on", 0.9, 0.7)
} else if raw.starts_with('⟁') && raw.contains("binds_to:") {
("binds_to", 0.9, 0.7)
} else if raw.starts_with('⟁') && raw.contains("tests:") {
("declares_test", 0.9, 0.7)
} else if raw.starts_with("RED blocker:") {
("declares_blocker", 0.9, 0.7)
} else if raw.starts_with("AMBER warning:") {
("declares_warning", 0.9, 0.7)
} else if is_epistemic {
if raw.contains("confidence:") {
// Parse the confidence value after "confidence:".
// Accept both numeric (0.6) and word-based
// (low/medium/high/certain) forms — the real corpus uses words.
let conf_val = raw
.find("confidence:")
.map(|pos| raw[pos + "confidence:".len()..].trim())
.map(Self::parse_confidence)
.unwrap_or(0.5)
.clamp(0.0, 1.0);
("epistemic_confidence", conf_val, conf_val)
} else if raw.contains("ambiguity:") {
("epistemic_ambiguity", 0.5, 0.3)
} else if raw.contains("evidence:") {
("evidenced_by", 0.8, 0.8)
("declares_metadata", 0.9, 0.7)
let node_type = if relation == "declares_test" {
NodeType::Process
NodeType::Concept
// Build extra tags for epistemic confidence to encode value.
let mut node_tags = vec!["light".into(), format!("light:{}", relation)];
if relation == "epistemic_confidence" {
node_tags.push(format!("light:confidence:{:.2}", edge_weight));
let tag_id = format!(
"light::{}::tag::{}::{}::{}",
line_no,
Self::slugify(raw)
id: tag_id.clone(),
label: raw.to_string(),
node_type,
tags: node_tags,
excerpt: Self::excerpt(raw),
// Epistemic markers attach to the preceding claim; others attach to
// the current section/file parent.
let edge_source = if is_epistemic {
last_claim_id
.clone()
.unwrap_or_else(|| current_parent.clone())
current_parent.clone()
source: edge_source,
target: tag_id.clone(),
weight: edge_weight,
causal_strength: edge_causal,
// Update last_claim_id for non-epistemic markers only.
if !is_epistemic {
last_claim_id = Some(tag_id);
Ok(())
impl IngestAdapter for L1ghtIngestAdapter {
fn domain(&self) -> &str {
"light"
fn ingest(&self, root: &Path) -> M1ndResult<(Graph, IngestStats)> {
let start = Instant::now();
let files = self.collect_files(root);
let mut stats = IngestStats {
files_scanned: files.len() as u64,
..Default::default()
let mut nodes = Vec::new();
let mut edges = Vec::new();
let mut node_seen = HashSet::new();
let mut edge_seen = HashSet::new();
for path in files {
let text = std::fs::read_to_string(&path)?;
self.parse_file(
root,
&path,
&mut nodes,
&mut edges,
&mut node_seen,
&mut edge_seen,
)?;
stats.files_parsed += 1;
let mut graph = Graph::with_capacity(nodes.len(), edges.len());
for node in &nodes {
let tags: Vec<&str> = node.tags.iter().map(String::as_str).collect();
if let Ok(node_id) = graph.add_node(
&node.id,
&node.label,
node.node_type,
&tags,
node.last_modified,
node.change_frequency,
graph.set_node_provenance(
node_id,
NodeProvenanceInput {
source_path: Some(&node.source_path),
line_start: node.line_start,
line_end: node.line_end,
excerpt: node.excerpt.as_deref(),
namespace: Some(&node.namespace),
canonical: node.canonical,
stats.nodes_created += 1;
for edge in &edges {
if let (Some(source), Some(target)) = (
graph.resolve_id(&edge.source),
graph.resolve_id(&edge.target),
if graph
.add_edge(
source,
target,
&edge.relation,
FiniteF32::new(edge.weight),
edge.direction,
edge.inhibitory,
FiniteF32::new(edge.causal_strength),
.is_ok()
{
stats.edges_created += 1;
if graph.num_nodes() > 0 {
graph.finalize()?;
stats.elapsed_ms = start.elapsed().as_secs_f64() * 1000.0;
Ok((graph, stats))
#[cfg(test)]
mod confidence_tests {
use super::L1ghtIngestAdapter as A;
#[test]
fn parses_numeric_confidence() {
assert!((A::parse_confidence("0.6") - 0.6).abs() < 1e-6);
assert!((A::parse_confidence(" 0.85 ") - 0.85).abs() < 1e-6);
fn parses_word_confidence() {
assert!((A::parse_confidence("high") - 0.8).abs() < 1e-6);
assert!((A::parse_confidence("MEDIUM") - 0.5).abs() < 1e-6);
assert!((A::parse_confidence("low.") - 0.3).abs() < 1e-6);
assert!((A::parse_confidence("certain") - 0.95).abs() < 1e-6);
fn unknown_confidence_is_neutral() {
assert!((A::parse_confidence("banana") - 0.5).abs() < 1e-6);
fn parses_created_and_source_agent_frontmatter() {
let lines = [
"---",
"Protocol: L1GHT/1.0",
"Node: AuthSystem",
"State: verified",
"Created: 1700000000000",
"Source-Agent: agent-B",
"Origin-Brain: /path/to/repo",
];
let meta = A::parse_header(&lines);
assert_eq!(meta.created.as_deref(), Some("1700000000000"));
assert_eq!(meta.source_agent.as_deref(), Some("agent-B"));
assert_eq!(meta.origin_brain.as_deref(), Some("/path/to/repo"));
fn prose_body_folds_into_section_excerpt() {
// A memorize-shaped .light.md: the claim BODY is the prose line between
// the section heading and its markers. The retrieval battery (C1/C4)
// measured that this body previously reached NO node and NO excerpt —
// recall by meaning had nothing to match. The fix folds prose into the
// owning section node's excerpt (the one recall surface that both ranks
// in seek and survives north's marker-fragment filter).
use crate::IngestAdapter;
let dir = std::env::temp_dir().join(format!(
"l1ght-prose-excerpt-{}-{}",
std::process::id(),
std::time::SystemTime::now()
.duration_since(std::time::UNIX_EPOCH)
.unwrap()
.as_nanos()
));
std::fs::create_dir_all(&dir).unwrap();
std::fs::write(
dir.join("sky-cadence-rule.light.md"),
"---\nProtocol: L1GHT/1.0\nNode: SkyCadenceRule\nState: authored\n\
Created: 1700000000000\nSource-Agent: agent-T\n---\n\n\
# SkyCadenceRule\n\n## SkyCadenceRule\n\n\
the release train waits for a green verification matrix before publish\n\n\
[⍂ entity: SkyCadenceRule]\n[𝔻 confidence: high]\n",
.unwrap();
let adapter = super::L1ghtIngestAdapter::new(Some("light".to_string()));
let (graph, _stats) = adapter.ingest(&dir).expect("ingest light dir");
// Find the section node and read its label + excerpt.
let mut section: Option<(String, String, String)> = None;
for (interned, &nid) in &graph.id_to_node {
let ext = graph.strings.resolve(*interned).to_string();
if ext.contains("::section::") {
let idx = nid.as_usize();
let label = graph.strings.resolve(graph.nodes.label[idx]).to_string();
let excerpt = graph.nodes.provenance[idx]
.excerpt
.map(|e| graph.strings.resolve(e).to_string())
.unwrap_or_default();
section = Some((ext, label, excerpt));
break;
std::fs::remove_dir_all(&dir).ok();
let (ext, label, excerpt) = section.expect("a section node must exist");
assert_eq!(label, "SkyCadenceRule", "section label unchanged ({ext})");
assert!(
excerpt.contains("verification matrix"),
"the claim BODY must reach the section excerpt (searchable/embeddable); got {excerpt:?}"
// Frontmatter must never pollute the excerpt.
!excerpt.contains("Protocol") && !excerpt.contains("Source-Agent"),
"frontmatter leaked into the excerpt: {excerpt:?}"
fn absent_provenance_frontmatter_is_none() {
// Legacy frontmatter: no Created / Source-Agent → honestly None, never faked.
"Node: LegacyNode",
"State: authored",
meta.created.is_none(),
"Created must be None on legacy files"
meta.source_agent.is_none(),
"Source-Agent must be None on legacy files"
meta.origin_brain.is_none(),
"Origin-Brain must be None on legacy files"