CDM logic

The Clinical Decision Module (CDM) is the deterministic decision engine at the core of AEGIS. It takes performance metrics, drift scores, and fixed performance reference comparisons as input and produces a composite output: a decision category and an independent alarm state.

View the CDM Pseudocode Reference

Ternary operator

AEGIS uses a general ternary decision function (Eq. 1 from the manuscript) of the form D = f(C1,...,CN) ? D1 : D2, which maps a set of conditions to one of multiple decision outcomes. Each metric evaluation produces a ternary state:

T(metric, threshold_lower, threshold_upper) =
    FAIL    if metric < threshold_lower
    BUFFER  if threshold_lower <= metric < threshold_upper
    PASS    if metric >= threshold_upper

This ternary logic underpins the CDM's ability to distinguish between outright failure (REJECT), performance buffer (CLINICAL REVIEW), minor drift (CONDITIONAL APPROVAL), and full compliance (APPROVE).

Condition polarity

AEGIS uses a lower-is-worse polarity convention for all metrics by default. This means:

For metrics where higher is worse (e.g., false positive rate, calibration error), you must invert the comparison before entering the CDM. Document the polarity convention for each metric in your S2 configuration.

# Example: inverting a higher-is-worse metric
def normalise_polarity(value, higher_is_worse=False):
    """Convert metric to lower-is-worse convention."""
    if higher_is_worse:
        return 1.0 - value
    return value

Priority-ordered decision hierarchy

The CDM evaluates conditions in strict priority order. The first condition that fires determines the decision. Lower-priority conditions are never evaluated once a higher-priority condition matches.

Priority Label Condition Decision
P1 (highest) Critical safety P_G,k < P^fail REJECT
P2 Performance buffer / regression (P_G,k in R_G) OR (tau < P^ref - P_G,k) CLINICAL REVIEW
P3 Minor drift / TAI concern (S_D in S^minor_D) OR (S_T < S^thr_T) CONDITIONAL APPROVAL
P4 (lowest) Full compliance All checks pass APPROVE

The priority ordering ensures that safety-critical failures are always caught first, regardless of other conditions.

**Sepsis example:** At iteration 7, sensitivity was 0.702 -- above P^fail (0.65) and above R_G(sensitivity) (0.66), but regressed from the fixed performance reference P^ref (0.723). The CDM evaluated as follows: - P1: sensitivity 0.702 >= P^fail 0.65 -- **not triggered** - P2: P^ref - P_G,k = 0.723 - 0.702 = 0.021 > tau 0.015 -- **TRIGGERED** (regression from fixed performance reference) Result: CLINICAL REVIEW with details `{priority: P2, trigger: "P^ref 0.723 - sensitivity 0.702 = 0.021 > tau 0.015"}`. The model was flagged for clinical review due to performance regression.

Alarm conditions (A1--A3)

Alarm conditions operate on an independent channel from the decision hierarchy. They are evaluated for every iteration regardless of the decision outcome.

Alarm Condition What it monitors
A1 P^rel_D < P^PMS Released model on Drifting set below PMS safety floor
A2 P^rel_D <= P^rel_G - tau Released model regressed from released performance reference
A3 S_D in S^major_D (drift score > 0.90) Major distributional shift

Key framing: APPROVE + ALARM is not contradictory. This combination means:

For example, at iteration 8 in the sepsis study, the new model passed P4 (APPROVE) but the released model triggered alarm A3 due to drift_score 1.000, exceeding S^major_D = 0.90.

This dual-channel design ensures that PMS obligations are never masked by a successful iteration.

Composite output

The CDM returns a structured object containing both channels:

{
    "decision": "APPROVE",              # from priority hierarchy
    "alarm": True,                       # from alarm channel
    "alarm_conditions": ["A3"],          # which alarms fired
    "details": {
        "priority": "P4",
        "trigger": "All metrics pass all checks"
    }
}

The composite output feeds directly into:

  1. The audit trail (see Audit trail)
  2. PCCP regulatory documentation (see PCCP mapping)
  3. CAPA initiation (if REJECT or ALARM)

Pseudocode

The complete reference implementation follows the priority-ordered evaluation pattern:

