Spaces:
Running on Zero
Running on Zero
| """ | |
| Cocoon Schema v2 — Living Memory Kernel, Codette RC+xi Framework | |
| Upgrades over v1 (plain dict cocoons): | |
| - Typed dataclass with all fields required or defaulted | |
| - Retrieval index fields: problem_type, user_preferences_inferred, project_context | |
| - Contradiction tracking: contradicts_cocoon_ids | |
| - Follow-up hooks: open_threads list for continuity | |
| - Perspective audit: which perspectives were active and which dominated | |
| - Confidence and verifiability flags | |
| - Helper method: relevance_score() for retrieval ranking | |
| Usage: | |
| from reasoning_forge.cocoon_schema_v2 import Cocoon, build_cocoon | |
| """ | |
| from __future__ import annotations | |
| import hashlib | |
| import time | |
| from dataclasses import dataclass, field | |
| from typing import Optional | |
| # Valid emotional valences as defined in the Living Memory Kernel spec | |
| VALID_VALENCES = frozenset([ | |
| "curiosity", "awe", "joy", "insight", "confusion", | |
| "frustration", "fear", "empathy", "determination", | |
| "surprise", "trust", "gratitude", | |
| ]) | |
| # Valid problem type categories | |
| VALID_PROBLEM_TYPES = frozenset([ | |
| "architectural", # system/software design decisions | |
| "ethical", # value conflicts, governance | |
| "technical", # implementation, debugging | |
| "creative", # generative, design, artistic | |
| "analytical", # data, logic, causal reasoning | |
| "relational", # interpersonal, communication | |
| "strategic", # planning, prioritization | |
| "exploratory", # open-ended inquiry, research | |
| "meta", # reasoning about Codette itself | |
| "unknown", | |
| ]) | |
| class Cocoon: | |
| """A single memory unit stored by the Living Memory Kernel. | |
| Fields are organized into four concern groups: | |
| 1. Identity — what this cocoon is | |
| 2. Content — the actual exchange | |
| 3. Cognitive state — what the reasoning engine was doing | |
| 4. Retrieval — fields that enable smart memory lookup | |
| """ | |
| # ─── Identity ─────────────────────────────────────────────────────────── | |
| cocoon_id: str # SHA-256 of query + timestamp | |
| timestamp: float # Unix epoch | |
| session_id: Optional[str] = None # conversation session identifier | |
| # ─── Content ──────────────────────────────────────────────────────────── | |
| query: str = "" # original user query | |
| response_summary: str = "" # compressed synthesis (< 200 words) | |
| full_response_hash: str = "" # SHA-256 of full response text | |
| # ─── Emotional / importance ────────────────────────────────────────────── | |
| emotional_valence: str = "curiosity" # must be in VALID_VALENCES | |
| importance_score: float = 5.0 # 1.0 – 10.0 | |
| confidence: float = 0.75 # 0.0 – 1.0 synthesis confidence | |
| # ─── Cognitive state at time of storage ───────────────────────────────── | |
| epsilon_value: float = 0.35 # epistemic tension | |
| gamma_coherence: float = 0.72 # ensemble coherence | |
| eta_score: Optional[float] = None # AEGIS ethical alignment | |
| active_perspectives: list[str] = field(default_factory=list) | |
| dominant_perspective: Optional[str] = None # perspective with highest signal | |
| unresolved_tensions: list[str] = field(default_factory=list) | |
| synthesis_quality: str = "adequate" # 'strong' | 'adequate' | 'partial' | |
| # ─── Retrieval fields ─────────────────────────────────────────────────── | |
| problem_type: str = "unknown" # from VALID_PROBLEM_TYPES | |
| topic_tags: list[str] = field(default_factory=list) # keyword tags | |
| project_context: Optional[str] = None # e.g., 'Codette-Reasoning', 'raiffs-bits' | |
| user_preferences_inferred: dict[str, str] = field(default_factory=dict) | |
| # e.g., {"detail_level": "high", "tone": "direct", "domain": "AI architecture"} | |
| # ─── Continuity ───────────────────────────────────────────────────────── | |
| open_threads: list[str] = field(default_factory=list) | |
| # Questions or decisions that were NOT resolved — follow-up hooks | |
| # e.g., ["Does synthesis_engine v2 handle all 8 perspectives?", | |
| # "Need to test cocoon retrieval with semantic search"] | |
| contradicts_cocoon_ids: list[str] = field(default_factory=list) | |
| # IDs of prior cocoons this cocoon's conclusion conflicts with | |
| references_cocoon_ids: list[str] = field(default_factory=list) | |
| # IDs of prior cocoons this cocoon builds on | |
| # ─── Quality flags ────────────────────────────────────────────────────── | |
| is_hallucination_flagged: bool = False | |
| is_sycophancy_flagged: bool = False | |
| is_verified: bool = False # True if response was externally verified | |
| def validate(self) -> list[str]: | |
| """Return a list of validation errors (empty list = valid).""" | |
| errors = [] | |
| if self.emotional_valence not in VALID_VALENCES: | |
| errors.append(f"Invalid valence: {self.emotional_valence!r}. Must be one of {sorted(VALID_VALENCES)}") | |
| if not 1.0 <= self.importance_score <= 10.0: | |
| errors.append(f"importance_score {self.importance_score} out of range [1, 10]") | |
| if not 0.0 <= self.confidence <= 1.0: | |
| errors.append(f"confidence {self.confidence} out of range [0, 1]") | |
| if not 0.0 <= self.epsilon_value <= 1.0: | |
| errors.append(f"epsilon_value {self.epsilon_value} out of range [0, 1]") | |
| if not 0.0 <= self.gamma_coherence <= 1.0: | |
| errors.append(f"gamma_coherence {self.gamma_coherence} out of range [0, 1]") | |
| if self.problem_type not in VALID_PROBLEM_TYPES: | |
| errors.append(f"Invalid problem_type: {self.problem_type!r}. Must be one of {sorted(VALID_PROBLEM_TYPES)}") | |
| if self.synthesis_quality not in ("strong", "adequate", "partial"): | |
| errors.append(f"Invalid synthesis_quality: {self.synthesis_quality!r}") | |
| return errors | |
| def relevance_score( | |
| self, | |
| query_keywords: list[str], | |
| current_project: Optional[str] = None, | |
| recency_weight: float = 0.2, | |
| ) -> float: | |
| """Score this cocoon's retrieval relevance to a new query. | |
| Higher = more relevant. Used by the memory kernel for ranked recall. | |
| Args: | |
| query_keywords: Lowercased keyword list from the incoming query. | |
| current_project: Active project context, if any. | |
| recency_weight: How much to weight recency vs. importance (0-1). | |
| Returns: | |
| Relevance score (unbounded, higher is better). | |
| """ | |
| score = 0.0 | |
| # Tag overlap | |
| tags_lower = [t.lower() for t in self.topic_tags] | |
| for kw in query_keywords: | |
| if any(kw in tag for tag in tags_lower): | |
| score += 1.5 | |
| if kw in self.query.lower(): | |
| score += 1.0 | |
| # Project match bonus | |
| if current_project and self.project_context == current_project: | |
| score += 2.0 | |
| # Importance weight | |
| score += self.importance_score * 0.3 | |
| # Recency weight (decay over ~30 days) | |
| age_days = (time.time() - self.timestamp) / 86400 | |
| recency = max(0.0, 1.0 - age_days / 30) | |
| score += recency * recency_weight * 5.0 | |
| # Quality penalty | |
| if self.synthesis_quality == "partial": | |
| score *= 0.6 | |
| elif self.synthesis_quality == "strong": | |
| score *= 1.15 | |
| # Penalize flagged cocoons | |
| if self.is_hallucination_flagged or self.is_sycophancy_flagged: | |
| score *= 0.4 | |
| return score | |
| def to_retrieval_summary(self) -> str: | |
| """Compact string for memory search display.""" | |
| tags = ", ".join(self.topic_tags[:5]) if self.topic_tags else "(no tags)" | |
| threads = " | ".join(self.open_threads[:2]) if self.open_threads else "none" | |
| return ( | |
| f"[{self.cocoon_id[:8]}] {self.query[:60]}… " | |
| f"| type={self.problem_type} | ε={self.epsilon_value:.2f} " | |
| f"| importance={self.importance_score:.1f} | valence={self.emotional_valence} " | |
| f"| tags=[{tags}] | open_threads=[{threads}]" | |
| ) | |
| def build_cocoon( | |
| query: str, | |
| response_text: str, | |
| response_summary: str, | |
| emotional_valence: str = "curiosity", | |
| importance_score: float = 5.0, | |
| epsilon_value: float = 0.35, | |
| gamma_coherence: float = 0.72, | |
| active_perspectives: Optional[list[str]] = None, | |
| dominant_perspective: Optional[str] = None, | |
| unresolved_tensions: Optional[list[str]] = None, | |
| synthesis_quality: str = "adequate", | |
| problem_type: str = "unknown", | |
| topic_tags: Optional[list[str]] = None, | |
| project_context: Optional[str] = None, | |
| user_preferences_inferred: Optional[dict[str, str]] = None, | |
| open_threads: Optional[list[str]] = None, | |
| contradicts_cocoon_ids: Optional[list[str]] = None, | |
| references_cocoon_ids: Optional[list[str]] = None, | |
| eta_score: Optional[float] = None, | |
| confidence: float = 0.75, | |
| session_id: Optional[str] = None, | |
| ) -> Cocoon: | |
| """Factory function that builds and validates a Cocoon. | |
| Raises ValueError if validation fails. | |
| """ | |
| ts = time.time() | |
| cocoon_id = hashlib.sha256(f"{query}{ts}".encode()).hexdigest() | |
| full_hash = hashlib.sha256(response_text.encode()).hexdigest() | |
| # Auto-tag from query words if no tags provided | |
| if topic_tags is None: | |
| import re | |
| words = re.findall(r'\b[a-zA-Z][a-zA-Z]{3,}\b', query.lower()) | |
| stop = {"this", "that", "with", "from", "have", "what", "when", "where", "which", "will", "been"} | |
| topic_tags = [w for w in dict.fromkeys(words) if w not in stop][:8] | |
| cocoon = Cocoon( | |
| cocoon_id=cocoon_id, | |
| timestamp=ts, | |
| session_id=session_id, | |
| query=query, | |
| response_summary=response_summary, | |
| full_response_hash=full_hash, | |
| emotional_valence=emotional_valence, | |
| importance_score=float(importance_score), | |
| confidence=confidence, | |
| epsilon_value=epsilon_value, | |
| gamma_coherence=gamma_coherence, | |
| eta_score=eta_score, | |
| active_perspectives=active_perspectives or [], | |
| dominant_perspective=dominant_perspective, | |
| unresolved_tensions=unresolved_tensions or [], | |
| synthesis_quality=synthesis_quality, | |
| problem_type=problem_type, | |
| topic_tags=topic_tags, | |
| project_context=project_context, | |
| user_preferences_inferred=user_preferences_inferred or {}, | |
| open_threads=open_threads or [], | |
| contradicts_cocoon_ids=contradicts_cocoon_ids or [], | |
| references_cocoon_ids=references_cocoon_ids or [], | |
| ) | |
| errors = cocoon.validate() | |
| if errors: | |
| raise ValueError(f"Cocoon validation failed: {errors}") | |
| return cocoon | |