package ontology import "sync" import "tutor/internal/workflows" type Store interface { Save(Material, []ConceptCandidate, []EdgeCandidate, []Gap) error Snapshot() Snapshot } type MemoryStore struct { mu sync.RWMutex materials []Material concepts []ConceptCandidate edges []EdgeCandidate gaps []Gap } func NewMemoryStore() *MemoryStore { return &MemoryStore{} } func (s *MemoryStore) Save( material Material, concepts []ConceptCandidate, edges []EdgeCandidate, gaps []Gap, ) error { s.mu.Lock() defer s.mu.Unlock() s.materials = append(s.materials, cloneMaterial(material)) s.concepts = append(s.concepts, cloneConcepts(concepts)...) s.edges = append(s.edges, cloneEdges(edges)...) s.gaps = append(s.gaps, cloneGaps(gaps)...) return nil } func (s *MemoryStore) Snapshot() Snapshot { s.mu.RLock() defer s.mu.RUnlock() return Snapshot{ Materials: cloneMaterials(s.materials), Concepts: cloneConcepts(s.concepts), Edges: cloneEdges(s.edges), Gaps: cloneGaps(s.gaps), } } func cloneMaterial(material Material) Material { return material } func cloneMaterials(items []Material) []Material { cloned := make([]Material, len(items)) copy(cloned, items) return cloned } func cloneConcepts(items []ConceptCandidate) []ConceptCandidate { cloned := make([]ConceptCandidate, len(items)) for i, item := range items { cloned[i] = item cloned[i].Evidence = append([]workflows.EvidenceRef(nil), item.Evidence...) } return cloned } func cloneEdges(items []EdgeCandidate) []EdgeCandidate { cloned := make([]EdgeCandidate, len(items)) for i, item := range items { cloned[i] = item cloned[i].Evidence = append([]workflows.EvidenceRef(nil), item.Evidence...) } return cloned } func cloneGaps(items []Gap) []Gap { cloned := make([]Gap, len(items)) for i, item := range items { cloned[i] = item cloned[i].SupportingEvidence = append([]workflows.EvidenceRef(nil), item.SupportingEvidence...) } return cloned }