export class MemoryTurnAccess { constructor() { this.reset(); } reset() { this.searched = false; this.searchResultIds = new Set(); this.readIds = new Set(); } recordSearch(ids) { this.searched = true; for (const id of ids) this.searchResultIds.add(id); } requireSearchedId(id) { if (!this.searched) { throw new Error("Memory workflow blocked: call memory_search in this user turn before reading or mutating memory."); } if (!this.searchResultIds.has(id)) { throw new Error(`Memory workflow blocked: search for the exact concept '${id}' in this user turn first.`); } } recordRead(ids) { for (const id of ids) { this.requireSearchedId(id); this.readIds.add(id); } } requireWrite(id, exists) { if (!this.searched) { throw new Error("Memory workflow blocked: call memory_search for duplicates in this user turn before writing."); } if (!exists) return; this.requireSearchedId(id); if (!this.readIds.has(id)) { throw new Error(`Memory workflow blocked: read existing concept '${id}' in this user turn before updating it.`); } } requireForget(id) { this.requireSearchedId(id); if (!this.readIds.has(id)) { throw new Error(`Memory workflow blocked: read concept '${id}' in this user turn before forgetting it.`); } } }