Skip to main content

How Decisions Become Network State

CU-IP, the Intelligence Plane, emits decisions: a PCI to assign, a neighbor relation to add or remove. Nothing acts on a decision but the controller, and this page is what it does with one. The Intelligence Functions themselves are on the CU-IP page; their tuning is chart values under racora-cu.cuIp.

The Loop​

Every NRCell has its own timer, firing every racora-controller.decisions.pollIntervalS (default 1 s). Each tick fetches CU-IP's active decisions over its Flight endpoint (/decisions/active), keeps the ones aimed at this cell, and dispatches each by its function (pci, anr) and the spec field it targets. The routing is function-agnostic; what differs per function is data, described below.

The Gates​

A decision is applied only when every gate passes on this tick. Each has a name that appears in the controller's log, and as the dispatch.outcome attribute of the dispatch.consider span once the decision reaches the live re-check (a decision the first quick check skips emits no span):

GateSkips whenOutcome
targetthe decision is not for this cell or its fieldskipped_target_mismatch
stabilizationthe cell's last applied change for this function is younger than decisions.minStabilizationS (default 30 s); PCI falls back to status.pciAssignedAt when no watermark existsskipped_not_stable
freshnessthe decision is older than that last applied change, so it describes the state before itskipped_stale
confidencethe decision's confidence is below decisions.minConfidence (default 0.95; deterministic functions emit 1.0)skipped_low_confidence
verify-current (pci, anr)the live spec value (spec.pci; spec.neighbors, order-insensitive) differs from the current_value the decision was computed from, so a concurrent operator edit is not overwrittenskipped_stale
preconditionthe decision carries a precondition no handler is registered for, or its handler could not satisfy it on this tickskipped_precondition_unsupported, skipped_precondition_failed

decisions.perFunction overrides the stabilization and confidence knobs per function. The stabilization gate also absorbs the re-emission window after an apply: CU-IP keeps emitting the same recommendation until it observes the new spec.

Before and After the Change​

  • Preconditions act. A PCI decision carries cell_locked: the handler sends cell_lock to the CU-CP, which bars the cell, releases its UEs and deactivates it, before the spec is patched. ANR decisions carry no precondition.
  • The patch is an ordinary write to the cell's spec (spec.pci, spec.neighbors), the same field an operator would edit.
  • After the patch, per function: pci rebuilds the DU configuration, so the controller waits for the DU rollout to finish and then sends the explicit cell_unlock. If the cell is declared adminState: Locked, the unlock is withheld and the cell stays down, as declared. anr needs neither: the neighbor change flows to the running CU-CP through the same mobility sync as an operator edit. A function without a registered policy gets nothing extra and a warning in the log.

The Audit Trail​

Every apply stamps status.lastApplied[<function>] with the time and the decision id. That is what the stabilization and freshness gates read back, which is what makes a one-second poll loop single-shot per decision. Functions add their own fields:

  • PCI writes status.lastRetune, sets status.pciSource to controller-retuned and refreshes status.pciAssignedAt.
  • ANR rewrites status.neighbors[] with provenance: every relation carries source: manual|anr and appliedAt.

Both are on kubectl get nrcell <name> -o yaml; the fields are in the NRCell API.

Who Owns a Neighbor Relation​

Provenance decides what ANR may touch:

  • Relations you declare are source: manual. In the default ownership mode, merge-preserve-manual, ANR never removes them, whatever the measurement graph says. ownership: anr-owns-all in the function's configuration (racora-cu.cuIp.engineConfig) opts every relation into ANR's removal logic; ownership: report-only evaluates and logs without acting.
  • Relations ANR adds are source: anr, and only those are subject to its removal logic. Deleting one from the spec yourself removes it, and ANR re-adds it only if the radio evidence still supports it. Re-declaring an ANR-added relation does not adopt it as manual; provenance is one-way.
  • When you edit spec.neighbors directly, the controller refreshes the provenance map: new entries default to manual, existing entries keep their source, entries removed from the spec drop out.
  • Each ANR change lands as one audited decision in status.lastApplied.anr, and reaches the running CU-CP live, without a DU restart.

Turning a function off is dropping it from racora-cu.cuIp.engines (default pci,anr).