Restore full N×M memory scoring matrix (/score command)

The full matrix scorer was deleted during the AST conversion. Restore
it: /score runs score_memories() which computes divergence for every
memory × response pair, stores the MemoryScore on MindState, and
displays per-memory weights with bar charts on the F2 screen.

Both scoring paths now use ActivityGuard::update() for live progress
in the status bar instead of creating a new activity per iteration.

Also bumps score API timeout from 120s to 300s and adds progress
logging throughout.

Co-Authored-By: Proof of Concept <poc@bcachefs.org>
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
This commit is contained in:
ProofOfConcept 2026-04-09 22:19:02 -04:00 committed by Kent Overstreet
parent f6a6c37435
commit 58cec97e57
6 changed files with 187 additions and 98 deletions

View file

@ -57,8 +57,8 @@ fn commands() -> Vec<SlashCommand> { vec![
});
}
} },
SlashCommand { name: "/score", help: "Score memory importance",
handler: |s, _| { let _ = s.mind_tx.send(MindCommand::Score); } },
SlashCommand { name: "/score", help: "Score memory importance (full matrix)",
handler: |s, _| { let _ = s.mind_tx.send(MindCommand::ScoreFull); } },
SlashCommand { name: "/dmn", help: "Show DMN state",
handler: |s, _| {
let st = s.shared_mind.lock().unwrap();
@ -527,7 +527,7 @@ impl InteractScreen {
}
}
}
AstNode::Branch { role, children } => {
AstNode::Branch { role, children, .. } => {
match role {
Role::User => {
let text: String = children.iter()

View file

@ -39,7 +39,7 @@ impl ConsciousScreen {
if let AstNode::Leaf(leaf) = node {
if let NodeBody::Memory { key, score, text } = leaf.body() {
let status = match score {
Some(s) => { scored += 1; format!("score: {:.2}", s) }
Some(s) => { scored += 1; format!("{:.2}", s) }
None => { unscored += 1; String::new() }
};
mem_children.push(SectionView {
@ -63,7 +63,51 @@ impl ConsciousScreen {
});
}
views.push(section_to_view("Conversation", ctx.conversation()));
let conv = ctx.conversation();
let mut conv_children: Vec<SectionView> = Vec::new();
for node in conv {
let mut view = SectionView {
name: node.label(),
tokens: node.tokens(),
content: match node {
AstNode::Leaf(leaf) => leaf.body().text().to_string(),
_ => String::new(),
},
children: match node {
AstNode::Branch { children, .. } => children.iter()
.map(|c| SectionView {
name: c.label(), tokens: c.tokens(),
content: match c { AstNode::Leaf(l) => l.body().text().to_string(), _ => String::new() },
children: Vec::new(), status: String::new(),
}).collect(),
_ => Vec::new(),
},
status: String::new(),
};
// Show memory attribution inline as status text
if let AstNode::Branch { memory_scores: ms, .. } = node {
if !ms.is_empty() {
let mut attrs: Vec<(&str, f64)> = ms.iter()
.map(|(k, v)| (k.as_str(), *v))
.collect();
attrs.sort_by(|a, b| b.1.partial_cmp(&a.1).unwrap_or(std::cmp::Ordering::Equal));
let parts: Vec<String> = attrs.iter()
.map(|(k, s)| format!("{}({:.1})", k, s))
.collect();
view.status = format!("{}", parts.join(" "));
}
}
conv_children.push(view);
}
let conv_tokens: usize = conv_children.iter().map(|c| c.tokens).sum();
views.push(SectionView {
name: format!("Conversation ({} entries)", conv_children.len()),
tokens: conv_tokens,
content: String::new(),
children: conv_children,
status: String::new(),
});
views
}
}

View file

@ -187,10 +187,9 @@ impl SubconsciousScreen {
agent.context.try_lock().ok()
.map(|ctx| {
let conv = ctx.conversation();
let mut view = section_to_view("Conversation", conv);
let view = section_to_view("Conversation", conv);
let fork = fork_point.min(view.children.len());
view.children = view.children.split_off(fork);
vec![view]
view.children.into_iter().skip(fork).collect()
})
.unwrap_or_default()
}