symfonic.core.learning.phases_maintenance¶
phases_maintenance ¶
Maintenance consolidation phase implementations.
Phase 8 (Working TTL cleanup) and Phase 9 (Semantic importance decay) live here. These are housekeeping phases that clean up stale data rather than building new structure.
cleanup_working_ttl
async
¶
cleanup_working_ttl(
graph: GraphMemoryStore,
scope: TenantScope,
all_nodes: list[MemoryNode] | None = None,
) -> int
Prune WORKING-layer graph nodes with expired TTL.
Queries all WORKING-layer nodes and deletes those whose
ttl_hours property has elapsed relative to updated_at.
v7.26.2 (Shape C1) adds two durability-aware branches:
durability == "expired"-- pruned unconditionally (the explicit "this transient row served its purpose" signal fromupgrade_durability), bypassing all TTL math.durability == "transient"-- subject to a 1h implicit TTL floor. A transient row with nottl_hoursages out after 1h; a transient row with a longerttl_hoursis capped at 1h (Contract F). This protects against the "still syncing" footgun where a transient row withttl_hours=720would otherwise survive 30 days.
Nodes with no durability marker keep their pre-v7.26.2 behaviour
exactly: pruned only when they carry a ttl_hours that has elapsed.
Returns:
| Type | Description |
|---|---|
int
|
Number of pruned nodes. |
Source code in src/symfonic/core/learning/phases_maintenance.py
decay_importance
async
¶
decay_importance(
graph: GraphMemoryStore,
scope: TenantScope,
all_nodes: list[MemoryNode],
stale_days: int = STALE_DAYS_DEFAULT,
) -> int
Reduce importance of semantic nodes not accessed in stale_days.
Nodes whose updated_at is older than the threshold have their
importance reduced by 0.5, floored at 1.0.
High-signal / identity nodes are EXEMPT from decay so that the user
profile and agent persona are never corrupted by age-based attrition.
See :func:_is_exempt_from_decay for the exemption criteria.
Returns:
| Type | Description |
|---|---|
int
|
Number of decayed nodes. |
Source code in src/symfonic/core/learning/phases_maintenance.py
prune_retracted
async
¶
prune_retracted(
graph: GraphMemoryStore,
scope: TenantScope,
grace_days: int = RETRACTED_GRACE_DAYS_DEFAULT,
) -> int
Hard-delete nodes soft-retracted more than grace_days ago.
A retract_node extraction op flags a false-positive/corrected memory
with the namespaced retraction marker + timestamp (see
symfonic.memory.retraction and SymfonicAgent._retract_memory). The
flag alone removes the node from every read path immediately
(GraphMemoryStore.query_nodes excludes it), but the row lingers for
reversibility/audit. This phase reclaims it once it has been retracted
past the grace window.
Must query with include_retracted=True -- retracted nodes are invisible
to the default read path by design, so a plain scan would never see them.
query_nodes is ancestor-visible (a child scope sees a parent scope's
rows), so an enumerated retracted node may belong to an ANCESTOR scope,
not this one. Only a node materialized at exactly scope is deleted;
ancestor-owned rows are left for the ancestor's own consolidation to
reclaim, otherwise a child's consolidation could hard-delete a parent's
memory.
Returns:
| Type | Description |
|---|---|
int
|
Number of pruned nodes. |