def cdm_evaluate(metrics, thresholds, drift_score, gold_standard, config):
    """
    Clinical Decision Module -- priority-ordered evaluation.

    Parameters
    ----------
    metrics : dict          Current iteration metrics
    thresholds : dict       All threshold values from S2 configuration
    drift_score : float     Proportion of features with significant drift
    gold_standard : dict    Gold standard baseline metrics
    config : dict           Active categories and configuration

    Returns
    -------
    dict  {'decision', 'alarm', 'alarm_conditions', 'details'}
    """
    # Alarm channel -- always evaluated
    alarm_conditions = _check_alarm(metrics, thresholds, config)

    # P1: Critical safety floor
    for metric_name, value in metrics.items():
        pfail_key = f'P_fail_{metric_name}'
        if pfail_key in thresholds and value < thresholds[pfail_key]:
            return {
                'decision': 'REJECT',
                'alarm': len(alarm_conditions) > 0,
                'alarm_conditions': alarm_conditions,
                'details': {
                    'priority': 'P1',
                    'trigger': f'{metric_name} = {value:.3f} < P_fail = {thresholds[pfail_key]}'
                }
            }

    # P2: Performance buffer OR regression from fixed performance reference → CLINICAL REVIEW
    if config.get('clinical_review_enabled', True):
        # Check R_G buffer zone
        for metric_name, value in metrics.items():
            rg_key = f'R_G_{metric_name}'
            if rg_key in thresholds and value < thresholds[rg_key]:
                return {
                    'decision': 'CLINICAL REVIEW',
                    'alarm': len(alarm_conditions) > 0,
                    'alarm_conditions': alarm_conditions,
                    'details': {
                        'priority': 'P2',
                        'trigger': f'{metric_name} = {value:.3f} in R_G buffer'
                    }
                }
        # Check regression from fixed performance reference (P^ref)
        tau = thresholds.get('tau', 0.015)
        for metric_name, value in metrics.items():
            if metric_name in gold_standard:
                deviation = gold_standard[metric_name] - value
                if deviation > tau:
                    return {
                        'decision': 'CLINICAL REVIEW',
                        'alarm': len(alarm_conditions) > 0,
                        'alarm_conditions': alarm_conditions,
                        'details': {
                            'priority': 'P2',
                            'trigger': f'P^ref - {metric_name} = {deviation:.3f} > tau = {tau}'
                        }
                    }

    # P3: Minor drift OR TAI concern → CONDITIONAL APPROVAL
    if config.get('conditional_approval_enabled', True):
        minor_low = thresholds.get('S_minor_D_low', 0.30)
        minor_high = thresholds.get('S_minor_D_high', 0.70)
        if minor_low <= drift_score <= minor_high:
            return {
                'decision': 'CONDITIONAL APPROVAL',
                'alarm': len(alarm_conditions) > 0,
                'alarm_conditions': alarm_conditions,
                'details': {
                    'priority': 'P3',
                    'trigger': f'drift = {drift_score:.3f} in S^minor_D [{minor_low}, {minor_high}]'
                }
            }

    # P4: All checks passed
    return {
        'decision': 'APPROVE',
        'alarm': len(alarm_conditions) > 0,
        'alarm_conditions': alarm_conditions,
        'details': {'priority': 'P4', 'trigger': 'All metrics pass all checks'}
    }

Alarm evaluation function

def _check_alarm(metrics, thresholds, config):
    """Check PMS alarm conditions independently of decision hierarchy."""
    alarms = []

    # A1: Released model below PMS safety floor
    released = config.get('released_metrics', {})
    for metric_name, value in released.items():
        pms_key = f'P_PMS_{metric_name}'
        if pms_key in thresholds and value < thresholds[pms_key]:
            alarms.append({
                'id': 'A1',
                'detail': f'Released {metric_name} = {value:.3f} < P_PMS'
            })

    # A2: Released model regressed from released performance reference
    released_golden = config.get('released_golden_metrics', {})
    tau = thresholds.get('tau', 0.015)
    for metric_name, value in released.items():
        if metric_name in released_golden:
            if value <= released_golden[metric_name] - tau:
                alarms.append({
                    'id': 'A2',
                    'detail': f'P^rel_D {value:.3f} <= P^rel_G - tau = {released_golden[metric_name] - tau:.3f}'
                })

    # A3: Major distributional shift (drift score > 0.90)
    drift_score = config.get('current_drift_score', 0.0)
    if drift_score > thresholds.get('S_major_D', 0.90):
        alarms.append({
            'id': 'A3',
            'detail': f'Drift {drift_score:.3f} > theta_major'
        })

    return alarms

Logging specification

Every CDM evaluation must be logged. The required fields are documented in Audit trail. At minimum, each log entry must record:

**Sepsis example:** At iteration 10, the CDM produced the most severe composite output observed in the experiment: REJECT (P1) + ALARM (A3). Sensitivity had dropped to 0.428 (far below P_fail = 0.65) due to catastrophic label corruption (80% positive flip, 30% negative flip) combined with Gaussian noise. Simultaneously, the drift score reached 1.000, exceeding theta_major = 0.90 and firing alarm A3. This composite REJECT + ALARM state triggered immediate CAPA initiation.

Source

Manuscript Section II-B-3 (CDM specification), Tables III and IV (decision categories and priority hierarchy). The ternary decision function is defined as Equation 1. Alarm conditions are specified in Table IV. The reference Python implementation is reproduced from Supplementary S3.3. Sepsis iteration results are in Table VIII.