{# Bug-context report block. Expects `ctx` (a BugContext) in context. #} {% if ctx.change_note %}
Changed since Awaiting {{ ctx.change_note }}
{% endif %} {% set _by_parts = [] %} {% if ctx.reporter_name or ctx.reporter_email %} {% set _ = _by_parts.append('reporter') %} {% endif %} {% if ctx.filed or ctx.last_activity %} {% set _ = _by_parts.append('env') %} {% endif %} {% if _by_parts %}

{% if ctx.reporter_name or ctx.reporter_email %} Reported by {{ ctx.reporter_name or ctx.reporter_email }} {% endif %} {% if ctx.filed %} · filed {{ ctx.filed[:10] }}{% endif %} {% if ctx.last_activity %} · last activity {{ ctx.last_activity[:10] }}{% endif %}

{% endif %} {% set fx = ctx.firefox_version | version_only %} {% set _taken = is_taken(ctx) %} {% if ctx.platform or fx or ctx.affected_versions or _taken %}

{% if ctx.platform %}Platform{{ ctx.platform }}{% endif %} {% if fx %}Found{{ fx }}{% endif %} {% if ctx.affected_versions %}Affected{{ ctx.affected_versions }}{% endif %} {% if _taken %}Assigned{{ assignee_display(ctx) }}{% endif %}

{% endif %} {# Needinfo flags already pending on the bug at draft time. Scoped to the card (draft is defined); the `and` short-circuits before touching ctx.pending_needinfos in the watching view, where draft isn't in scope. #} {% if draft is defined and ctx.pending_needinfos %} {% set _redundant = redundant_needinfos(draft) | map('lower') | list %}
Pending NI {% for ni in ctx.pending_needinfos %} {% set _dupe = (ni.requestee | string | lower) in _redundant %} {{ ni.requestee }}{% if ni.since %} since {{ (ni.since | string)[:10] }}{% endif %} {% if _dupe %}⚠ already has a pending needinfo{% endif %} {% endfor %}
{% endif %} {% if ctx.inventory_present or ctx.inventory_missing %} {% endif %} {% set _regressors, _similar = (ctx.see_also | split_see_also) %} {% if _regressors %}
regression {% for s in _regressors %} bug {{ s.bug_id }} {% endfor %}
{% endif %} {% if _similar %}
Similar ({{ _similar|length }})
{% for s in _similar %} bug {{ s.bug_id }}{% if s.label %}{{ s.label }}{% endif %} {% endfor %}
{% endif %} {% if ctx.description_excerpt or ctx.recent_comments or ctx.attachments or ctx.ai_reasoning %}
{% if ctx.description_excerpt %} {% set parsed = ctx.description_excerpt | parse_description %}
Bug description (excerpt)
{% if parsed.intro %}

{{ parsed.intro | linkify }}

{% endif %} {% if parsed.steps %}
Steps to reproduce
{{ parsed.steps | linkify }}
{% endif %} {% if parsed.actual %}
Actual
{{ parsed.actual | linkify }}
{% endif %} {% if parsed.expected %}
Expected
{{ parsed.expected | linkify }}
{% endif %} {% if parsed.notes %}

{{ parsed.notes | linkify }}

{% endif %}
{% endif %} {% set key_comments = ctx.recent_comments | filter_key_comments %} {% if key_comments %}
{{ key_comments|length }} key comment{% if key_comments|length != 1 %}s{% endif %}
{% for c in key_comments %}
{{ c.author }} {{ c.ts[:16].replace('T', ' ') if c.ts else '' }}

{{ c.text | linkify }}

{% endfor %}
{% endif %} {% if ctx.attachments %}
Attachments ({{ ctx.attachments|length }})
{% for a in ctx.attachments %} {% set m = a | attachment_meta %}
{{ m.label }} {% if m.is_image %} {# Image: open in the in-page lightbox (base.html) instead of a new tab. JS reads data-img-* via event delegation so it survives htmx swaps. #} {% else %} {{ a.name }} {% endif %}
{% endfor %}
{% endif %} {% if ctx.ai_reasoning %}
AI reasoning
{{ ctx.ai_reasoning | render_markdown }}
{% endif %}
{% endif %}