use std::sync::Arc;
use khive_pack_brain::BrainPack;
use khive_pack_kg::KgPack;
use khive_pack_memory::MemoryPack;
use khive_runtime::{DispatchHook, KhiveRuntime, Namespace, PackRuntime, VerbRegistryBuilder};
use serde_json::json;
async fn promote_namespace(brain: &BrainPack, rt: &KhiveRuntime, namespace: &str) {
use khive_runtime::{Namespace, VerbRegistryBuilder};
let registry = VerbRegistryBuilder::new()
.build()
.expect("minimal registry for promotion");
let ns = Namespace::parse(namespace).expect("valid namespace string");
let token = rt.authorize(ns).expect("authorize namespace token");
brain
.dispatch("brain.profiles", json!({}), ®istry, &token)
.await
.expect("brain.profiles must succeed to promote namespace via production path");
}
#[tokio::test]
async fn dispatch_hook_fires_on_cold_namespace_no_prior_activation() {
let rt = KhiveRuntime::memory().expect("in-memory runtime");
let brain = Arc::new(BrainPack::new(rt.clone()));
let mut builder = VerbRegistryBuilder::new();
builder.register(KgPack::new(rt.clone()));
let hook: Arc<dyn DispatchHook> = brain.clone();
builder.with_dispatch_hook(hook);
let registry = builder.build().expect("registry builds");
registry
.dispatch(
"create",
json!({
"kind": "entity",
"name": "ColdHookProbe",
"entity_kind": "concept"
}),
)
.await
.expect("create entity must succeed");
promote_namespace(&brain, &rt, "local").await;
let snap = brain.snapshot();
assert_eq!(
snap.balanced_recall.total_events, 1,
"active snapshot total_events must be 1 after cold-hook signal survives promotion; got {}",
snap.balanced_recall.total_events
);
}
#[tokio::test]
async fn dispatch_hook_applies_signals_per_namespace_independently() {
let rt = KhiveRuntime::memory().expect("in-memory runtime");
let brain = Arc::new(BrainPack::new(rt.clone()));
let build_registry = |ns: &str| {
let rt2 = rt.clone();
let brain2 = brain.clone();
let ns_owned = ns.to_string();
let mut builder = VerbRegistryBuilder::new();
builder.register(KgPack::new(rt2));
builder.with_default_namespace(ns_owned);
let hook: Arc<dyn DispatchHook> = brain2;
builder.with_dispatch_hook(hook);
builder.build().expect("registry builds")
};
let reg_alpha = build_registry("ns-alpha");
let reg_beta = build_registry("ns-beta");
for i in 0..2u32 {
reg_alpha
.dispatch(
"create",
json!({"kind":"entity","name":format!("AlphaE{i}"),"entity_kind":"concept"}),
)
.await
.expect("alpha dispatch");
}
for i in 0..3u32 {
reg_beta
.dispatch(
"create",
json!({"kind":"entity","name":format!("BetaE{i}"),"entity_kind":"concept"}),
)
.await
.expect("beta dispatch");
}
promote_namespace(&brain, &rt, "ns-alpha").await;
let snap_alpha = brain.snapshot();
assert_eq!(
snap_alpha.balanced_recall.total_events, 2,
"ns-alpha active snapshot must show 2 events after promotion; got {}",
snap_alpha.balanced_recall.total_events
);
promote_namespace(&brain, &rt, "ns-beta").await;
let snap_beta = brain.snapshot();
assert_eq!(
snap_beta.balanced_recall.total_events, 3,
"ns-beta active snapshot must show 3 events after promotion; got {}",
snap_beta.balanced_recall.total_events
);
}
#[tokio::test]
async fn brain_pack_hook_does_not_fire_on_unknown_verb() {
let rt = KhiveRuntime::memory().expect("in-memory runtime");
let brain = Arc::new(BrainPack::new(rt.clone()));
let mut builder = VerbRegistryBuilder::new();
builder.register(KgPack::new(rt.clone()));
let hook: Arc<dyn DispatchHook> = brain.clone();
builder.with_dispatch_hook(hook);
let registry = builder.build().expect("registry builds");
let _ = registry.dispatch("frobnicate_nonexistent", json!({})).await;
promote_namespace(&brain, &rt, "local").await;
let snap = brain.snapshot();
assert_eq!(
snap.balanced_recall.total_events, 0,
"failed dispatch must NOT fire the hook; total_events must remain 0 after promotion; got {}",
snap.balanced_recall.total_events
);
}
#[tokio::test]
async fn cold_hook_signal_applies_on_top_of_persisted_snapshot() {
use khive_runtime::Namespace;
let rt = KhiveRuntime::memory().expect("in-memory runtime");
let setup_registry = {
let mut builder = VerbRegistryBuilder::new();
builder.register(KgPack::new(rt.clone()));
builder.register(BrainPack::new(rt.clone()));
builder.build().expect("setup registry")
};
let entity_result = setup_registry
.dispatch(
"create",
json!({
"kind": "entity",
"name": "SnapshotProbeTarget",
"entity_kind": "concept"
}),
)
.await
.expect("create entity for feedback target");
let target_id = entity_result["id"]
.as_str()
.expect("created entity must have id")
.to_string();
let brain_a = BrainPack::new(rt.clone());
let empty_registry = VerbRegistryBuilder::new()
.build()
.expect("minimal registry");
let local_ns = Namespace::parse("local").expect("local namespace");
let local_token = rt.authorize(local_ns).expect("local token");
brain_a
.dispatch("brain.profiles", json!({}), &empty_registry, &local_token)
.await
.expect("promote local namespace in brain_a before feedback");
for _ in 0..5u32 {
brain_a
.dispatch(
"brain.feedback",
json!({ "target_id": target_id, "signal": "useful" }),
&empty_registry,
&local_token,
)
.await
.expect("brain.feedback must succeed");
}
let persisted_total = brain_a.snapshot().balanced_recall.total_events;
assert_eq!(
persisted_total, 5,
"after 5 feedback calls brain_a snapshot must show 5 total_events; got {persisted_total}"
);
drop(brain_a);
let brain_b = Arc::new(BrainPack::new(rt.clone()));
let mut hook_builder = VerbRegistryBuilder::new();
hook_builder.register(KgPack::new(rt.clone()));
hook_builder.with_default_namespace("local".to_string());
let hook_arc: Arc<dyn DispatchHook> = brain_b.clone();
hook_builder.with_dispatch_hook(hook_arc);
let hook_registry = hook_builder.build().expect("hook registry for brain_b");
hook_registry
.dispatch(
"create",
json!({"kind":"entity","name":"ColdReplayProbe","entity_kind":"concept"}),
)
.await
.expect("kg dispatch through brain_b hook must succeed");
brain_b
.dispatch("brain.profiles", json!({}), &empty_registry, &local_token)
.await
.expect("promote local namespace in brain_b via cold DB load");
let snap = brain_b.snapshot();
assert_eq!(
snap.balanced_recall.total_events,
persisted_total + 1,
"brain_b cold-reload must yield persisted total ({persisted_total}) + \
1 queued signal; got {}",
snap.balanced_recall.total_events
);
}
#[tokio::test]
async fn brain_feedback_accepts_foreign_namespace_target_id() {
let rt = KhiveRuntime::memory().expect("in-memory runtime");
let ns_primary = Namespace::parse("brain-primary-ns").unwrap();
let ns_foreign = Namespace::parse("brain-foreign-ns").unwrap();
let tok_foreign = rt.authorize(ns_foreign.clone()).unwrap();
let foreign_note = rt
.create_note(
&tok_foreign,
"observation",
None,
"foreign-namespace recalled memory",
None,
None,
vec![],
)
.await
.unwrap();
let foreign_id = foreign_note.id.as_hyphenated().to_string();
let tok_primary = rt.authorize(ns_primary.clone()).unwrap();
let brain = BrainPack::new(rt.clone());
let empty_registry = VerbRegistryBuilder::new().build().unwrap();
brain
.dispatch("brain.profiles", json!({}), &empty_registry, &tok_primary)
.await
.expect("promote primary namespace");
let out = brain
.dispatch(
"brain.feedback",
json!({ "target_id": foreign_id, "signal": "useful" }),
&empty_registry,
&tok_primary,
)
.await;
assert!(
out.is_ok(),
"brain.feedback on a foreign-namespace target must succeed \
(ADR-007 Rule 2 by-ID resolution); got: {out:?}"
);
let absent = "00000000-0000-4000-8000-000000000000";
let err = brain
.dispatch(
"brain.feedback",
json!({ "target_id": absent, "signal": "useful" }),
&empty_registry,
&tok_primary,
)
.await
.unwrap_err();
assert!(
err.to_string().to_lowercase().contains("not found"),
"brain.feedback on an absent target_id must return NotFound; got: {err}"
);
}
#[tokio::test]
async fn memory_recall_through_real_registry_updates_brain_posteriors() {
let rt = KhiveRuntime::memory().expect("in-memory runtime");
let brain = Arc::new(BrainPack::new(rt.clone()));
let mut builder = VerbRegistryBuilder::new();
builder.register(KgPack::new(rt.clone()));
builder.register(MemoryPack::new(rt.clone()));
let hook: Arc<dyn DispatchHook> = brain.clone();
builder.with_dispatch_hook(hook);
let registry = builder.build().expect("registry builds");
let remembered = registry
.dispatch(
"memory.remember",
json!({
"content": "The attention mechanism in transformers uses Q K V matrices",
"memory_type": "semantic",
"salience": 0.8,
"decay": 0.01
}),
)
.await
.expect("memory.remember succeeds");
let note_id = remembered["id"]
.as_str()
.expect("remembered note has id")
.to_string();
let before = brain.snapshot().balanced_recall;
let recall_result = registry
.dispatch(
"memory.recall",
json!({ "query": "attention mechanism transformers", "limit": 1 }),
)
.await
.expect("memory.recall succeeds");
let hits = recall_result.as_array().expect("recall returns an array");
assert!(
!hits.is_empty(),
"recall must produce a real hit, not a miss"
);
let hit_id = hits[0]["id"].as_str().expect("hit has id").to_string();
assert_eq!(
hit_id, note_id,
"recall must hit the memory just remembered (sanity check before asserting learning)"
);
promote_namespace(&brain, &rt, "local").await;
let after = brain.snapshot().balanced_recall;
assert_ne!(
(after.temporal.alpha(), after.temporal.beta()),
(before.temporal.alpha(), before.temporal.beta()),
"temporal posterior must move on a real memory.recall hit dispatched \
through the real VerbRegistry; before={:?} after={:?}",
(before.temporal.alpha(), before.temporal.beta()),
(after.temporal.alpha(), after.temporal.beta())
);
let hit_uuid: uuid::Uuid = hit_id.parse().expect("hit id is a valid uuid");
let entity_posterior = after
.entity_posteriors
.get(&hit_uuid)
.expect("hit entity must have a posterior entry after a real recall hit");
assert_ne!(
(entity_posterior.alpha(), entity_posterior.beta()),
(1.0, 1.0),
"hit entity posterior must move off the BetaPosterior::new(1.0, 1.0) default; got {:?}",
(entity_posterior.alpha(), entity_posterior.beta())
);
assert!(
!before.entity_posteriors.contains_key(&hit_uuid),
"sanity: the hit entity must not have had a posterior before this recall"
);
}