{% extends "base.html" %} {% block title %}{{ inc.title }}{% endblock %} {% block content %}
Incidents / #{{ inc.id }}

{% if inc.resolved_at %}{% else %}{% endif %}{{ inc.title }}

{{ inc.kind }} · started {{ inc.started_at|dt }} · {% if inc.resolved_at %}resolved {{ inc.resolved_at|dt }} · lasted {{ fmt_duration(inc.duration_seconds) }}{% else %}ongoing for {{ fmt_duration(inc.duration_seconds) }}{% endif %}{% if m %} · {{ m.name }}{% elif inc.server_id %} · {{ (inc.source or 'server')|replace('server:', '') }}{% endif %}
{% if user.can_edit %}
{% if not inc.acknowledged_at and not inc.resolved_at %}
{% endif %} {% if not inc.resolved_at and not inc.manual %}
{% endif %}
{% endif %}
{% if inc.acknowledged_at %}
Acknowledged by {{ inc.acknowledged_by }} at {{ inc.acknowledged_at|dt }}. Repeat alerts and escalation are paused.
{% elif inc.escalated_at %}
Escalated at {{ inc.escalated_at|dt }} because nobody acknowledged in time.
{% endif %} {% if ai_enabled %}

✦ AI analysis

Root cause, fix and a postmortem draft from the evidence. {{ ai_quota.left }} of {{ ai_quota.limit }} analyses left this month.
{% if user.can_edit %}
{% if analysis %}{% else %}{% endif %}
{% endif %}
{% if analysis %}

{{ analysis.summary }}

{% if analysis.impact %}

Impact: {{ analysis.impact }}

{% endif %}
{% if analysis.fix %}
Fix
    {% for f in analysis.fix %}
  1. {{ f }}
  2. {% endfor %}
{% endif %} {% if analysis.prevention %}
Prevent it
    {% for f in analysis.prevention %}
  • {{ f }}
  • {% endfor %}
{% endif %}
{% if analysis.postmortem %}
Postmortem draft
{{ analysis.postmortem }}
{% if user.can_edit and not inc.postmortem %}{% endif %}
{% endif %}
Generated {{ analysis.at[:16]|replace('T',' ') }} UTC by {{ analysis.model }}. AI can be wrong; verify before acting.
{% else %}

Click Explain to get a plain-English root cause, the most likely fix and a ready-to-paste postmortem, built from the failing checks, response evidence, server metrics and traces.

{% endif %}
{% endif %}

Cause

{{ inc.cause or (first_fail.error if first_fail else 'No cause recorded.') }}

{% if evidence %}

Evidence from the first failing check

Status
HTTP {{ evidence.evidence.status }}
Timing
DNS {{ evidence.evidence.timing.dns_ms }} ms · first byte {{ evidence.evidence.timing.ttfb_ms }} ms · total {{ evidence.evidence.timing.total_ms }} ms
{% for k, v in evidence.evidence.headers.items() %}
{{ k }}
{{ v }}
{% endfor %}
Response body
{{ evidence.evidence.body }}
{% endif %}

Timeline

  • Started {{ inc.started_at|dt }}
  • {% for u in inc.updates or [] %}
  • {{ u.status }} {{ u.at[:16]|replace('T',' ') }} UTC
    {{ u.message }}
  • {% endfor %} {% for al in alerts %}
  • Alert: {{ al.title }} {{ al.created_at|dt }}
    {% for k, v in al.delivery.items() %}{{ k.split(':')[0] }}: {{ v }}{% if not loop.last %} · {% endif %}{% endfor %}
  • {% endfor %} {% if inc.acknowledged_at %}
  • Acknowledged by {{ inc.acknowledged_by }} {{ inc.acknowledged_at|dt }}
  • {% endif %} {% if inc.resolved_at %}
  • Resolved {{ inc.resolved_at|dt }}
  • {% endif %}
{% if checks %}

Checks around the incident

{% for c in checks %}{% endfor %}
{{ checks|length }} checks from 30 min before the incident{% if inc.resolved_at %} to 5 min after recovery{% else %} until now{% endif %}.
{% endif %}

Postmortem

What happened, why, and what changes so it doesn't recur. Shown on status pages that include this component.

{% if user.can_edit %}
{% else %}
{{ inc.postmortem or '—' }}
{% endif %}
{% endblock %}