use std::fmt::Write as _;
use crate::dreaming::lexicon::load_data_document;
pub const DREAMING_AUDIT_PATH: &str = "dreaming-gap-analysis.lino";
pub const DREAMING_AUDIT_TASK: &str =
"Audit issue 540 dreaming through Formal AI: inspect the grounded dreaming meta-algorithm, \
identify every implementation gap from amendment application through replay, pattern \
learning, storage consent, and idle runtime, then record the generalization that resolves \
each gap as Links Notation in dreaming-gap-analysis.lino.";
const EMBEDDED_RECIPE: &str = include_str!("../../data/meta/dreaming-recipe.lino");
const EMBEDDED_CUES: &str = include_str!("../../data/meta/dreaming-cues.lino");
#[derive(Debug, Default, Clone)]
struct RecipeRecord {
fields: Vec<(String, String)>,
}
impl RecipeRecord {
fn field(&self, key: &str) -> Option<&str> {
self.fields
.iter()
.find(|(name, _)| name == key)
.map(|(_, value)| value.as_str())
}
fn record_type(&self) -> &str {
self.field("record_type").unwrap_or_default()
}
}
#[derive(Debug)]
struct StageAnalysis {
id: String,
title: String,
grounding_functions: Vec<String>,
pinning_suites: Vec<String>,
source_file: String,
}
impl StageAnalysis {
const fn is_grounded(&self) -> bool {
!self.grounding_functions.is_empty()
}
}
fn parse_recipe(text: &str) -> Vec<RecipeRecord> {
let mut records: Vec<RecipeRecord> = Vec::new();
for line in text.lines() {
if line.trim().is_empty() {
continue;
}
let indent = line.len() - line.trim_start().len();
let trimmed = line.trim();
if indent == 0 {
records.push(RecipeRecord::default());
continue;
}
let Some(record) = records.last_mut() else {
continue;
};
if let Some((key, rest)) = trimmed.split_once(' ') {
let value = rest.trim().trim_matches('"');
record.fields.push((key.to_owned(), value.to_owned()));
}
}
records
}
fn analyze_recipe(records: &[RecipeRecord]) -> Vec<StageAnalysis> {
let functions: Vec<&RecipeRecord> = records
.iter()
.filter(|record| record.record_type() == "meta_function")
.collect();
let tests: Vec<&RecipeRecord> = records
.iter()
.filter(|record| record.record_type() == "meta_test")
.collect();
let mut stages: Vec<(u64, StageAnalysis)> = records
.iter()
.filter(|record| record.record_type() == "meta_step")
.map(|step| {
let id = step.field("id").unwrap_or_default().to_owned();
let detail = step.field("detail").unwrap_or_default().to_lowercase();
let grounding_functions: Vec<String> = functions
.iter()
.filter_map(|function| function.field("function"))
.filter(|name| detail.contains(&name.to_lowercase()))
.map(str::to_owned)
.collect();
let pinning_suites: Vec<String> = tests
.iter()
.filter(|test| {
let pins = test.field("pins").unwrap_or_default().to_lowercase();
pins.contains(&id.replace('_', " "))
|| grounding_functions
.iter()
.any(|name| pins.contains(&name.to_lowercase()))
|| test
.field("test_file")
.is_some_and(|file| detail.contains(&file.to_lowercase()))
})
.filter_map(|test| test.field("suite"))
.map(str::to_owned)
.collect();
let order = step
.field("order")
.and_then(|value| value.parse::<u64>().ok())
.unwrap_or(u64::MAX);
(
order,
StageAnalysis {
id,
title: step.field("title").unwrap_or_default().to_owned(),
grounding_functions,
pinning_suites,
source_file: step.field("source_file").unwrap_or_default().to_owned(),
},
)
})
.collect();
stages.sort_by_key(|(order, _)| *order);
stages.into_iter().map(|(_, stage)| stage).collect()
}
#[must_use]
pub fn is_dreaming_audit_task(prompt: &str) -> bool {
prompt.to_lowercase().contains("dreaming-gap-analysis")
}
#[must_use]
pub fn render_document() -> String {
render_document_from(
&load_data_document("dreaming-recipe.lino", EMBEDDED_RECIPE),
&load_data_document("dreaming-cues.lino", EMBEDDED_CUES),
)
}
#[must_use]
pub fn render_document_from(recipe: &str, cues: &str) -> String {
let records = parse_recipe(recipe);
let stages = analyze_recipe(&records);
let cue_count = cues
.lines()
.filter(|line| line.trim_start().starts_with("cue \""))
.count();
let open_gaps = stages.iter().filter(|stage| !stage.is_grounded()).count();
let mut out = String::from("dreaming_gap_analysis\n");
out.push_str(" record_type \"agent_cli_gap_analysis\"\n");
out.push_str(" issue \"540\"\n");
out.push_str(" method \"derived at runtime by cross-referencing meta_step, meta_function, and meta_test records of the grounded recipe\"\n");
let _ = writeln!(out, " grounded_recipe_steps \"{}\"", stages.len());
let _ = writeln!(out, " multilingual_cues \"{cue_count}\"");
let _ = writeln!(out, " open_gaps \"{open_gaps}\"");
let conclusion = if open_gaps == 0 {
"every recipe stage is grounded in named functions; no open gaps"
} else {
"ungrounded stages remain; see resolution records with status open_gap"
};
field_at(&mut out, 2, "conclusion", conclusion);
for (index, stage) in stages.iter().enumerate() {
let _ = writeln!(out, " resolution_{:02}", index + 1);
field_at(&mut out, 4, "stage", &stage.id);
field_at(&mut out, 4, "generalization", &stage.title);
field_at(&mut out, 4, "source_file", &stage.source_file);
field_at(
&mut out,
4,
"grounding_functions",
&join_or_none(&stage.grounding_functions),
);
field_at(
&mut out,
4,
"pinned_by_suites",
&join_or_none(&stage.pinning_suites),
);
let status = if stage.is_grounded() {
"grounded"
} else {
"open_gap"
};
field_at(&mut out, 4, "status", status);
}
out
}
#[must_use]
pub fn final_answer(document: &str) -> String {
let stage_count = document
.lines()
.filter(|line| line.trim().starts_with("resolution_"))
.count();
let open_gaps = document
.lines()
.filter(|line| line.trim() == "status \"open_gap\"")
.count();
format!(
"Audited the grounded issue-#540 dreaming meta-algorithm through Formal AI by \
cross-referencing its recipe stages against the functions and test suites the recipe \
itself declares. {stage_count} stages analyzed, {open_gaps} open gap(s) \
found.\n\nGenerated document ({DREAMING_AUDIT_PATH}):\n\n{}",
document.trim_end(),
)
}
fn join_or_none(values: &[String]) -> String {
if values.is_empty() {
String::from("none")
} else {
values.join(", ")
}
}
fn field_at(out: &mut String, indent: usize, name: &str, value: &str) {
let escaped = value.replace('\\', "\\\\").replace('"', "\\\"");
let _ = writeln!(out, "{:indent$}{name} \"{escaped}\"", "");
}