Skip to content

Commit 56c30de

Browse files
committed
fix: clean stale module declarations, all 21 tactic tests passing
12 cognitive primitives implemented: 7 as styles/ submodules (rte, htd, smad, tcp, irs, mcp, tca) 5 as additions to existing modules (causal_diff, bgz17_bridge, nars, cascade) 21 tests passing. Waiting for tactics #13-#34. https://claude.ai/code/session_01M3at4EuHVvQ8S95mSnKgtK
1 parent c54b4dc commit 56c30de

3 files changed

Lines changed: 259 additions & 0 deletions

File tree

src/hpc/metacog.rs

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
//! #10 Meta-Cognition — monitor confidence reliability over time.
2+
3+
use super::nars::NarsTruth;
4+
5+
/// Meta-cognitive assessment result.
6+
pub struct MetaAssessment {
7+
pub confidence: f32,
8+
pub meta_confidence: f32,
9+
pub should_admit_ignorance: bool,
10+
}
11+
12+
/// Meta-cognition monitor: tracks confidence history, computes meta-confidence.
13+
/// Science: Fleming & Dolan (2012), Brier (1950), Yeung & Summerfield (2012).
14+
pub struct MetaCognition {
15+
history: Vec<f32>,
16+
max_history: usize,
17+
calibration_error: f32,
18+
}
19+
20+
impl MetaCognition {
21+
pub fn new(max_history: usize) -> Self {
22+
Self { history: Vec::new(), max_history, calibration_error: 0.5 }
23+
}
24+
25+
/// Assess meta-confidence: how reliable is our confidence?
26+
pub fn assess(&mut self, truth: &NarsTruth) -> MetaAssessment {
27+
let confidence = truth.confidence;
28+
self.history.push(confidence);
29+
if self.history.len() > self.max_history {
30+
self.history.remove(0);
31+
}
32+
33+
let mean = self.history.iter().sum::<f32>() / self.history.len() as f32;
34+
let variance = self.history.iter()
35+
.map(|c| (c - mean).powi(2))
36+
.sum::<f32>() / self.history.len() as f32;
37+
38+
let meta_confidence = 1.0 - variance.sqrt();
39+
40+
MetaAssessment {
41+
confidence,
42+
meta_confidence,
43+
should_admit_ignorance: confidence < 0.3 && self.calibration_error > 0.2,
44+
}
45+
}
46+
47+
/// Update calibration error with actual outcome.
48+
pub fn update_calibration(&mut self, predicted_confidence: f32, was_correct: bool) {
49+
let outcome = if was_correct { 1.0 } else { 0.0 };
50+
let brier = (predicted_confidence - outcome).powi(2);
51+
self.calibration_error = 0.9 * self.calibration_error + 0.1 * brier;
52+
}
53+
}
54+
55+
#[cfg(test)]
56+
mod tests {
57+
use super::*;
58+
59+
#[test]
60+
fn test_metacog_stable_confidence() {
61+
let mut mc = MetaCognition::new(100);
62+
for _ in 0..10 {
63+
mc.assess(&NarsTruth::new(0.8, 0.9));
64+
}
65+
let result = mc.assess(&NarsTruth::new(0.8, 0.9));
66+
assert!(result.meta_confidence > 0.9);
67+
assert!(!result.should_admit_ignorance);
68+
}
69+
70+
#[test]
71+
fn test_metacog_unstable_confidence() {
72+
let mut mc = MetaCognition::new(100);
73+
for i in 0..10 {
74+
let c = if i % 2 == 0 { 0.9 } else { 0.1 };
75+
mc.assess(&NarsTruth::new(0.5, c));
76+
}
77+
let result = mc.assess(&NarsTruth::new(0.5, 0.5));
78+
assert!(result.meta_confidence < 0.7);
79+
}
80+
81+
#[test]
82+
fn test_calibration_update() {
83+
let mut mc = MetaCognition::new(100);
84+
for _ in 0..10 {
85+
mc.update_calibration(0.9, false);
86+
}
87+
assert!(mc.calibration_error > 0.3);
88+
}
89+
}

