You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The capacity path and the two protection settings it bypasses can be summarized as follows:
flowchart TD
Update["Memory update is applied"] --> Append["Append eligible new facts"]
Append --> Over{"len(facts) > max_facts?"}
Over -- "No" --> Persist["Persist current facts"]
Over -- "Yes" --> Trim["_trim_facts_to_max"]
Trim --> Rank["Sort by confidence descending"]
Rank --> Keep["Keep first max_facts entries"]
Rank --> Drop["Omit lower-confidence entries"]
Keep --> Persist
Drop --> DeleteSet["Convert missing fact IDs to deletes"]
DeleteSet --> Unlink["Physically unlink fact files"]
Injection["Injection: correction has a guaranteed 500-token budget"]
Staleness["Staleness review: correction is protected by default"]
Injection -. "not consulted" .-> Trim
Staleness -. "not consulted" .-> Trim
Loading
Why this is a problem
Consider a store that is already at its fact limit. A fact with confidence 0.9 that has not been confirmed for 180 days will outrank and survive over a fact with confidence 0.7 that the user confirmed seven days ago. The recently confirmed fact is removed from persisted memory because confidence is the only eviction key, even though its recency may make it more useful.
Category importance can be lost in the same way. A correction fact can be pushed out by enough higher-confidence preference facts. Once the correction has been removed, its guaranteed injection budget cannot help because it is no longer present to inject.
Physical removal also makes an incorrect eviction difficult to inspect or reverse. The capacity-trim path does not write a durable eviction record showing which fact was evicted, why it lost the ranking, or how to restore it.
Proposed directions
I would appreciate maintainer guidance on one or a combination of these directions:
Use a composite eviction score that combines confidence with recency decay, based on updatedAt or a dedicated last-confirmed timestamp.
Add protected categories or per-category quotas so facts such as correction are not the first capacity-eviction candidates. This could reuse or align with the existing guaranteed/staleness category settings.
Replace capacity eviction with soft deletion, or at minimum write an audit log containing the evicted fact, timestamp, reason, and ranking inputs so the decision is recoverable and auditable.
I am willing to submit a PR once maintainers agree on the preferred direction.
Current behavior
As of
mainat commit8234370a6ad2abd83bdba35271b902aa0bd19d47:backend/packages/harness/deerflow/agents/memory/backends/deermem/deermem/config.py:88)._trim_facts_to_maxsorts all facts by confidence in descending order and keeps the firstmax_factsentries (backend/packages/harness/deerflow/agents/memory/backends/deermem/deermem/core/updater.py:75,updater.py:88). The updater applies this trim after appending new facts (updater.py:1829,updater.py:1833). The ranking does not useupdatedAt, a last-confirmed timestamp, category quotas, or another diversity signal.createdAtandupdatedAtmetadata (backend/packages/harness/deerflow/agents/memory/backends/deermem/deermem/core/storage.py:228,storage.py:248), but the fact schema only acceptsstatus: "active"and explicitly describes deletion as physical (storage.py:203,storage.py:205). The persistence path turns facts omitted from the updated snapshot into deletes (backend/packages/harness/deerflow/agents/memory/backends/deermem/deermem/core/updater.py:1252,updater.py:1257), and storage unlinks their fact files (storage.py:831,storage.py:832). Capacity-evicted facts therefore have no archived state or restore path.correctionis the default guaranteed category with a separate 500-token budget (backend/packages/harness/deerflow/agents/memory/backends/deermem/deermem/config.py:106,config.py:110), and the prompt formatter selects guaranteed facts separately from regular facts (backend/packages/harness/deerflow/agents/memory/backends/deermem/deermem/core/prompt.py:607,prompt.py:625). The separate staleness-review path also protectscorrectionby default (config.py:139,backend/packages/harness/deerflow/agents/memory/backends/deermem/deermem/core/updater.py:571,updater.py:577). However, the capacity trim does not consult either protection setting, so capacity governance is not aligned with injection or staleness governance.The capacity path and the two protection settings it bypasses can be summarized as follows:
flowchart TD Update["Memory update is applied"] --> Append["Append eligible new facts"] Append --> Over{"len(facts) > max_facts?"} Over -- "No" --> Persist["Persist current facts"] Over -- "Yes" --> Trim["_trim_facts_to_max"] Trim --> Rank["Sort by confidence descending"] Rank --> Keep["Keep first max_facts entries"] Rank --> Drop["Omit lower-confidence entries"] Keep --> Persist Drop --> DeleteSet["Convert missing fact IDs to deletes"] DeleteSet --> Unlink["Physically unlink fact files"] Injection["Injection: correction has a guaranteed 500-token budget"] Staleness["Staleness review: correction is protected by default"] Injection -. "not consulted" .-> Trim Staleness -. "not consulted" .-> TrimWhy this is a problem
Consider a store that is already at its fact limit. A fact with confidence
0.9that has not been confirmed for 180 days will outrank and survive over a fact with confidence0.7that the user confirmed seven days ago. The recently confirmed fact is removed from persisted memory because confidence is the only eviction key, even though its recency may make it more useful.Category importance can be lost in the same way. A
correctionfact can be pushed out by enough higher-confidencepreferencefacts. Once the correction has been removed, its guaranteed injection budget cannot help because it is no longer present to inject.Physical removal also makes an incorrect eviction difficult to inspect or reverse. The capacity-trim path does not write a durable eviction record showing which fact was evicted, why it lost the ranking, or how to restore it.
Proposed directions
I would appreciate maintainer guidance on one or a combination of these directions:
updatedAtor a dedicated last-confirmed timestamp.correctionare not the first capacity-eviction candidates. This could reuse or align with the existing guaranteed/staleness category settings.I am willing to submit a PR once maintainers agree on the preferred direction.