# How Ouroboros Drift Detection Measures Goal, Constraint, and Ontology Drift with 50/30/20 Weights

> Learn how Ouroboros Drift Detection measures goal, constraint, and ontology drift using 50/30/20 weights and a 0.3 threshold for early issue detection.

- Repository: [Q00/ouroboros](https://github.com/Q00/ouroboros)
- Tags: deep-dive
- Published: 2026-03-14

---

**Ouroboros Drift Detection calculates a combined deviation score by weighting goal drift at 50%, constraint drift at 30%, and ontology drift at 20%, emitting a `DriftThresholdExceededEvent` when the aggregate exceeds the 0.3 threshold defined in NFR 5.**

Ouroboros Drift Detection is the observability mechanism in the Q00/ouroboros repository that ensures autonomous workflows remain faithful to their immutable Seed specification. By quantifying semantic divergence across three distinct dimensions using a fixed 5/3/2 weighting ratio, the system provides deterministic safeguards against runaway generative behavior.

## The Three Components of Drift Measurement

Ouroboros tracks deviation from the original Seed through three independent metrics, each capturing a specific type of specification violation. These metrics are implemented in [`src/ouroboros/observability/drift.py`](https://github.com/Q00/ouroboros/blob/main/src/ouroboros/observability/drift.py) and aggregated using the prescribed 50/30/20 weight distribution.

### Goal Drift (50% Weight)

**Goal drift** measures the semantic distance between the current generative output and the immutable `goal` string defined in the Seed. The `calculate_goal_drift()` function tokenizes both strings, constructs word sets, and computes **Jaccard similarity**. The final score is calculated as `1 - similarity`, yielding a value between 0 (identical intent) and 1 (completely divergent).

This component receives the highest weight (`GOAL_DRIFT_WEIGHT = 0.5`) because alignment with the core objective is considered the primary fidelity criterion.

### Constraint Drift (30% Weight)

**Constraint drift** quantifies hard boundary violations through the `calculate_constraint_drift()` method. The system multiplies the count of accumulated constraint violations by a fixed penalty factor of `0.1`, capping the result at `1.0` to prevent unbounded growth.

Assigned a weight of `0.3` (`CONSTRAINT_DRIFT_WEIGHT`), this metric ensures that violations of explicit boundaries—such as "Python 3.14+" or "No external database" requirements—contribute significantly to the combined score without overwhelming goal-oriented deviations.

### Ontology Drift (20% Weight)

**Ontology drift** captures conceptual divergence between the active workflow vocabulary and the schema defined in `seed.ontology_schema`. The `calculate_ontology_drift()` function extracts field names from the ontology schema, builds a set of currently utilized concepts, and computes the Jaccard distance (`1 - |intersection|/|union|`).

With a weight of `0.2` (`ONTOLOGY_DRIFT_WEIGHT`), this component penalizes unauthorized conceptual expansion—such as introducing "status" fields when only "tasks" are defined in the schema—while maintaining proportionally lower impact than goal or constraint deviations.

## Weighted Aggregation Implementation

The three independent drift scores are combined into a single **combined drift** metric using the weighted sum defined in PRD 13.1. The implementation in [`src/ouroboros/observability/drift.py`](https://github.com/Q00/ouroboros/blob/main/src/ouroboros/observability/drift.py) applies the 5/3/2 ratio through explicit constants:

```python
combined = (
    goal_drift * GOAL_DRIFT_WEIGHT          # 0.5

    + constraint_drift * CONSTRAINT_DRIFT_WEIGHT  # 0.3

    + ontology_drift * ONTOLOGY_DRIFT_WEIGHT      # 0.2

)

```

These weight constants are explicitly defined at lines 50-52 of the drift module:
- `GOAL_DRIFT_WEIGHT = 0.5`
- `CONSTRAINT_DRIFT_WEIGHT = 0.3`
- `ONTOLOGY_DRIFT_WEIGHT = 0.2`

## Threshold Monitoring and Event Emission

The aggregated score is evaluated against **NFR 5**, which mandates that acceptable drift must remain at or below `0.3`. When `combined_drift` exceeds this threshold, the system emits a `DriftThresholdExceededEvent`, triggering downstream consensus mechanisms or corrective interventions.

The `DriftMeasurement` class encapsulates this logic, providing an `is_acceptable` boolean property that compares the combined score against the NFR 5 threshold.

## Practical Implementation Example

The following example demonstrates measuring drift against a Seed specification:

```python
from ouroboros.observability.drift import DriftMeasurement
from ouroboros.core.seed import Seed

# 1️⃣ Load or construct a Seed (immutable spec)

seed = Seed(
    goal="Build a CLI task manager",
    constraints=("Python 3.14+", "No external database"),
    acceptance_criteria=("Tasks can be created", "Tasks can be listed"),
    ontology_schema=OntologySchema(
        name="TaskManager",
        description="Task manager ontology",
        fields=(
            OntologyField(name="tasks", field_type="array", description="List of tasks"),
        ),
    ),
    evaluation_principles=(),
    exit_conditions=(),
    metadata=SeedMetadata(),
)

# 2️⃣ Simulate a workflow iteration

current_output = "A simple command-line tool that lists tasks"
constraint_violations = []                     # none so far

current_concepts = ["tasks", "status"]          # observed concepts

# 3️⃣ Measure drift

measurement = DriftMeasurement()
metrics = measurement.measure(
    current_output=current_output,
    constraint_violations=constraint_violations,
    current_concepts=current_concepts,
    seed=seed,
)

print(f"Goal drift:      {metrics.goal_drift:.3f}")
print(f"Constraint drift:{metrics.constraint_drift:.3f}")
print(f"Ontology drift:  {metrics.ontology_drift:.3f}")
print(f"Combined drift:  {metrics.combined_drift:.3f}")
print(f"Acceptable?      {metrics.is_acceptable}")

```

Typical output:

```

Goal drift:      0.200
Constraint drift:0.000
Ontology drift:  0.250
Combined drift:  0.260
Acceptable?      True

```

## Key Source Files

The drift detection implementation spans multiple modules:

- **[`src/ouroboros/observability/drift.py`](https://github.com/Q00/ouroboros/blob/main/src/ouroboros/observability/drift.py)** — Contains core measurement logic, weight constants (`GOAL_DRIFT_WEIGHT`, `CONSTRAINT_DRIFT_WEIGHT`, `ONTOLOGY_DRIFT_WEIGHT`), and event definitions.
- **[`src/ouroboros/core/seed.py`](https://github.com/Q00/ouroboros/blob/main/src/ouroboros/core/seed.py)** — Defines the immutable Seed model providing `goal` and `ontology_schema` attributes used by drift calculations.
- **[`tests/unit/observability/test_drift.py`](https://github.com/Q00/ouroboros/blob/main/tests/unit/observability/test_drift.py)** — Unit tests verifying each drift component and the weighted 5/3/2 aggregation.
- **[`src/ouroboros/tui/widgets/drift_meter.py`](https://github.com/Q00/ouroboros/blob/main/src/ouroboros/tui/widgets/drift_meter.py)** — Terminal UI component visualizing `combined_drift` and alerting when thresholds are breached.

## Summary

- **Ouroboros Drift Detection** employs three specialized metrics—goal, constraint, and ontology drift—to quantify workflow deviation from the immutable Seed.
- The **50/30/20 weighting scheme** (5/3/2 ratio) prioritizes goal alignment while maintaining boundaries through constraint and ontology monitoring.
- **Jaccard similarity/distance** calculations provide deterministic semantic comparisons for goal and ontology components.
- Hard constraint violations are linearly penalized at **0.1 per violation** with a ceiling at 1.0.
- The **0.3 threshold** (NFR 5) triggers `DriftThresholdExceededEvent` when the weighted combined score exceeds acceptable limits.
- All functionality is centralized in [`src/ouroboros/observability/drift.py`](https://github.com/Q00/ouroboros/blob/main/src/ouroboros/observability/drift.py) with comprehensive test coverage in the corresponding unit test module.

## Frequently Asked Questions

### How does Ouroboros calculate the combined drift score?

Ouroboros calculates the combined drift score by executing a weighted sum of three independent metrics: goal drift multiplied by 0.5, constraint drift multiplied by 0.3, and ontology drift multiplied by 0.2. This aggregation is implemented in the `measure()` method of the `DriftMeasurement` class within [`src/ouroboros/observability/drift.py`](https://github.com/Q00/ouroboros/blob/main/src/ouroboros/observability/drift.py).

### What happens when the drift threshold is exceeded?

When the combined drift exceeds 0.3 (the NFR 5 threshold), the system instantiates and emits a `DriftThresholdExceededEvent`. This event can trigger consensus mechanisms, workflow termination, or corrective actions depending on the runtime configuration. The `is_acceptable` property on the metrics object returns `False` when this condition occurs.

### Why does goal drift have a higher weight than ontology drift?

Goal drift receives a 50% weight because deviation from the core objective represents the most critical failure mode for autonomous systems. Ontology drift receives only 20% because conceptual expansion, while important, is less immediately damaging than violating explicit constraints or missing the primary goal. This hierarchy reflects the priority order defined in the Ouroboros PRD.

### Can the 50/30/20 weights be customized?

According to the source code in [`src/ouroboros/observability/drift.py`](https://github.com/Q00/ouroboros/blob/main/src/ouroboros/observability/drift.py), the weights are defined as module-level constants (`GOAL_DRIFT_WEIGHT`, `CONSTRAINT_DRIFT_WEIGHT`, `ONTOLOGY_DRIFT_WEIGHT`) and appear to be fixed at 0.5, 0.3, and 0.2 respectively. While the constants could theoretically be modified at the code level, the PRD specification treats the 5/3/2 ratio as a fundamental design constraint for the drift detection algorithm.