Skip to content

Memory Types

shared.memory_types

Typed memory — 14 categories with per-type retention/decay/boost policy.

14 types: instruction, fact, decision, goal, preference, commitment, relationship, observation, rule, todo, question, hypothesis, context, procedural (S17, ENGRAM: "how to do X" — the data foundation for Stage 2 behavior annotations).

Each type has its own: - default_importance (auto-fill on save) - decay_rate (0 = never decays) - never_archive flag - requires_expires_at flag - boost_on_keywords for retrieval

MemoryKind

Bases: str, Enum

Source code in shared/memory_types.py
class MemoryKind(str, enum.Enum):
    INSTRUCTION = "instruction"
    FACT = "fact"
    DECISION = "decision"
    GOAL = "goal"
    PREFERENCE = "preference"
    COMMITMENT = "commitment"
    RELATIONSHIP = "relationship"
    OBSERVATION = "observation"
    RULE = "rule"
    TODO = "todo"
    QUESTION = "question"
    HYPOTHESIS = "hypothesis"
    CONTEXT = "context"
    PROCEDURAL = "procedural"

get_policy

get_policy(kind)

Get policy for a kind. Unknown kinds fall back to FACT.

Source code in shared/memory_types.py
def get_policy(kind: MemoryKind | str) -> TypePolicy:
    """Get policy for a kind. Unknown kinds fall back to FACT."""
    try:
        k = MemoryKind(kind) if isinstance(kind, str) else kind
    except ValueError:
        k = MemoryKind.FACT
    return _REGISTRY[k]

kind_for_text

kind_for_text(text)

Best-effort heuristic for auto-classification. Returns FACT if nothing matches.

Two gates apply, and they are the whole fix. QUESTION is decided by _is_question and TODO by _is_task_request — by the SHAPE of the text, not by one word appearing in it. Everything else still matches by substring, deliberately.

WHY SUBSTRING IS KEPT. Whole-word matching was tried first, because kw in text is what let "how" match inside "show". Measured against 10404 live rows it also broke Russian inflection and English stems — feminine and prefixed verb forms stopped matching their dictionary keys, and committed stopped matching commit — losing 148 classifications. This house writes in feminine grammatical forms, so a silently became FACT. The semantic gates remove the real defect without that cost, so the blunt instrument was withdrawn.

Returning FACT is not a failure: it is the honest answer for text that matched no pattern, and it costs a coarser retrieval hint. Over-tagging is what this replaces.

Source code in shared/memory_types.py
def kind_for_text(text: str) -> MemoryKind:
    """Best-effort heuristic for auto-classification. Returns FACT if nothing matches.

    Two gates apply, and they are the whole fix. QUESTION is decided by `_is_question`
    and TODO by `_is_task_request` — by the SHAPE of the text, not by one word appearing
    in it. Everything else still matches by substring, deliberately.

    WHY SUBSTRING IS KEPT. Whole-word matching was tried first, because `kw in text`
    is what let "how" match inside "show". Measured against 10404 live rows it also
    broke Russian inflection and English stems — feminine and prefixed verb forms
    stopped matching their dictionary keys, and `committed` stopped matching `commit` —
    losing 148 classifications. This house writes in feminine grammatical forms, so a
    silently became FACT. The semantic gates remove the real defect without that cost,
    so the blunt instrument was withdrawn.

    Returning FACT is not a failure: it is the honest answer for text that matched no
    pattern, and it costs a coarser retrieval hint. Over-tagging is what this replaces.
    """
    tl = text.lower()
    for kind, kws in _KEYWORD_MAP:
        if kind is MemoryKind.QUESTION:
            if _is_question(text):
                return kind
            continue
        if kind is MemoryKind.TODO and _is_task_request(text):
            return kind
        if any(kw in tl for kw in kws):
            return kind
    return MemoryKind.FACT