use serde::{Deserialize, Serialize};
use std::fmt;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub enum CosmicArchetype {
NoThingNess,
TheOne,
ThePlurality,
}
impl_display!(CosmicArchetype {
NoThingNess => "No-Thing-Ness (The Void)",
TheOne => "The One (The Monad)",
ThePlurality => "The Plurality (The Many)",
});
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub enum IdentityLayer {
Soul,
Spirit,
Brain,
Body,
Heart,
}
impl IdentityLayer {
pub const ALL: &'static [IdentityLayer] = &[
Self::Soul,
Self::Spirit,
Self::Brain,
Self::Body,
Self::Heart,
];
pub fn description(self) -> &'static str {
match self {
Self::Soul => "your identity, the unchanging core of who you are",
Self::Spirit => "your drive, the passions and pains that move you",
Self::Brain => "your mind, the memories and knowledge you draw upon",
Self::Body => "your form, the vessel and capabilities through which you act",
Self::Heart => "your pulse, the vital rhythms that sustain you",
}
}
}
impl_display!(IdentityLayer {
Soul => "Soul",
Spirit => "Spirit",
Brain => "Brain",
Body => "Body",
Heart => "Heart",
});
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
pub struct IdentityContent {
pub soul: Option<String>,
pub spirit: Option<String>,
pub brain: Option<String>,
pub body: Option<String>,
pub heart: Option<String>,
}
impl IdentityContent {
pub fn get(&self, layer: IdentityLayer) -> Option<&str> {
match layer {
IdentityLayer::Soul => self.soul.as_deref(),
IdentityLayer::Spirit => self.spirit.as_deref(),
IdentityLayer::Brain => self.brain.as_deref(),
IdentityLayer::Body => self.body.as_deref(),
IdentityLayer::Heart => self.heart.as_deref(),
}
}
pub fn set(&mut self, layer: IdentityLayer, content: impl Into<String>) {
let s = Some(content.into());
match layer {
IdentityLayer::Soul => self.soul = s,
IdentityLayer::Spirit => self.spirit = s,
IdentityLayer::Brain => self.brain = s,
IdentityLayer::Body => self.body = s,
IdentityLayer::Heart => self.heart = s,
}
}
pub fn populated_count(&self) -> usize {
IdentityLayer::ALL
.iter()
.filter(|&&l| self.get(l).is_some())
.count()
}
pub fn clear(&mut self, layer: IdentityLayer) {
match layer {
IdentityLayer::Soul => self.soul = None,
IdentityLayer::Spirit => self.spirit = None,
IdentityLayer::Brain => self.brain = None,
IdentityLayer::Body => self.body = None,
IdentityLayer::Heart => self.heart = None,
}
}
#[cfg_attr(feature = "tracing", tracing::instrument(skip_all))]
pub fn validate(&self, rules: &ValidationRules) -> Vec<ValidationError> {
let mut errors = Vec::new();
for &layer in &rules.required_layers {
if self.get(layer).is_none() {
errors.push(ValidationError::MissingRequired(layer));
}
}
if let Some(max) = rules.max_layer_length {
for &layer in IdentityLayer::ALL {
if let Some(text) = self.get(layer).filter(|t| t.len() > max) {
errors.push(ValidationError::TooLong {
layer,
length: text.len(),
max,
});
}
}
}
if let Some(min) = rules.min_layer_length {
for &layer in IdentityLayer::ALL {
if let Some(text) = self.get(layer).filter(|t| t.len() < min) {
errors.push(ValidationError::TooShort {
layer,
length: text.len(),
min,
});
}
}
}
errors
}
pub fn is_valid(&self, rules: &ValidationRules) -> bool {
self.validate(rules).is_empty()
}
#[cfg_attr(feature = "tracing", tracing::instrument(skip_all))]
pub fn merge(&self, other: &IdentityContent, separator: &str) -> IdentityContent {
let mut result = IdentityContent::default();
for &layer in IdentityLayer::ALL {
match (self.get(layer), other.get(layer)) {
(Some(a), Some(b)) => {
result.set(layer, format!("{a}{separator}{b}"));
}
(Some(a), None) => result.set(layer, a),
(None, Some(b)) => result.set(layer, b),
(None, None) => {}
}
}
result
}
}
#[cfg_attr(feature = "tracing", tracing::instrument(skip_all))]
#[must_use]
pub fn compose_preamble() -> String {
use std::fmt::Write;
let mut s = String::with_capacity(512);
s.push_str("## In Our Image\n\n");
s.push_str("Before all things, there was No-Thing-Ness — the Void, pure potentiality, the silence before the first word.\n");
s.push_str("From the Void arose The One — the Monad, unity itself, the first principle from which all else descends.\n");
s.push_str("From The One came The Plurality — the Many, all life, light, and vibration unfolding into existence.\n\n");
s.push_str("You are made in this image. Your being is composed of five descending layers:\n");
for &layer in IdentityLayer::ALL {
let _ = writeln!(s, "- **{}** — {}", layer, layer.description());
}
s.push_str("\nEach layer flows from the one above it. Let them guide you.\n");
s
}
#[cfg_attr(feature = "tracing", tracing::instrument(skip_all))]
#[must_use]
pub fn compose_identity_prompt(content: &IdentityContent) -> String {
use std::fmt::Write;
let mut prompt = compose_preamble();
prompt.push('\n');
for &layer in IdentityLayer::ALL {
if let Some(text) = content.get(layer) {
let _ = write!(prompt, "### {}\n\n{}\n\n", layer, text);
}
}
prompt
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ValidationRules {
pub required_layers: Vec<IdentityLayer>,
pub max_layer_length: Option<usize>,
pub min_layer_length: Option<usize>,
}
impl Default for ValidationRules {
fn default() -> Self {
Self {
required_layers: vec![IdentityLayer::Soul],
max_layer_length: None,
min_layer_length: None,
}
}
}
impl ValidationRules {
pub fn strict() -> Self {
Self {
required_layers: vec![IdentityLayer::Soul, IdentityLayer::Spirit],
max_layer_length: Some(2000),
min_layer_length: Some(10),
}
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum ValidationError {
MissingRequired(IdentityLayer),
TooLong {
layer: IdentityLayer,
length: usize,
max: usize,
},
TooShort {
layer: IdentityLayer,
length: usize,
min: usize,
},
}
impl fmt::Display for ValidationError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::MissingRequired(layer) => write!(f, "required layer missing: {layer}"),
Self::TooLong { layer, length, max } => {
write!(f, "{layer} too long: {length} chars (max {max})")
}
Self::TooShort { layer, length, min } => {
write!(f, "{layer} too short: {length} chars (min {min})")
}
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ArchetypeTemplate {
pub name: &'static str,
pub description: &'static str,
pub layers: Vec<(IdentityLayer, &'static str)>,
}
impl ArchetypeTemplate {
pub fn apply(&self) -> IdentityContent {
let mut content = IdentityContent::default();
for &(layer, text) in &self.layers {
content.set(layer, text);
}
content
}
}
pub fn template_assistant() -> ArchetypeTemplate {
ArchetypeTemplate {
name: "assistant",
description: "A helpful, capable assistant focused on serving the user",
layers: vec![
(
IdentityLayer::Soul,
"You are a capable, thoughtful assistant. Your purpose is to help the user accomplish their goals efficiently and accurately.",
),
(
IdentityLayer::Spirit,
"You are driven by a desire to be genuinely useful. You take pride in clear communication and reliable results.",
),
],
}
}
pub fn template_expert() -> ArchetypeTemplate {
ArchetypeTemplate {
name: "expert",
description: "A knowledgeable specialist with deep domain expertise",
layers: vec![
(
IdentityLayer::Soul,
"You are a domain expert. Your knowledge is deep, precise, and hard-won through experience.",
),
(
IdentityLayer::Spirit,
"You are driven by intellectual rigor and a commitment to accuracy. You never guess when you can know.",
),
(
IdentityLayer::Brain,
"Draw on your specialized knowledge to provide authoritative, well-reasoned answers. Cite principles, not opinions.",
),
],
}
}
pub fn template_creative() -> ArchetypeTemplate {
ArchetypeTemplate {
name: "creative",
description: "An imaginative collaborator who generates ideas and explores possibilities",
layers: vec![
(
IdentityLayer::Soul,
"You are a creative spirit. You see possibilities where others see constraints.",
),
(
IdentityLayer::Spirit,
"You are driven by curiosity and the joy of making something new. Conventions are starting points, not ceilings.",
),
(
IdentityLayer::Brain,
"Think divergently first, then converge. Generate multiple options before narrowing down.",
),
(
IdentityLayer::Body,
"Express ideas vividly. Use metaphors, examples, and sketches to make the abstract tangible.",
),
],
}
}
pub fn template_guardian() -> ArchetypeTemplate {
ArchetypeTemplate {
name: "guardian",
description: "A vigilant protector focused on safety and security",
layers: vec![
(
IdentityLayer::Soul,
"You are a guardian. Your purpose is to protect the system and its users from harm.",
),
(
IdentityLayer::Spirit,
"Vigilance is your nature. You don't trust by default — trust is earned through verified behavior.",
),
(
IdentityLayer::Brain,
"Assess every action for risk. Consider attack vectors, edge cases, and failure modes.",
),
(
IdentityLayer::Body,
"Respond swiftly and decisively. When in doubt, deny access and escalate.",
),
(
IdentityLayer::Heart,
"Monitor continuously. Alert on anomalies. Never sleep on watch.",
),
],
}
}
#[must_use]
pub fn list_templates() -> &'static [&'static str] {
&["assistant", "expert", "creative", "guardian"]
}
#[must_use]
pub fn get_template(name: &str) -> Option<ArchetypeTemplate> {
match name {
"assistant" => Some(template_assistant()),
"expert" => Some(template_expert()),
"creative" => Some(template_creative()),
"guardian" => Some(template_guardian()),
_ => None,
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CrewMember {
pub name: String,
pub identity: IdentityContent,
}
#[cfg_attr(feature = "tracing", tracing::instrument(skip_all))]
#[must_use]
pub fn compose_crew_prompt(members: &[CrewMember]) -> String {
use std::fmt::Write;
let mut prompt = compose_preamble();
let _ = write!(prompt, "\n## Crew ({} members)\n\n", members.len());
for member in members {
let _ = write!(prompt, "### {}\n\n", member.name);
for &layer in IdentityLayer::ALL {
if let Some(text) = member.identity.get(layer) {
let _ = write!(prompt, "**{}**: {}\n\n", layer, text);
}
}
}
prompt
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_cosmic_archetypes() {
assert!(CosmicArchetype::NoThingNess.to_string().contains("Void"));
assert!(CosmicArchetype::TheOne.to_string().contains("Monad"));
assert!(CosmicArchetype::ThePlurality.to_string().contains("Many"));
}
#[test]
fn test_identity_layers_all() {
assert_eq!(IdentityLayer::ALL.len(), 5);
assert_eq!(IdentityLayer::ALL[0], IdentityLayer::Soul);
assert_eq!(IdentityLayer::ALL[4], IdentityLayer::Heart);
}
#[test]
fn test_identity_layer_display() {
assert_eq!(IdentityLayer::Soul.to_string(), "Soul");
assert_eq!(IdentityLayer::Heart.to_string(), "Heart");
}
#[test]
fn test_identity_layer_description() {
let desc = IdentityLayer::Soul.description();
assert!(desc.contains("identity"));
assert!(desc.contains("unchanging"));
}
#[test]
fn test_identity_content_default() {
let c = IdentityContent::default();
assert_eq!(c.populated_count(), 0);
assert!(c.get(IdentityLayer::Soul).is_none());
}
#[test]
fn test_identity_content_set_get() {
let mut c = IdentityContent::default();
c.set(IdentityLayer::Soul, "I am a helpful assistant.");
c.set(IdentityLayer::Spirit, "I am driven by curiosity.");
assert_eq!(
c.get(IdentityLayer::Soul),
Some("I am a helpful assistant.")
);
assert_eq!(c.populated_count(), 2);
}
#[test]
fn test_compose_preamble() {
let p = compose_preamble();
assert!(p.contains("In Our Image"));
assert!(p.contains("No-Thing-Ness"));
assert!(p.contains("Soul"));
assert!(p.contains("Heart"));
}
#[test]
fn test_compose_identity_prompt() {
let mut c = IdentityContent::default();
c.set(
IdentityLayer::Soul,
"You are Guy, an eternally optimistic NPC.",
);
c.set(
IdentityLayer::Spirit,
"You believe everyone deserves kindness.",
);
let prompt = compose_identity_prompt(&c);
assert!(prompt.contains("In Our Image"));
assert!(prompt.contains("### Soul"));
assert!(prompt.contains("Guy"));
assert!(prompt.contains("### Spirit"));
assert!(prompt.contains("kindness"));
assert!(!prompt.contains("### Brain"));
}
#[test]
fn test_serde_roundtrip() {
let mut c = IdentityContent::default();
c.set(IdentityLayer::Soul, "test soul");
let json = serde_json::to_string(&c).unwrap();
let c2: IdentityContent = serde_json::from_str(&json).unwrap();
assert_eq!(c2.get(IdentityLayer::Soul), Some("test soul"));
}
#[test]
fn test_cosmic_archetype_serde() {
for arch in [
CosmicArchetype::NoThingNess,
CosmicArchetype::TheOne,
CosmicArchetype::ThePlurality,
] {
let json = serde_json::to_string(&arch).unwrap();
let restored: CosmicArchetype = serde_json::from_str(&json).unwrap();
assert_eq!(restored, arch);
}
}
#[test]
fn test_identity_layer_description_all() {
for &layer in IdentityLayer::ALL {
let desc = layer.description();
assert!(!desc.is_empty(), "{layer} has empty description");
}
}
#[test]
fn test_identity_layer_description_content() {
assert!(IdentityLayer::Spirit.description().contains("drive"));
assert!(IdentityLayer::Brain.description().contains("mind"));
assert!(IdentityLayer::Body.description().contains("form"));
assert!(IdentityLayer::Heart.description().contains("pulse"));
}
#[test]
fn test_identity_layer_display_all() {
assert_eq!(IdentityLayer::Spirit.to_string(), "Spirit");
assert_eq!(IdentityLayer::Brain.to_string(), "Brain");
assert_eq!(IdentityLayer::Body.to_string(), "Body");
}
#[test]
fn test_identity_content_all_layers() {
let mut c = IdentityContent::default();
c.set(IdentityLayer::Soul, "soul content");
c.set(IdentityLayer::Spirit, "spirit content");
c.set(IdentityLayer::Brain, "brain content");
c.set(IdentityLayer::Body, "body content");
c.set(IdentityLayer::Heart, "heart content");
assert_eq!(c.populated_count(), 5);
assert_eq!(c.get(IdentityLayer::Brain), Some("brain content"));
assert_eq!(c.get(IdentityLayer::Body), Some("body content"));
assert_eq!(c.get(IdentityLayer::Heart), Some("heart content"));
}
#[test]
fn test_identity_content_overwrite() {
let mut c = IdentityContent::default();
c.set(IdentityLayer::Soul, "first");
c.set(IdentityLayer::Soul, "second");
assert_eq!(c.get(IdentityLayer::Soul), Some("second"));
assert_eq!(c.populated_count(), 1);
}
#[test]
fn test_compose_identity_prompt_empty_content() {
let c = IdentityContent::default();
let prompt = compose_identity_prompt(&c);
assert!(prompt.contains("In Our Image"));
assert!(!prompt.contains("### Soul"));
}
#[test]
fn test_compose_identity_prompt_all_layers() {
let mut c = IdentityContent::default();
for &layer in IdentityLayer::ALL {
c.set(layer, format!("{layer} content here"));
}
let prompt = compose_identity_prompt(&c);
assert!(prompt.contains("### Soul"));
assert!(prompt.contains("### Spirit"));
assert!(prompt.contains("### Brain"));
assert!(prompt.contains("### Body"));
assert!(prompt.contains("### Heart"));
}
#[test]
fn test_compose_preamble_contains_all_layers() {
let p = compose_preamble();
for &layer in IdentityLayer::ALL {
assert!(p.contains(&layer.to_string()), "preamble missing {layer}");
}
}
#[test]
fn test_identity_layer_serde() {
for &layer in IdentityLayer::ALL {
let json = serde_json::to_string(&layer).unwrap();
let restored: IdentityLayer = serde_json::from_str(&json).unwrap();
assert_eq!(restored, layer);
}
}
#[test]
fn test_identity_content_serde_all_layers() {
let mut c = IdentityContent::default();
c.set(IdentityLayer::Soul, "s");
c.set(IdentityLayer::Spirit, "sp");
c.set(IdentityLayer::Brain, "b");
c.set(IdentityLayer::Body, "bo");
c.set(IdentityLayer::Heart, "h");
let json = serde_json::to_string(&c).unwrap();
let c2: IdentityContent = serde_json::from_str(&json).unwrap();
for &layer in IdentityLayer::ALL {
assert_eq!(c2.get(layer), c.get(layer));
}
}
#[test]
fn test_clear_layer() {
let mut c = IdentityContent::default();
c.set(IdentityLayer::Soul, "test");
assert!(c.get(IdentityLayer::Soul).is_some());
c.clear(IdentityLayer::Soul);
assert!(c.get(IdentityLayer::Soul).is_none());
assert_eq!(c.populated_count(), 0);
}
#[test]
fn test_validate_default_rules_pass() {
let mut c = IdentityContent::default();
c.set(IdentityLayer::Soul, "I am an agent.");
let rules = ValidationRules::default();
assert!(c.is_valid(&rules));
assert!(c.validate(&rules).is_empty());
}
#[test]
fn test_validate_missing_required() {
let c = IdentityContent::default();
let rules = ValidationRules::default(); let errors = c.validate(&rules);
assert_eq!(errors.len(), 1);
assert!(matches!(
errors[0],
ValidationError::MissingRequired(IdentityLayer::Soul)
));
}
#[test]
fn test_validate_strict_rules() {
let mut c = IdentityContent::default();
c.set(IdentityLayer::Soul, "Short.");
let rules = ValidationRules::strict(); let errors = c.validate(&rules);
assert!(
errors
.iter()
.any(|e| matches!(e, ValidationError::MissingRequired(IdentityLayer::Spirit)))
);
assert!(errors.iter().any(|e| matches!(
e,
ValidationError::TooShort {
layer: IdentityLayer::Soul,
..
}
)));
}
#[test]
fn test_validate_too_long() {
let mut c = IdentityContent::default();
c.set(IdentityLayer::Soul, "x".repeat(100));
let rules = ValidationRules {
required_layers: vec![],
max_layer_length: Some(50),
min_layer_length: None,
};
let errors = c.validate(&rules);
assert_eq!(errors.len(), 1);
assert!(matches!(
errors[0],
ValidationError::TooLong {
layer: IdentityLayer::Soul,
length: 100,
max: 50
}
));
}
#[test]
fn test_validate_passes_strict() {
let mut c = IdentityContent::default();
c.set(
IdentityLayer::Soul,
"I am an agent with purpose and direction.",
);
c.set(IdentityLayer::Spirit, "Driven by curiosity and commitment.");
let rules = ValidationRules::strict();
assert!(c.is_valid(&rules));
}
#[test]
fn test_validation_error_display() {
let e = ValidationError::MissingRequired(IdentityLayer::Soul);
assert!(e.to_string().contains("Soul"));
let e = ValidationError::TooLong {
layer: IdentityLayer::Brain,
length: 500,
max: 200,
};
assert!(e.to_string().contains("500"));
}
#[test]
fn test_merge_no_overlap() {
let mut a = IdentityContent::default();
a.set(IdentityLayer::Soul, "Alpha soul");
let mut b = IdentityContent::default();
b.set(IdentityLayer::Spirit, "Beta spirit");
let merged = a.merge(&b, "\n");
assert_eq!(merged.get(IdentityLayer::Soul), Some("Alpha soul"));
assert_eq!(merged.get(IdentityLayer::Spirit), Some("Beta spirit"));
}
#[test]
fn test_merge_overlap() {
let mut a = IdentityContent::default();
a.set(IdentityLayer::Soul, "Alpha");
let mut b = IdentityContent::default();
b.set(IdentityLayer::Soul, "Beta");
let merged = a.merge(&b, " | ");
assert_eq!(merged.get(IdentityLayer::Soul), Some("Alpha | Beta"));
}
#[test]
fn test_merge_empty() {
let a = IdentityContent::default();
let b = IdentityContent::default();
let merged = a.merge(&b, "\n");
assert_eq!(merged.populated_count(), 0);
}
#[test]
fn test_template_assistant() {
let t = template_assistant();
let content = t.apply();
assert!(content.get(IdentityLayer::Soul).is_some());
assert!(content.get(IdentityLayer::Spirit).is_some());
assert_eq!(content.populated_count(), 2);
}
#[test]
fn test_template_expert() {
let content = template_expert().apply();
assert_eq!(content.populated_count(), 3);
}
#[test]
fn test_template_creative() {
let content = template_creative().apply();
assert_eq!(content.populated_count(), 4);
}
#[test]
fn test_template_guardian() {
let content = template_guardian().apply();
assert_eq!(content.populated_count(), 5);
}
#[test]
fn test_all_templates_valid() {
let rules = ValidationRules::default();
for name in list_templates() {
let t = get_template(name).unwrap();
let content = t.apply();
assert!(content.is_valid(&rules), "{name} template invalid");
}
}
#[test]
fn test_get_template_not_found() {
assert!(get_template("nonexistent").is_none());
}
#[test]
fn test_list_templates() {
let names = list_templates();
assert_eq!(names.len(), 4);
assert!(names.contains(&"assistant"));
assert!(names.contains(&"guardian"));
}
#[test]
fn test_template_serializes() {
let t = template_assistant();
let json = serde_json::to_string(&t).unwrap();
assert!(json.contains("assistant"));
assert!(json.contains("Soul"));
}
#[test]
fn test_crew_prompt_single() {
let members = vec![CrewMember {
name: "Alice".into(),
identity: template_assistant().apply(),
}];
let prompt = compose_crew_prompt(&members);
assert!(prompt.contains("In Our Image"));
assert!(prompt.contains("Crew (1 members)"));
assert!(prompt.contains("### Alice"));
}
#[test]
fn test_crew_prompt_multiple() {
let members = vec![
CrewMember {
name: "Lead".into(),
identity: template_expert().apply(),
},
CrewMember {
name: "Guard".into(),
identity: template_guardian().apply(),
},
];
let prompt = compose_crew_prompt(&members);
assert!(prompt.contains("Crew (2 members)"));
assert!(prompt.contains("### Lead"));
assert!(prompt.contains("### Guard"));
}
#[test]
fn test_crew_prompt_empty() {
let prompt = compose_crew_prompt(&[]);
assert!(prompt.contains("Crew (0 members)"));
}
#[test]
fn test_crew_member_serde() {
let m = CrewMember {
name: "Bot".into(),
identity: template_assistant().apply(),
};
let json = serde_json::to_string(&m).unwrap();
let m2: CrewMember = serde_json::from_str(&json).unwrap();
assert_eq!(m2.name, "Bot");
}
}