HOLONOGRAPH / The Guide · Drift attribution v0.23.0 all chapters

Chapter 13

Drift attribution

Reflects Holonograph v0.23.0 · ~6 min read

When a score changes over time, drift attribution tells you which layer of your system the change came from. It answers the question every operator asks after a moved number: is this us, or is this the vendor, or is this our evaluation, or is this just noise?

What it is

A per-surface analysis over a window that returns a timeline of change points. Each change point carries three things: the timestamp of the shift, one of four source labels, and the window over which the analysis is confident about that label.

The four source labels are the same four sources of drift the four-layer snapshot separates at capture time:

  • substrate: your own deployment
  • light source: the vendor moved under you
  • lens: your evaluation configuration changed
  • noise: the model's irreducible non-determinism
How to read the four labels Attribute the change, not the component. The same component can move for different reasons, and each reason is a different source. When your judge model changes, the source is not "the judge" — it is decided by who controlled the change and whether it was visible to you. A vendor silently rerouting the model behind a fixed alias is light source drift. You deliberately swapping the judge model, or revising its rubric, is lens drift. Same component, same moved number, read apart by control and visibility. Always attribute a change to the source that produced it, never to the part of the system it happened to touch.

Why it matters

Without attribution, a score move is a mystery. The operator has to guess at the cause, and every guess pulls the team in a different direction. With attribution, the same score move is a labeled event with a first suggestion for what to do next. The whole point is to route the response to the layer that can act on it.

How to use it

Point the analysis at a surface and a window:

POST /lens/attribute
Authorization: Bearer <token>
x-holonograph-run-mode: production
Content-Type: application/json

{
  "surfaceId": "classify-intent",
  "since": "2026-06-01T00:00:00Z",
  "until": "2026-07-05T00:00:00Z",
  "bucket": "day",
  "changePointDeltaThreshold": 0.15
}

The response is the timeline plus a couple of companion arrays:

{
  "surfaceId": "classify-intent",
  "eventCount": 12483,
  "changePoints": [
    {
      "timestamp": "2026-06-14T09:20:00Z",
      "source": "light source",
      "window": { "from": "2026-06-12T00:00:00Z", "to": "2026-06-15T00:00:00Z" }
    }
  ],
  "bracketedWindows": [ /* companion windows the analysis wants you to know about before acting */ ]
}

bucket controls the temporal resolution of the timeline. changePointDeltaThreshold is a sensitivity knob: higher = fewer points. Both are optional; the defaults are usually what you want.

Reading the output

Every change point comes with one of the four source labels. Do this with each:

LabelWhat it meansWhat to do
substrate The change tracks something you changed about your deployment. Check your own deployment: recent prompt edits, tool-schema revisions, feature flags, retrieval-index updates. Your substrate columns (Chapter 04) are where you look first.
light source The vendor moved under you: a model was silently re-routed, updated, or its behavior shifted. Check light_source_identifier across the window. If it's stable and the behavior still moved, the vendor changed the model behind an unchanged name.
lens Your evaluation configuration changed. Check the lens version history. A new lens version around the change point means you're seeing the apparatus move, not the system.
noise The model's irreducible non-determinism dominates this window. Gather more data before acting. A noise-labeled change point is a signal to widen the window, not a signal to ship a fix.

The bracketedWindows array holds companion windows the analysis wants you to see before acting on a source label: periods where the timeline is less confident than usual. Read those first when a change point lands adjacent to one.

Working through a report

The usual cadence: run the analysis over a window that ends at "yesterday," then walk the change points in order. Each label sends you to a different place (your deploy log, the vendor's changelog, your lens history), and the labeled window tells you where to look. Once every point has an action (or a decision not to act), the report is done.

Reference

Endpoint

Method & pathPurpose
POST /lens/attributeRun drift attribution over a window.

Request

FieldShapeNotes
surfaceIdstring (req)The surface to analyze.
sinceISO 8601 (opt)Inclusive lower bound on events considered.
untilISO 8601 (opt)Exclusive upper bound.
bucketenum (opt)day, hour, minute. Temporal resolution of the timeline.
changePointDeltaThresholdnumber 0–1 (opt)Sensitivity. Higher = fewer change points.

Response

FieldShapeNotes
surfaceIdstringEcho of the surface.
eventCountnumberHow many events were considered.
changePoints[]arrayTimeline of change points; each has timestamp, source label, and window.
bracketedWindows[]arrayCompanion windows worth reading before acting on nearby change points.