Skip to content

Commit 12930fd

Browse files
committed
feat(memory): auto-register commitment and intention notes as prospective items
Observer commitment notes (importance >= 0.5) are now automatically registered with ProspectiveMemoryManager using heuristic trigger type inference (time_based, event_based, context_based). Future-oriented preference notes also register as low-priority context-based items. Trigger type inference uses regex patterns for temporal and event language without LLM calls.
1 parent 1c1691a commit 12930fd

1 file changed

Lines changed: 107 additions & 0 deletions

File tree

src/memory/CognitiveMemoryManager.ts

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -622,10 +622,87 @@ export class CognitiveMemoryManager implements ICognitiveMemoryManager {
622622
return assembleMemoryContext(input);
623623
}
624624

625+
// =========================================================================
626+
// Prospective auto-registration helpers
627+
// =========================================================================
628+
629+
/**
630+
* Temporal patterns for extracting time-based triggers from observation notes.
631+
* Matches relative expressions ("tomorrow", "next Friday", "in 2 hours")
632+
* and absolute expressions ("on March 5th", "at 3pm").
633+
*/
634+
private static readonly TEMPORAL_PATTERNS = [
635+
/\b(tomorrow|tonight|next\s+(week|month|monday|tuesday|wednesday|thursday|friday|saturday|sunday))\b/i,
636+
/\b(in\s+\d+\s+(hours?|days?|weeks?|minutes?))\b/i,
637+
/\b(on\s+(january|february|march|april|may|june|july|august|september|october|november|december)\s+\d+)/i,
638+
/\b(at\s+\d{1,2}(:\d{2})?\s*(am|pm)?)\b/i,
639+
/\b(\d{4}-\d{2}-\d{2})\b/,
640+
];
641+
642+
/**
643+
* Event-based patterns for extracting event triggers from observation notes.
644+
* Matches conditional language ("when X happens", "after the meeting").
645+
*/
646+
private static readonly EVENT_PATTERNS = [
647+
/\bwhen\s+(.{3,40}?)\s*(happens?|occurs?|starts?|ends?|finishes?|completes?)\b/i,
648+
/\bafter\s+(the\s+)?(.{3,30})\b/i,
649+
/\bonce\s+(.{3,30})\s+(is|are|has|have)\b/i,
650+
];
651+
652+
/**
653+
* Infer the prospective trigger type from an observation note's content.
654+
* Uses regex heuristics — no LLM call needed.
655+
*
656+
* Priority: temporal patterns (most specific) → event patterns → context-based fallback.
657+
*
658+
* @param note - The observation note to classify
659+
* @returns The most likely trigger type for ProspectiveMemoryManager
660+
*/
661+
private inferTriggerType(note: ObservationNote): 'time_based' | 'event_based' | 'context_based' {
662+
for (const pattern of CognitiveMemoryManager.TEMPORAL_PATTERNS) {
663+
if (pattern.test(note.content)) return 'time_based';
664+
}
665+
for (const pattern of CognitiveMemoryManager.EVENT_PATTERNS) {
666+
if (pattern.test(note.content)) return 'event_based';
667+
}
668+
// Default: context-based — fires when topic becomes relevant via embedding similarity
669+
return 'context_based';
670+
}
671+
672+
/**
673+
* Extract an event cue string from "when X" / "after X" patterns.
674+
* Returns undefined if no event language is detected.
675+
*
676+
* @param note - The observation note to extract from
677+
* @returns Event cue string, or undefined
678+
*/
679+
private extractEventCue(note: ObservationNote): string | undefined {
680+
for (const pattern of CognitiveMemoryManager.EVENT_PATTERNS) {
681+
const match = note.content.match(pattern);
682+
if (match) return match[1] ?? match[2];
683+
}
684+
return undefined;
685+
}
686+
625687
// =========================================================================
626688
// Batch 2: Observer
627689
// =========================================================================
628690

691+
/**
692+
* Feed a conversation message to the observation pipeline.
693+
*
694+
* Pipeline flow:
695+
* 1. Observer extracts typed observation notes from buffered messages
696+
* 2. Notes are fed to the Reflector for consolidation into long-term traces
697+
* 3. Reflected traces are encoded via `encode()` (typed as semantic/episodic/etc.)
698+
* 4. Superseded traces are soft-deleted
699+
* 5. Commitment and intention notes are auto-registered with ProspectiveMemoryManager
700+
*
701+
* @param role - Message role (user, assistant, system, tool)
702+
* @param content - Message text content
703+
* @param mood - Optional PAD emotional state at observation time
704+
* @returns Observation notes if threshold was reached, null otherwise
705+
*/
629706
async observe(
630707
role: 'user' | 'assistant' | 'system' | 'tool',
631708
content: string,
@@ -664,6 +741,36 @@ export class CognitiveMemoryManager implements ICognitiveMemoryManager {
664741
}
665742
}
666743

744+
// Auto-register commitment and intention notes as prospective memory items.
745+
// Commitment notes above 0.5 importance represent real intentions, not hedging
746+
// ("maybe I'll..." vs "I will..."). Preference notes expressing future desire
747+
// also register as low-priority context-based items so they surface naturally
748+
// when the topic comes up again.
749+
if (notes && notes.length > 0 && this.prospective) {
750+
for (const note of notes) {
751+
const isCommitment = note.type === 'commitment' && note.importance >= 0.5;
752+
const isFuturePreference = note.type === 'preference' && note.importance >= 0.6
753+
&& /\b(love to|want to|been meaning to|plan to|going to|hope to)\b/i.test(note.content);
754+
755+
if (isCommitment || isFuturePreference) {
756+
const triggerType = this.inferTriggerType(note);
757+
try {
758+
await this.prospective.register({
759+
content: note.content,
760+
triggerType,
761+
triggerEvent: triggerType === 'event_based' ? this.extractEventCue(note) : undefined,
762+
cueText: note.content,
763+
// Future preferences get a lower importance than explicit commitments
764+
importance: isFuturePreference ? note.importance * 0.7 : note.importance,
765+
recurring: false,
766+
});
767+
} catch {
768+
// Prospective registration is non-critical — don't fail the observe() call
769+
}
770+
}
771+
}
772+
}
773+
667774
return notes;
668775
}
669776

0 commit comments

Comments
 (0)