Files
the-nexus/nexus/mnemosyne/entry.py
Alexander Whitestone 653c20862c feat(mnemosyne): add vitality and last_accessed fields to ArchiveEntry
Part of #1258 — memory decay system.
- vitality: float 0.0-1.0 (default 1.0)
- last_accessed: ISO datetime of last access

Also ensures updated_at and content_hash fields from main are present.
2026-04-12 05:41:42 +00:00

64 lines
2.3 KiB
Python

"""Archive entry model for Mnemosyne.
Each entry is a node in the holographic graph — a piece of meaning
with metadata, content, and links to related entries.
"""
from __future__ import annotations
import hashlib
from dataclasses import dataclass, field
from datetime import datetime, timezone
from typing import Optional
import uuid
def _compute_content_hash(title: str, content: str) -> str:
"""Compute SHA-256 of title+content for deduplication."""
raw = f"{title}\x00{content}".encode("utf-8")
return hashlib.sha256(raw).hexdigest()
@dataclass
class ArchiveEntry:
"""A single node in the Mnemosyne holographic archive."""
id: str = field(default_factory=lambda: str(uuid.uuid4()))
title: str = ""
content: str = ""
source: str = "" # "mempalace", "event", "manual", etc.
source_ref: Optional[str] = None # original MemPalace ID, event URI, etc.
topics: list[str] = field(default_factory=list)
metadata: dict = field(default_factory=dict)
created_at: str = field(default_factory=lambda: datetime.now(timezone.utc).isoformat())
updated_at: Optional[str] = None # Set on mutation; None means same as created_at
links: list[str] = field(default_factory=list) # IDs of related entries
content_hash: Optional[str] = None # SHA-256 of title+content for dedup
vitality: float = 1.0 # 0.0 (dead) to 1.0 (fully alive)
last_accessed: Optional[str] = None # ISO datetime of last access; None = never accessed
def __post_init__(self):
if self.content_hash is None:
self.content_hash = _compute_content_hash(self.title, self.content)
def to_dict(self) -> dict:
return {
"id": self.id,
"title": self.title,
"content": self.content,
"source": self.source,
"source_ref": self.source_ref,
"topics": self.topics,
"metadata": self.metadata,
"created_at": self.created_at,
"updated_at": self.updated_at,
"links": self.links,
"content_hash": self.content_hash,
"vitality": self.vitality,
"last_accessed": self.last_accessed,
}
@classmethod
def from_dict(cls, data: dict) -> ArchiveEntry:
return cls(**{k: v for k, v in data.items() if k in cls.__dataclass_fields__})