Graph Decay Manager
Graph DecayManager: the storage-agnostic lifecycle sweep (inherited), plus materialisation of the decayed effectiveConfidence onto :Proposition nodes so confidence-ranked reads push into Neo4j.
Materialisation runs entirely in Neo4j — a MATCH … SET sweep, no store load — because pulling the whole store into the JVM just to recompute a column and write it back is exactly the kind of work a durable backend should push down. The CASE in DECAY_EXPRESSION is a faithful transcript of Proposition.effectiveConfidenceAt at the default decay rate; the parity integration test pins the two together so the Cypher can't drift from the Kotlin definition.
The SET is wrapped in CALL { … } IN TRANSACTIONS so a whole-store sweep commits in batches rather than holding write locks on every :Proposition for one long transaction that competes with concurrent saves. The trade-off is that a mid-sweep failure leaves the column partially refreshed instead of all-or-nothing — harmless for decay, since the stale rows simply carry their old value into the next sweep. (This also means a sweep must run in its own implicit transaction, not inside an enclosing one — DecayManager opens none, and callers must not wrap it in @Transactional.)
Functions
Refresh cached decayed confidence for one context (no-op for non-caching backends).
Refresh cached decayed confidence across all contexts (no-op for non-caching backends).
Sweep the propositions in a single context for lifecycle transitions.
Sweep the propositions across all contexts for lifecycle transitions.
Runner: refresh cached confidence, then apply lifecycle transitions across all contexts.