daemonic_error 0.1.0

Errors that compose, predict, and leave receipts - Compose: algebraic combination (in active development) - Predict: Glass/Severity - Receipts: audit trail, position, checksum - Reflection: Runtime Reflection through TopologySegment (in active development)
use crate::{DaemonicClock, DaemonicError};
use crate::daemonic::observation::observable::Observable;
use crate::daemonic::glass::Severity;
use crate::daemonic::glass::Glass;
use crate::daemonic::{SemanticAnchor, TopologySegment};

/// DaemonicObserver — "I can see."
///
/// The observer side of observation. Things that direct
/// observation at observables and receive glass reflections.
///
/// The human wielding the rock. The Shade projecting Walkers.
/// The compiler inspecting source code.
///
/// Observer requires the full Daemonic trait because observers
/// need identity (who am I), time (when did I look), and
/// position (where am I in the lattice).
///
/// ONE required method: observe().
/// Everything else is defaulted.
pub trait DaemonicObserver<GLASS: Glass<GLASS> + Iterator>: Send + Sync {
	/// The clock this observer uses for timestamping observations.
	type Clock: for<'clock> DaemonicClock<'clock, GLASS>;
	
	/// Core observation. THE method.
	/// Look at an observable, get a glass back.
	///
	/// The glass returned is the single-sided mirror between
	/// this observer and the target. What comes back depends
	/// on the target's state, the observer's state, and
	/// the medium between them.
	fn observe<T: Observable>(
		&self,
		target: &T,
	) -> impl Glass<T::Observed>;
	
	/// Observer's position in the lattice.
	/// Required for positioning observations.
	fn position(&self) -> &TopologySegment;
	
	/// Re-observe with awareness of prior result.
	/// Default: just observe again, ignore prior.
	/// Override for context-sensitive re-observation
	/// (the curiosity loop).
	fn re_observe<T: Observable>(
		&self,
		target: &T,
		prior_severity: Severity,
	) -> impl Glass<T::Observed> {
		self.observe(target)
	}
	
	/// Self-healing observation loop. PROVIDED FREE.
	///
	/// Does NOT cap depth. Depth is irrelevant.
	/// Terminates on entropy conditions:
	///   - Zero delta: clock didn't tick between observations
	///   - Exponential degradation: work per observation halving
	///   - Path revisit: same target observed too many times
	///     without novel results
	///
	/// Clock tick = work = entropy.
	/// When work stops, observation stops.
	/// When work degrades exponentially, observation stops.
	///
	/// The curiosity loop: observe → check entropy → re-observe
	/// until the clock settles.
	// todo: fix, self cant find clock
	// fn observe_until_stable<T: Observable, C: for<'clock> DaemonicClock<'clock, GLASS>>(&self, target: &T) -> impl Glass<T::Observed> {
	// 	let mut observation = self.observe(target);
	// 	// let mut last_tick = self.clock().now(); //todo fix this
	// 	let mut last_tick = C::now;
	// 	let mut prev_delta: Option<u64> = None;
	// 	let mut zero_count: usize = 0;
	//
	// 	loop {
	// 		let current_severity = observation.severity();
	//
	// 		// Terminal states: stop regardless of entropy
	// 		match current_severity {
	// 			Severity::Stable => break,
	// 			Severity::Impossible => break,
	// 			// Warp and Shattered are terminal for observation
	// 			// but the CALLER might want to repair
	// 			// so we break and let them decide
	// 			Severity::Warp | Severity::Shattered => break,
	// 			_ => {}
	// 		}
	//
	// 		// Check entropy: has the clock moved?
	// 		let current_tick = C::now;
	// 		let delta = current_tick.saturating_sub(last_tick);
	//
	// 		// Zero delta: no work done
	// 		if delta == 0 {
	// 			zero_count += 1;
	// 			// Allow a few zero-deltas (sometimes work
	// 			// happens between observations that doesn't tick)
	// 			// but not many
	// 			if zero_count >= 3 {
	// 				break; // entropy death
	// 			}
	// 		} else {
	// 			zero_count = 0; // reset on any work
	// 		}
	//
	// 		// Exponential degradation: work is collapsing
	// 		if let Some(prev) = prev_delta {
	// 			if prev > 0 && delta < prev / 2 {
	// 				break; // degradation termination
	// 			}
	// 		}
	//
	// 		prev_delta = Some(delta);
	// 		last_tick = current_tick;
	//
	// 		// Re-observe with prior context
	// 		observation = self.re_observe(target, current_severity);
	// 	}
	//
	// 	observation
	// }
	/// Declare entity death (Broken Sword)
	///
	/// Called when: Entity encounters unrecoverable error
	/// Returns: BrokenSwordContext error with full context
	/// # Broken Sword Semantics
	///
	/// "Broken Sword" is a self-aware death declaration by a Daemonic entity.
	/// The term originates from the Unification Wars Trilogy, where TCS Jericho,
	/// trapped and outnumbered, declared "Jericho is Broken Sword" - meaning:
	/// "We are dying, we will not surrender, rescue is impossible, recovery only."
	///
	/// In Daemonic context:
	/// - Entity encounters unrecoverable error
	/// - Entity declares its own death (not external kill)
	/// - Error propagates upstream to parent
	/// - Parent marks entity for reaping
	/// - Parent survives (no cascade failure)
	///
	/// ## Reap Strategy
	///
	/// **Default: Background reaping**
	/// - Entities queued for cleanup
	/// - Processed asynchronously
	/// - No blocking on parent
	///
	/// **System-level: Immediate reaping** (future)
	/// - Flagged for priority cleanup
	/// - Sudo privileges (future detection)
	/// - Processed before background queue
	///
	/// ## Reap Failure Handling
	///
	/// After 3 failed reap attempts:
	/// 1. **Map boundaries**: Identify affected symbols (event horizon)
	/// 2. **Establish orbit**: Mark symbols as orbiting black hole
	/// 3. **Force kill**: Topology unwrapped enough, safe to terminate
	///
	/// This prevents hard desync by maintaining topological awareness
	/// even when entity cannot be gracefully reaped.
	///
	/// ## Cascade Death
	///
	/// When parent dies:
	/// - Child with no external references → Dies with parent
	/// - Child with external references → Survives (orphaned)
	/// - Child with dependents → Survives (needed by others)
	///
	/// ## Mesh Awareness (future)
	///
	/// All entity deaths are broadcast to mesh peers (if configured):
	/// - Enables distributed reference tracking
	/// - Prevents dangling references
	/// - Maintains mesh consistency
	fn broken_sword(&self, err: impl SemanticAnchor) -> GLASS;
}