feedback: not-relevant/not-useful commands, edge strength adjustment

Add adjust_edge_strength() to Store — modifies strength on all edges
between two nodes, clamped to [0.05, 0.95].

New commands:
- `not-relevant KEY` — weakens ALL edges to the node by 0.01
  (bad routing: search found the wrong thing)
- `not-useful KEY` — weakens node weight, not edges
  (bad content: search found the right thing but it's not good)

Enhanced `used KEY` — now also strengthens all edges to the node by
0.01, in addition to the existing node weight boost.

Three-tier design: agents adjust by 0.00001 (automatic), conscious
commands adjust by 0.01 (deliberate), manual override sets directly.
All clamped, never hitting 0 or 1.

Design spec: .claude/analysis/2026-03-14-link-strength-feedback.md

Co-Authored-By: Kent Overstreet <kent.overstreet@linux.dev>
This commit is contained in:
ProofOfConcept 2026-03-14 12:14:17 -04:00
parent dccc18b205
commit cb44138433
3 changed files with 184 additions and 1 deletions

View file

@ -175,6 +175,18 @@ EXAMPLES:
/// Optional context
context: Vec<String>,
},
/// Mark a search result as not relevant (weakens edges that led to it)
#[command(name = "not-relevant")]
NotRelevant {
/// Node key that was not relevant
key: String,
},
/// Mark a node as not useful (weakens node weight, not edges)
#[command(name = "not-useful")]
NotUseful {
/// Node key
key: String,
},
/// Record a gap in memory coverage
Gap {
/// Gap description
@ -717,6 +729,8 @@ fn main() {
Command::Query { expr } => cmd_query(&expr),
Command::Used { key } => cmd_used(&key),
Command::Wrong { key, context } => cmd_wrong(&key, &context),
Command::NotRelevant { key } => cmd_not_relevant(&key),
Command::NotUseful { key } => cmd_not_useful(&key),
Command::Gap { description } => cmd_gap(&description),
// Node
@ -1342,8 +1356,24 @@ fn cmd_used(key: &[String]) -> Result<(), String> {
let mut store = store::Store::load()?;
let resolved = store.resolve_key(&key)?;
store.mark_used(&resolved);
// Also strengthen edges to this node — conscious-tier delta.
const DELTA: f32 = 0.01;
let mut strengthened = 0;
for rel in &mut store.relations {
if rel.deleted { continue; }
if rel.source_key == resolved || rel.target_key == resolved {
let old = rel.strength;
rel.strength = (rel.strength + DELTA).clamp(0.05, 0.95);
if (rel.strength - old).abs() > 0.001 {
rel.version += 1;
strengthened += 1;
}
}
}
store.save()?;
println!("Marked '{}' as used", resolved);
println!("Marked '{}' as used (strengthened {} edges)", resolved, strengthened);
Ok(())
}
@ -1357,6 +1387,40 @@ fn cmd_wrong(key: &str, context: &[String]) -> Result<(), String> {
Ok(())
}
fn cmd_not_relevant(key: &str) -> Result<(), String> {
let mut store = store::Store::load()?;
let resolved = store.resolve_key(key)?;
// Weaken all edges to this node — it was routed to incorrectly.
// Conscious-tier delta: 0.01 per edge.
const DELTA: f32 = -0.01;
let mut adjusted = 0;
for rel in &mut store.relations {
if rel.deleted { continue; }
if rel.source_key == resolved || rel.target_key == resolved {
let old = rel.strength;
rel.strength = (rel.strength + DELTA).clamp(0.05, 0.95);
if (rel.strength - old).abs() > 0.001 {
rel.version += 1;
adjusted += 1;
}
}
}
store.save()?;
println!("Not relevant: '{}' — weakened {} edges by {}", resolved, adjusted, DELTA.abs());
Ok(())
}
fn cmd_not_useful(key: &str) -> Result<(), String> {
let mut store = store::Store::load()?;
let resolved = store.resolve_key(key)?;
// Same as wrong but with clearer semantics: node content is bad, edges are fine.
store.mark_wrong(&resolved, Some("not-useful"));
store.save()?;
println!("Not useful: '{}' — node weight reduced", resolved);
Ok(())
}
fn cmd_gap(description: &[String]) -> Result<(), String> {
if description.is_empty() {
return Err("gap requires a description".into());