src/hpc/roleplay.rs

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
//! #9 Iterative Roleplay Synthesis — perspective sweep on Base17 fingerprints.
2+
3+
use super::bgz17_bridge::Base17;
4+
5+
/// One perspective result: which role, what it produced, how novel.
6+
pub struct PerspectiveResult {
7+
pub role_idx: usize,
8+
pub result: Base17,
9+
pub novelty: f32,
10+
}
11+
12+
/// Perspective sweep: each role modulates the query via XOR-analog (dim-wise add),
13+
/// then the nearest in corpus is found. Novelty = L1 from accumulated perspectives.
14+
/// Science: Kanerva (2009) XOR binding, De Bono (1985), Galton (1907).
15+
pub fn perspective_sweep(
16+
query: &Base17,
17+
roles: &[Base17],
18+
corpus: &[Base17],
19+
) -> Vec<PerspectiveResult> {
20+
let max_l1 = (17u32 * 65535) as f32;
21+
let mut results = Vec::new();
22+
let mut seen = query.clone();
23+
24+
for (idx, role) in roles.iter().enumerate() {
25+
// Role-modulate query: dim-wise addition (XOR-analog for i16)
26+
let mut modulated = Base17 { dims: [0; 17] };
27+
for d in 0..17 {
28+
modulated.dims[d] = query.dims[d].wrapping_add(role.dims[d]);
29+
}
30+
31+
// Find nearest in corpus
32+
let mut best = corpus.first().cloned().unwrap_or(Base17 { dims: [0; 17] });
33+
let mut best_dist = u32::MAX;
34+
for c in corpus {
35+
let d = modulated.l1(c);
36+
if d < best_dist {
37+
best_dist = d;
38+
best = c.clone();
39+
}
40+
}
41+
42+
// Novelty: how different from accumulated perspectives
43+
let novelty = best.l1(&seen) as f32 / max_l1;
44+
results.push(PerspectiveResult { role_idx: idx, result: best.clone(), novelty });
45+
46+
// Accumulate: running mean
47+
for d in 0..17 {
48+
seen.dims[d] = ((seen.dims[d] as i32 + best.dims[d] as i32) / 2) as i16;
49+
}
50+
}
51+
52+
results.sort_by(|a, b| b.novelty.partial_cmp(&a.novelty).unwrap());
53+
results
54+
}
55+
56+
#[cfg(test)]
57+
mod tests {
58+
use super::*;
59+
60+
#[test]
61+
fn test_perspective_sweep() {
62+
let query = Base17 { dims: [100; 17] };
63+
let roles = vec![
64+
Base17 { dims: [10; 17] },
65+
Base17 { dims: [-50; 17] },
66+
Base17 { dims: [200; 17] },
67+
];
68+
let corpus: Vec<Base17> = (0..20).map(|i| {
69+
let mut dims = [0i16; 17];
70+
dims[0] = (i * 50) as i16;
71+
Base17 { dims }
72+
}).collect();
73+
74+
let results = perspective_sweep(&query, &roles, &corpus);
75+
assert_eq!(results.len(), 3);
76+
assert!(results[0].novelty >= results[1].novelty);
77+
}
78+
79+
#[test]
80+
fn test_perspective_novelty() {
81+
let query = Base17 { dims: [0; 17] };
82+
let roles = vec![
83+
Base17 { dims: [0; 17] },
84+
Base17 { dims: [10000; 17] },
85+
];
86+
let corpus = vec![
87+
Base17 { dims: [0; 17] },
88+
Base17 { dims: [10000; 17] },
89+
];
90+
let results = perspective_sweep(&query, &roles, &corpus);
91+
assert!(results[0].novelty > results[1].novelty);
92+
}
93+
}

src/hpc/temporal.rs

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
//! #12 Temporal Context Augmentation — embed timestamps into Base17 fingerprints.
2+
3+
use super::bgz17_bridge::Base17;
4+
5+
/// Temporal context: event time, reference time, speech time (Reichenbach).
6+
pub struct TemporalContext {
7+
pub event_time: u64,
8+
pub reference_time: u64,
9+
pub speech_time: u64,
10+
}
11+
12+
/// Temporally augmented Base17: original fingerprint + temporal signal.
13+
pub struct TemporalFingerprint {
14+
pub base: Base17,
15+
pub temporal: TemporalContext,
16+
pub recency: f32,
17+
}
18+
19+
/// Augment a Base17 fingerprint with temporal context.
20+
/// Recency decays with time distance from reference.
21+
/// Science: Reichenbach (1947), Kamp & Reyle (1993 Ch.5), Vendler (1957).
22+
pub fn temporalize(
23+
base: &Base17,
24+
event_time: u64,
25+
reference_time: u64,
26+
) -> TemporalFingerprint {
27+
let speech_time = reference_time;
28+
let time_delta = if event_time > reference_time {
29+
event_time - reference_time
30+
} else {
31+
reference_time - event_time
32+
};
33+
let scale = 3600.0;
34+
let recency = (-1.0 * time_delta as f64 / scale).exp() as f32;
35+
36+
TemporalFingerprint {
37+
base: base.clone(),
38+
temporal: TemporalContext { event_time, reference_time, speech_time },
39+
recency,
40+
}
41+
}
42+
43+
/// Temporal similarity: combine Base17 L1 with recency weighting.
44+
pub fn temporal_similarity(a: &TemporalFingerprint, b: &TemporalFingerprint) -> (u32, f32) {
45+
let spatial = a.base.l1(&b.base);
46+
let temporal_weight = (a.recency * b.recency).sqrt();
47+
(spatial, temporal_weight)
48+
}
49+
50+
#[cfg(test)]
51+
mod tests {
52+
use super::*;
53+
54+
#[test]
55+
fn test_temporalize_recent() {
56+
let base = Base17 { dims: [100; 17] };
57+
let tf = temporalize(&base, 1000, 1000);
58+
assert!((tf.recency - 1.0).abs() < 0.01);
59+
}
60+
61+
#[test]
62+
fn test_temporalize_old() {
63+
let base = Base17 { dims: [100; 17] };
64+
let tf = temporalize(&base, 0, 36000);
65+
assert!(tf.recency < 0.01);
66+
}
67+
68+
#[test]
69+
fn test_temporal_similarity() {
70+
let base = Base17 { dims: [100; 17] };
71+
let recent = temporalize(&base, 1000, 1000);
72+
let old = temporalize(&base, 0, 1000);
73+
let (spatial, weight) = temporal_similarity(&recent, &old);
74+
assert_eq!(spatial, 0);
75+
assert!(weight < 1.0);
76+
}
77+
}

0 commit comments

Comments
 (0)