mirror of
https://github.com/samvallad33/vestige.git
synced 2026-04-25 00:36:22 +02:00
fix: remove vestige-agent from workspace (not shipped), improve reasoning chain output
- Removed vestige-agent and vestige-agent-py from workspace members (ARC-AGI-3 code, not part of Vestige release — caused CI failure) - Improved deep_reference reasoning chain: fuller output with arrows on supersession reasoning, longer primary finding preview, fallback message when no relations found, boosted relation detection for search results with high combined_score Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
04781a95e2
commit
5b1127d630
10 changed files with 43 additions and 34 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -136,3 +136,4 @@ apps/dashboard/node_modules/
|
||||||
# External repos (forks, submodules)
|
# External repos (forks, submodules)
|
||||||
# =============================================================================
|
# =============================================================================
|
||||||
fastembed-rs/
|
fastembed-rs/
|
||||||
|
.mcp.json
|
||||||
|
|
|
||||||
|
|
@ -3,8 +3,6 @@ resolver = "2"
|
||||||
members = [
|
members = [
|
||||||
"crates/vestige-core",
|
"crates/vestige-core",
|
||||||
"crates/vestige-mcp",
|
"crates/vestige-mcp",
|
||||||
"crates/vestige-agent",
|
|
||||||
"crates/vestige-agent-py",
|
|
||||||
"tests/e2e",
|
"tests/e2e",
|
||||||
]
|
]
|
||||||
exclude = [
|
exclude = [
|
||||||
|
|
|
||||||
|
|
@ -51,6 +51,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
function playLoop() {
|
function playLoop() {
|
||||||
|
if (!playing) return;
|
||||||
animFrameId = requestAnimationFrame((now) => {
|
animFrameId = requestAnimationFrame((now) => {
|
||||||
const deltaSeconds = (now - lastTime) / 1000;
|
const deltaSeconds = (now - lastTime) / 1000;
|
||||||
lastTime = now;
|
lastTime = now;
|
||||||
|
|
@ -78,6 +79,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
onDestroy(() => {
|
onDestroy(() => {
|
||||||
|
playing = false;
|
||||||
cancelAnimationFrame(animFrameId);
|
cancelAnimationFrame(animFrameId);
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
|
||||||
|
|
@ -245,11 +245,11 @@ describe('EffectManager', () => {
|
||||||
expect(n1Pulses.length).toBeLessThanOrEqual(1);
|
expect(n1Pulses.length).toBeLessThanOrEqual(1);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('applies scale bump to contacted nodes', () => {
|
it('adds pulse to contacted nodes instead of direct scale mutation', () => {
|
||||||
const nodePositions = new Map<string, any>([
|
const nodePositions = new Map<string, any>([
|
||||||
['bump', new Vector3(3, 0, 0)],
|
['bump', new Vector3(3, 0, 0)],
|
||||||
]);
|
]);
|
||||||
const mesh = createMockMesh('bump', new Vector3(3, 0, 0));
|
createMockMesh('bump', new Vector3(3, 0, 0));
|
||||||
|
|
||||||
effects.createRippleWave(new Vector3(0, 0, 0) as any);
|
effects.createRippleWave(new Vector3(0, 0, 0) as any);
|
||||||
|
|
||||||
|
|
@ -258,8 +258,9 @@ describe('EffectManager', () => {
|
||||||
effects.update(nodeMeshMap, camera, nodePositions);
|
effects.update(nodeMeshMap, camera, nodePositions);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Scale should have been bumped (1.3x)
|
// Ripple wave should add a pulse effect (not a direct scale mutation)
|
||||||
expect(mesh.scale.x).toBeGreaterThan(1.0);
|
const bumpPulses = effects.pulseEffects.filter(p => p.nodeId === 'bump');
|
||||||
|
expect(bumpPulses.length).toBeGreaterThan(0);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('completes and cleans up after 90 frames', () => {
|
it('completes and cleans up after 90 frames', () => {
|
||||||
|
|
|
||||||
|
|
@ -335,11 +335,8 @@ export class EffectManager {
|
||||||
rw.pulsedNodes.add(id);
|
rw.pulsedNodes.add(id);
|
||||||
// Mini-pulse on contact
|
// Mini-pulse on contact
|
||||||
this.addPulse(id, 0.8, new THREE.Color(0x00ffd1), 0.03);
|
this.addPulse(id, 0.8, new THREE.Color(0x00ffd1), 0.03);
|
||||||
// Mini scale bump on the mesh
|
// Pulse handles the visual bump — no direct scale mutation
|
||||||
const mesh = nodeMeshMap.get(id);
|
// (multiplyScalar was cumulative and fought with animation system)
|
||||||
if (mesh) {
|
|
||||||
mesh.scale.multiplyScalar(1.3);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -115,7 +115,7 @@ export function mapEventToEffects(
|
||||||
id: data.id,
|
id: data.id,
|
||||||
label: (data.content ?? '').slice(0, 60),
|
label: (data.content ?? '').slice(0, 60),
|
||||||
type: data.node_type ?? 'fact',
|
type: data.node_type ?? 'fact',
|
||||||
retention: data.retention ?? 0.9,
|
retention: Math.max(0, Math.min(1, data.retention ?? 0.9)),
|
||||||
tags: data.tags ?? [],
|
tags: data.tags ?? [],
|
||||||
createdAt: new Date().toISOString(),
|
createdAt: new Date().toISOString(),
|
||||||
updatedAt: new Date().toISOString(),
|
updatedAt: new Date().toISOString(),
|
||||||
|
|
|
||||||
|
|
@ -205,7 +205,11 @@ export class NodeManager {
|
||||||
|
|
||||||
private createTextSprite(text: string, color: string): THREE.Sprite {
|
private createTextSprite(text: string, color: string): THREE.Sprite {
|
||||||
const canvas = document.createElement('canvas');
|
const canvas = document.createElement('canvas');
|
||||||
const ctx = canvas.getContext('2d')!;
|
const ctx = canvas.getContext('2d');
|
||||||
|
if (!ctx) {
|
||||||
|
const tex = new THREE.Texture();
|
||||||
|
return new THREE.Sprite(new THREE.SpriteMaterial({ map: tex, transparent: true, opacity: 0 }));
|
||||||
|
}
|
||||||
canvas.width = 512;
|
canvas.width = 512;
|
||||||
canvas.height = 64;
|
canvas.height = 64;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -45,8 +45,8 @@ function createWebSocketStore() {
|
||||||
const events = [parsed, ...s.events].slice(0, MAX_EVENTS);
|
const events = [parsed, ...s.events].slice(0, MAX_EVENTS);
|
||||||
return { ...s, events };
|
return { ...s, events };
|
||||||
});
|
});
|
||||||
} catch {
|
} catch (e) {
|
||||||
// Ignore malformed messages
|
console.warn('[vestige] Failed to parse WebSocket message:', e);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -380,9 +380,6 @@ impl DreamEngine {
|
||||||
let mut strengthened_ids = Vec::new();
|
let mut strengthened_ids = Vec::new();
|
||||||
|
|
||||||
let replay_set: HashSet<&String> = replay_queue.iter().collect();
|
let replay_set: HashSet<&String> = replay_queue.iter().collect();
|
||||||
let _triaged_map: HashMap<&str, &TriagedMemory> = triaged.iter()
|
|
||||||
.map(|m| (m.id.as_str(), m))
|
|
||||||
.collect();
|
|
||||||
|
|
||||||
// Process replay queue in oscillation waves
|
// Process replay queue in oscillation waves
|
||||||
let wave_count = replay_queue.len().div_ceil(self.wave_batch_size);
|
let wave_count = replay_queue.len().div_ceil(self.wave_batch_size);
|
||||||
|
|
@ -726,10 +723,12 @@ impl DreamEngine {
|
||||||
let mut seen_pairs: HashSet<(String, String)> = HashSet::new();
|
let mut seen_pairs: HashSet<(String, String)> = HashSet::new();
|
||||||
insights.retain(|i| {
|
insights.retain(|i| {
|
||||||
if i.source_memory_ids.len() >= 2 {
|
if i.source_memory_ids.len() >= 2 {
|
||||||
let pair = (
|
let (a, b) = (&i.source_memory_ids[0], &i.source_memory_ids[1]);
|
||||||
i.source_memory_ids[0].clone().min(i.source_memory_ids[1].clone()),
|
let pair = if a <= b {
|
||||||
i.source_memory_ids[0].clone().max(i.source_memory_ids[1].clone()),
|
(a.clone(), b.clone())
|
||||||
);
|
} else {
|
||||||
|
(b.clone(), a.clone())
|
||||||
|
};
|
||||||
seen_pairs.insert(pair)
|
seen_pairs.insert(pair)
|
||||||
} else {
|
} else {
|
||||||
true
|
true
|
||||||
|
|
|
||||||
|
|
@ -219,18 +219,18 @@ fn generate_reasoning_chain(
|
||||||
"PRIMARY FINDING (trust {:.0}%, {}): {}\n",
|
"PRIMARY FINDING (trust {:.0}%, {}): {}\n",
|
||||||
primary.trust * 100.0,
|
primary.trust * 100.0,
|
||||||
primary.updated_at.format("%b %d, %Y"),
|
primary.updated_at.format("%b %d, %Y"),
|
||||||
primary.content.chars().take(150).collect::<String>(),
|
primary.content.chars().take(300).collect::<String>(),
|
||||||
));
|
));
|
||||||
|
|
||||||
// Superseded memories
|
// Superseded memories — with reasoning arrows
|
||||||
let superseded: Vec<_> = relations.iter()
|
let superseded: Vec<_> = relations.iter()
|
||||||
.filter(|(_, _, r)| matches!(r.relation, Relation::Supersedes))
|
.filter(|(_, _, r)| matches!(r.relation, Relation::Supersedes))
|
||||||
.collect();
|
.collect();
|
||||||
for (preview, trust, rel) in &superseded {
|
for (preview, trust, rel) in &superseded {
|
||||||
chain.push_str(&format!(
|
chain.push_str(&format!(
|
||||||
" SUPERSEDES (trust {:.0}%): \"{}\" — {}\n",
|
" SUPERSEDES (trust {:.0}%): \"{}\"\n -> {}\n",
|
||||||
trust * 100.0,
|
trust * 100.0,
|
||||||
preview.chars().take(80).collect::<String>(),
|
preview.chars().take(100).collect::<String>(),
|
||||||
rel.reasoning,
|
rel.reasoning,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
@ -240,7 +240,7 @@ fn generate_reasoning_chain(
|
||||||
.filter(|(_, _, r)| matches!(r.relation, Relation::Supports))
|
.filter(|(_, _, r)| matches!(r.relation, Relation::Supports))
|
||||||
.collect();
|
.collect();
|
||||||
if !supporting.is_empty() {
|
if !supporting.is_empty() {
|
||||||
chain.push_str(&format!("\nSUPPORTED BY {} MEMOR{}:\n",
|
chain.push_str(&format!("SUPPORTED BY {} MEMOR{}:\n",
|
||||||
supporting.len(),
|
supporting.len(),
|
||||||
if supporting.len() == 1 { "Y" } else { "IES" },
|
if supporting.len() == 1 { "Y" } else { "IES" },
|
||||||
));
|
));
|
||||||
|
|
@ -248,7 +248,7 @@ fn generate_reasoning_chain(
|
||||||
chain.push_str(&format!(
|
chain.push_str(&format!(
|
||||||
" + (trust {:.0}%): \"{}\"\n",
|
" + (trust {:.0}%): \"{}\"\n",
|
||||||
trust * 100.0,
|
trust * 100.0,
|
||||||
preview.chars().take(80).collect::<String>(),
|
preview.chars().take(100).collect::<String>(),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -258,19 +258,23 @@ fn generate_reasoning_chain(
|
||||||
.filter(|(_, _, r)| matches!(r.relation, Relation::Contradicts))
|
.filter(|(_, _, r)| matches!(r.relation, Relation::Contradicts))
|
||||||
.collect();
|
.collect();
|
||||||
if !contradicting.is_empty() {
|
if !contradicting.is_empty() {
|
||||||
chain.push_str(&format!("\nCONTRADICTING EVIDENCE ({}):\n", contradicting.len()));
|
chain.push_str(&format!("CONTRADICTING EVIDENCE ({}):\n", contradicting.len()));
|
||||||
for (preview, trust, rel) in contradicting.iter().take(3) {
|
for (preview, trust, rel) in contradicting.iter().take(3) {
|
||||||
chain.push_str(&format!(
|
chain.push_str(&format!(
|
||||||
" ! (trust {:.0}%): \"{}\" — {}\n",
|
" ! (trust {:.0}%): \"{}\"\n -> {}\n",
|
||||||
trust * 100.0,
|
trust * 100.0,
|
||||||
preview.chars().take(80).collect::<String>(),
|
preview.chars().take(100).collect::<String>(),
|
||||||
rel.reasoning,
|
rel.reasoning,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Confidence summary
|
// If no relations found, still provide useful output
|
||||||
chain.push_str(&format!("\nOVERALL CONFIDENCE: {:.0}%\n", confidence * 100.0));
|
if superseded.is_empty() && supporting.is_empty() && contradicting.is_empty() {
|
||||||
|
chain.push_str("NO CONTRADICTIONS DETECTED. Evidence is consistent.\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
chain.push_str(&format!("OVERALL CONFIDENCE: {:.0}%\n", confidence * 100.0));
|
||||||
|
|
||||||
chain
|
chain
|
||||||
}
|
}
|
||||||
|
|
@ -541,12 +545,15 @@ pub async fn execute(
|
||||||
.max_by(|a, b| a.trust.partial_cmp(&b.trust).unwrap_or(std::cmp::Ordering::Equal))
|
.max_by(|a, b| a.trust.partial_cmp(&b.trust).unwrap_or(std::cmp::Ordering::Equal))
|
||||||
{
|
{
|
||||||
for other in scored.iter().filter(|s| s.id != primary.id).take(15) {
|
for other in scored.iter().filter(|s| s.id != primary.id).take(15) {
|
||||||
|
// Use combined_score as a proxy for semantic similarity (already reranked)
|
||||||
|
// Fall back to topic_overlap for keyword-level comparison
|
||||||
let sim = topic_overlap(&primary.content, &other.content);
|
let sim = topic_overlap(&primary.content, &other.content);
|
||||||
|
let effective_sim = if other.combined_score > 0.2 { sim.max(0.3) } else { sim };
|
||||||
let rel = assess_relation(
|
let rel = assess_relation(
|
||||||
&primary.content, &other.content,
|
&primary.content, &other.content,
|
||||||
primary.trust, other.trust,
|
primary.trust, other.trust,
|
||||||
primary.updated_at, other.updated_at,
|
primary.updated_at, other.updated_at,
|
||||||
sim,
|
effective_sim,
|
||||||
);
|
);
|
||||||
if !matches!(rel.relation, Relation::Irrelevant) {
|
if !matches!(rel.relation, Relation::Irrelevant) {
|
||||||
pair_relations.push((
|
pair_relations.push((
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue