ADR-0030: The incident experiment, and its postmortem¶
Status: Accepted Date: 2026-10-12 Deciders: Alex Nodeland
Builds the template's part of phase 6 of relayr RFC-0001, on relayr's proposal outcomes and measures (relayr ADR-0031).
Context¶
Phase 6's exit is that the example's experiment reports acceptance, rewrite rate and time to resolution. The incident example's rules wrote the timeline directly, so no rule proposed anything to accept, and nothing marked an incident's end.
Decision¶
- An incident ends with
incident.resolved.IncidentResolved(service, summary)firesclose-incident. Its run finds the service's latest open incident, marks its timeline resolved (resolved_at), posts a closing notice in the incident's thread, and proposes apostmortemthere. A repeated resolution finds the incident resolved, and does nothing.- The postmortem is a typed artifact, proposed for review: a summary, the timeline's entries, and follow-ups people add.
- Its rationale says what it was drawn from: the timeline, with its number of entries, and the resolution.
close-incidentreaches any thread, and trusts onlyopen-incident's record of it.- A resolution from monitoring brings no thread, so the rule's allowlist grants any thread (
threads="any") and direct writes to timelines, forresolved_at. Its other writes are a proposal and a notice. - It acts as the application, a code rule (
CODE_RULES), which may write in a restricted thread. - A timeline's writes are direct, so anyone who may write one could point it at a thread they choose. The rule therefore considers only timelines whose first version
open-incidentwrote, and takes the incident's service and thread from that first version. A timeline anyone else made, or edited since, can't steer it into another thread, restricted or not.
- A resolution from monitoring brings no thread, so the rule's allowlist grants any thread (
- relayr's evaluation joins the application.
relayr:proposal-outcomeis among Automation's rules and the code rules, and the bridge registers its action, with or withoutevals: scoring runs in the application. The template asks forrelayr-ai[evals]. Each postmortem people accept, edit or reject scores theclose-incidentrun that proposed it. - The experiment runs through the application itself.
incident-scenariosbuilds the application withcreate_app, in process, on a scripted model and a SQLite file of its own. It plays each example over its REST API, as monitoring and people would: an alert opens the incident, people write in the thread, the incident is resolved, and people accept the postmortem, edit it, or reject it, and in one scenario rewrite it afterwards.make evalsinstalls theevalsdependency group, which brings the HTTP client and SQLite driver this needs. - It exercises the measures end to end, and judges nothing. Each scenario's decisions are scripted, and no model is on the path, so the outcomes are the scripts' own. What it checks is that relayr's measures read what the application wrote. Each example's verdict, an
IncidentReview, reports:- the postmortem's outcome, from
proposal_rates; - how much of the postmortem the rule wrote people rewrote, from evalr's
measure_rewritesoverrelayr.evals.history, or none without a postmortem; - the seconds between the alert and its resolution, from their events' own timestamps.
- the postmortem's outcome, from
- Time to resolution is the alert to its resolution, by service. reflexr's
time_to_resolutionmeasures a causal chain, and a resolution that monitoring publishes starts a chain of its own, so it can't tell when an incident ended. Each resolution is paired with the service's latest alert before it.
Options considered¶
| Option | For | Against |
|---|---|---|
| A postmortem proposed on resolution (chosen) | A rule's proposal people review, so acceptance and edits are real; a useful artifact | One more rule and artifact type in the example |
| Proposed timeline entries | No new rule | A less useful timeline, with direct and proposed writes in one rule |
Acceptance from rule drafts (rule_conversion) |
Nothing new | Measures drafts, not a rule's proposals |
| The application, over REST (chosen) | The real wiring, as deployed | Slower than the parts alone |
| The parts, wired anew in the experiment | Faster | A second copy of the wiring, which drifts |
Consequences¶
- Easier:
make evalschecks the example's incidents end to end, through the same code that serves them, and is where a real evaluation of the rules, with a model on the path, would start. - Harder: the experiment builds the whole application for each example, so it takes seconds, not milliseconds.