Skip to content

Promotion Policies

Promotion policies boost an entity's decay score when specific conditions are met. They contain logic: FOR targets, APPLY blocks with ON ACCESS mutations, and WHEN predicates that select promotion profiles.

Architecture

Promotion has two components:

  1. Promotion Profiles — named parameter bundles declaring multiplier, score floor, score cap (no logic, no targets)
  2. Promotion Policies — targeted bindings with FOR, APPLY, ON ACCESS, and WHEN clauses

Creating a Promotion Profile

Promotion profiles contain no logic — they are parameter bundles referenced by name inside promotion policy APPLY blocks:

CREATE PROMOTION PROFILE reinforced_tier OPTIONS {
  multiplier: 1.5,
  scoreFloor: 0.3,
  scoreCap: 1.0
}
Parameter Default Description
multiplier 1.0 Score multiplier. >1.0 boosts, 1.0 is neutral, <1.0 dampens. A multiplier of 0.5 halves the decayed score; combined with an inverted decay profile (negative halfLifeSeconds) this implements "punish frequent access" semantics where hot nodes are demoted. See Inverted Decay.
scoreFloor 0.0 Minimum score AFTER the multiplier is applied. Different from the decay bundle's scoreFloor — this one acts inside the promoted-curve computation (max(promoFloor, base * multiplier)), the bundle's floor acts as the final clamp on the result. Neither is a visibility cutoff; the suppression check is visibilityThreshold on the decay bundle.
scoreCap 1.0 Maximum score after promotion

The decay pipeline is final = max(decayBundle.scoreFloor, min(promoProfile.scoreCap, max(promoProfile.scoreFloor, base * multiplier))), then suppressed = final < decayBundle.visibilityThreshold. The promotion floor only matters when the matching WHEN predicate fires; the decay floor matters always. Pick the right floor for the right job.

Creating a Promotion Policy

CREATE PROMOTION POLICY <name>
FOR (<target>)
APPLY {
  ON ACCESS {
    <mutations>
  }

  WHEN <predicate>
    APPLY PROFILE '<profile_name>'
}

Example: Basic Tiered Promotion

CREATE PROMOTION POLICY session_record_tiering
FOR (n:SessionRecord)
APPLY {
  ON ACCESS {
    SET n.accessCount = coalesce(n.accessCount, 0) + 1
    SET n.lastAccessedAt = timestamp()
  }

  WHEN n.accessCount >= 3
    APPLY PROFILE 'reinforced_tier'

  WHEN n.accessCount >= 5 AND n.sourceAgreement >= 0.95
    APPLY PROFILE 'canonical_tier'
}

Example: Negative Multiplier (Access Dampening)

A multiplier below 1.0 dampens the score for entities that hit a hot-path threshold. Pairs with an inverted decay profile to invert the recency bias: frequently-accessed entries are demoted, idle entries strengthen over time. See the full walkthrough in Inverted Decay.

CREATE PROMOTION PROFILE access_dampener OPTIONS {
  multiplier: 0.5,
  scoreFloor: 0.0,
  scoreCap: 1.0
}

CREATE PROMOTION POLICY hot_path_dampening
FOR (n:Memory)
APPLY {
  ON ACCESS {
    SET n.accessCount = coalesce(n.accessCount, 0) + 1
    SET n.lastAccessedAt = timestamp()
  }
  WHEN n.accessCount >= 5
    APPLY PROFILE 'access_dampener'
}

Example: Kalman-Filtered Behavioral Signals

CREATE PROMOTION POLICY episodic_recall_quality
FOR (n:MemoryEpisode)
APPLY {
  ON ACCESS {
    SET n.accessCount = coalesce(n.accessCount, 0) + 1
    SET n.lastAccessedAt = timestamp()

    WITH KALMAN{q: 0.05, r: 50.0} SET n.confidenceScore = $evaluatedConfidence

    WITH KALMAN SET n.crossSessionAccessRate =
      CASE WHEN n._lastSessionId <> $_session
        THEN coalesce(n.crossSessionAccessRate, 0) + 1
        ELSE n.crossSessionAccessRate
      END
    SET n._lastSessionId = $_session
    SET n._lastAgentId = $_agent
  }

  WHEN n.accessCount >= 5 AND n.confidenceScore >= 0.8
    APPLY PROFILE 'high_confidence_tier'

  WHEN n.accessCount >= 3
    APPLY PROFILE 'reinforced_tier'
}

ON ACCESS Semantics

ON ACCESS mutations execute when the target entity is accessed and passes the suppression gate. Key rules:

  • Mutations apply exclusively to the accessMeta index, never to the target node/edge itself
  • Property reads (e.g., n.accessCount) resolve from accessMeta first, then fall back to stored properties
  • Suppressed entities (score below visibility threshold) do not accumulate access state
  • WHEN predicates read persisted + buffered accessMeta state from prior accesses

WITH KALMAN

The WITH KALMAN clause applies Kalman filtering to smooth behavioral signals:

WITH KALMAN{q: 0.05, r: 50.0} SET n.confidenceScore = $evaluatedConfidence
Parameter Description
q Process noise covariance (how much the true value changes between observations)
r Measurement noise covariance (how noisy observations are)

When q and r are omitted, defaults are used. Kalman filtering is appropriate for derived behavioral metrics (access rates, confidence scores) — not for ground-truth values.

Query Context Variables

ON ACCESS blocks can access query context variables projected from request headers:

Request Header Available As Purpose
X-Query-Session $_session Same-session deduplication
X-Query-Agent $_agent Agent provenance tracking

Listing and Dropping

SHOW PROMOTION POLICIES;
DROP PROMOTION POLICY session_record_tiering;
DROP PROMOTION PROFILE reinforced_tier;

Dropping a promotion profile that is still referenced by an active policy produces a validation error.

See Also