{% extends "base.html" %} {% block title %}SpecterQA — {{ run_id }}{% endblock %} {% block content %}

{{ run_id }}

{{ run.passed | status_badge }}
Product {{ run.product_name | default("—", true) }}
Journey {{ run.scenario_name | default("—", true) }}
Persona {{ run.persona_name | default("—", true) }}{% if run.persona_role %} ({{ run.persona_role }}){% endif %}
Viewport {{ run.viewport_name | default("—", true) }} {% if run.viewport_size %}({{ run.viewport_size[0] }}x{{ run.viewport_size[1] }}){% endif %}
Duration {{ run.duration_seconds | default(0) | format_duration }}
Cost {{ run.cost_usd | default(0) | format_cost }}
Date {{ run._date_display }}
{% if run.mock_level %}
Mock Level {{ run.mock_level }}
{% endif %}
{% if run._has_report %} Download report.md {% endif %}

Steps

{% set steps = run.step_reports | default([]) %} {% if steps %}
{% for step in steps %}
{% if step.passed %} {% else %} {% endif %} Step {{ loop.index }} {{ step.step_id | default("") }} {{ step.mode | default("browser") }}

{{ step.description | default("No description") }}

{% if step.error %}
Error: {{ step.error }}
{% endif %} {% if step.notes %}

{{ step.notes }}

{% endif %}
Duration: {{ step.duration_seconds | default(0) | format_duration }} {% if step.action_count is defined %} Actions: {{ step.action_count }} {% endif %} {% if step.performance_ms is not none and step.performance_ms is defined %} Page load: {{ step.performance_ms | round(0) | int }}ms {% endif %}
{% if step.ux_observations is defined and step.ux_observations %}
UX Observations:
    {% for obs in step.ux_observations %}
  • {{ obs }}
  • {% endfor %}
{% endif %} {% if step.actions_taken is defined and step.actions_taken %}
Actions taken ({{ step.actions_taken | length }})
    {% for action in step.actions_taken %}
  1. {{ action | string | truncate(200) }}
  2. {% endfor %}
{% endif %} {% if step.findings is defined and step.findings %}
{% for finding in step.findings %}
{{ finding.severity | default('low') | upper }} {{ finding.category | default('') }} {{ finding.description | default('') }}
{% endfor %}
{% endif %} {% if step.screenshots is defined and step.screenshots %}
{% for ss_path in step.screenshots %} {% set ss_filename = ss_path.split('/')[-1] %} {% if ss_filename in run._screenshots_available %} Screenshot for step {{ loop.index }} {% endif %} {% endfor %}
{% endif %}
{% endfor %}
{% else %}

No step data available.

{% endif %}
{% if run._findings_by_severity %}

Findings

{% for severity, findings in run._findings_by_severity.items() %}

{{ severity | upper }} ({{ findings | length }})

{% for finding in findings %}
{{ finding.category | default("general") }} Step: {{ finding.step_id | default("—") }}

{{ finding.description | default("No description") }}

{% if finding.evidence %}

Evidence: {{ finding.evidence }}

{% endif %}
{% endfor %}
{% endfor %}
{% endif %} {% if run.cost_summary %}

Cost Breakdown

Total: {{ run.cost_usd | default(0) | format_cost }} {% if run.cost_summary.budget_limit_usd is defined %} Budget: {{ run.cost_summary.budget_limit_usd | format_cost }} {% endif %} {% if run.cost_summary.budget_remaining_usd is defined %} Remaining: {{ run.cost_summary.budget_remaining_usd | format_cost }} {% endif %} {% if run.cost_summary.call_count is defined %} API Calls: {{ run.cost_summary.call_count }} {% endif %}
{% set calls_by_model = run.cost_summary.get("calls_by_model", {}) %} {% set cost_by_model = run.cost_summary.get("cost_by_model", {}) %} {% if calls_by_model %} {% for model, count in calls_by_model.items() %} {% endfor %}
Model Calls Cost
{{ model }} {{ count }} {{ cost_by_model.get(model, 0) | format_cost }}
{% endif %}
{% endif %} {% endblock %} {% block scripts %} {% endblock %}