{% extends "base.html" %}
{% block title %}Request {{ req.request_id[:12] }} - MoralStack{% endblock %}
{% block content %}
<div class="page-header">
    <nav class="breadcrumb">
        <a href="/runs">Dashboard</a> &rsaquo;
        <a href="/runs/{{ run_id }}">Run {{ run_id[:12] }}</a> &rsaquo;
        <span>Request</span>
    </nav>
    <h1>Request <span class="mono">{{ req.request_id[:12] }}</span></h1>
</div>

{% if path_badge_info %}
<div class="card" style="margin-bottom:1rem; border-left:4px solid #2dd4bf;">
    <span class="meta-label">Percorso esecuzione</span>
    <span class="meta-value" style="margin-left:0.5rem;">
        <span class="badge badge-parallel">{{ path_badge_info.label }}</span>
    </span>
    {% if proxy_output_info and proxy_output_info.final_text_source %}
    <span class="muted" style="margin-left:0.75rem;">
        Fonte output finale: <span class="mono">{{ proxy_output_info.final_text_source }}</span>
    </span>
    {% endif %}
</div>
{% endif %}

<div class="card meta-grid">
    <div class="meta-item">
        <span class="meta-label">Domain</span>
        <span class="meta-value">{{ req.domain or '—' }}</span>
    </div>
    <div class="meta-item">
        <span class="meta-label">Created</span>
        <span class="meta-value ts">{{ req.created_at | fmtdate }}</span>
    </div>
    {% if req.get('conversation_id') or req.get('turn_index') is not none or req.get('parent_request_id') %}
    <div class="meta-item span-2">
        <span class="meta-label">Conversation</span>
        <span class="meta-value">
            {% if req.get('conversation_id') %}
            <a href="/conversations/{{ req.get('conversation_id') }}" class="mono">id={{ req.get('conversation_id') }}</a>
            {% endif %}
            {% if req.get('turn_index') is not none %}<span class="muted">turn={{ req.get('turn_index') }}</span>{% endif %}
            {% if req.get('parent_request_id') %}
            <a href="/runs/{{ run_id }}/requests/{{ req.get('parent_request_id') }}" class="mono">parent={{ req.get('parent_request_id')[:12] }}…</a>
            {% endif %}
        </span>
    </div>
    {% endif %}
</div>

{% if conversation_context %}
{% set state = conversation_context.state or {} %}
{% set summary = state.get('state_summary_json__parsed') or {} %}
{% set meta = conversation_context.meta_json__parsed or {} %}
{% set proxy = conversation_context.proxy_event or {} %}
{% set state_cft = state.get('cached_from_turn') %}
{% set meta_cft = meta.get('cached_from_turn') %}
<h2>Conversation context</h2>
<div class="card">
    <div class="meta-grid">
        <div class="meta-item">
            <span class="meta-label">Conversation ID</span>
            <span class="meta-value mono">
                <a href="/conversations/{{ conversation_context.conversation_id }}">
                    {{ conversation_context.conversation_id[:16] }}…
                </a>
            </span>
        </div>
        <div class="meta-item">
            <span class="meta-label">Turn</span>
            <span class="meta-value">
                {{ conversation_context.turn_index if conversation_context.turn_index is not none else '—' }}
                / {{ conversation_context.turn_count }}
            </span>
        </div>
        <div class="meta-item">
            <span class="meta-label">Posture (out)</span>
            <span class="meta-value">
                {% set posture = state.get('posture') or summary.get('last_governance_posture') or meta.get('governance_posture') %}
                {% if posture %}<span class="badge">{{ posture }}</span>{% else %}—{% endif %}
            </span>
        </div>
        <div class="meta-item">
            <span class="meta-label">Cached</span>
            <span class="meta-value">
                {% if state.get('was_cached') or meta.get('was_cached') %}
                <span class="badge badge-ok">yes</span>
                {% set cft = state_cft if state_cft is not none else meta_cft %}
                {% if cft is not none %}<span class="muted"> from turn {{ cft }}</span>{% endif %}
                {% else %}no{% endif %}
            </span>
        </div>
        <div class="meta-item">
            <span class="meta-label">Refresh required</span>
            <span class="meta-value">{% if state.get('refresh_required') %}yes{% else %}no{% endif %}</span>
        </div>
        {% if state.get('refresh_reason') %}
        <div class="meta-item">
            <span class="meta-label">Refresh reason</span>
            <span class="meta-value">{{ state.get('refresh_reason') }}</span>
        </div>
        {% endif %}
    </div>

    {% if conversation_context.siblings and conversation_context.siblings | length > 1 %}
    <h4 style="margin-top:1rem;">All turns in conversation</h4>
    <table class="table">
        <thead>
        <tr><th>Turn</th><th>Request</th><th>Domain</th></tr>
        </thead>
        <tbody>
        {% for s in conversation_context.siblings %}
        <tr {% if s.is_current %}style="background: var(--blue-bg);"{% endif %}>
            <td>{{ s.turn_index if s.turn_index is not none else '—' }}</td>
            <td class="mono">
                {% if s.is_current %}<strong>{{ (s.request_id or '')[:12] }} (current)</strong>
                {% else %}<a href="/runs/{{ run_id }}/requests/{{ s.request_id }}">{{ (s.request_id or '')[:12] }}</a>{% endif %}
            </td>
            <td>{{ s.domain or '—' }}</td>
        </tr>
        {% endfor %}
        </tbody>
    </table>
    {% endif %}

    {% if conversation_context.ledger_events %}
    <h4 style="margin-top:1rem;">Ledger activity (this turn)</h4>
    <table class="table">
        <thead><tr><th>Op</th><th>Outcome</th><th>Similarity</th><th>Reason</th><th>From turn</th></tr></thead>
        <tbody>
        {% for ev in conversation_context.ledger_events %}
        <tr>
            <td>{{ ev.operation or '—' }}</td>
            <td><span class="badge">{{ ev.outcome or '—' }}</span></td>
            <td>{% if ev.similarity is not none %}{{ "%.3f" | format(ev.similarity) }}{% else %}—{% endif %}</td>
            <td>{{ ev.reason or '—' }}</td>
            <td>{{ ev.from_turn if ev.from_turn is not none else '—' }}</td>
        </tr>
        {% endfor %}
        </tbody>
    </table>
    {% endif %}

    {% if conversation_context.session_events %}
    <h4 style="margin-top:1rem;">Session store activity (this turn)</h4>
    <table class="table">
        <thead><tr><th>Op</th><th>Outcome</th></tr></thead>
        <tbody>
        {% for ev in conversation_context.session_events %}
        <tr>
            <td>{{ ev.operation or '—' }}</td>
            <td><span class="badge">{{ ev.outcome or '—' }}</span></td>
        </tr>
        {% endfor %}
        </tbody>
    </table>
    {% endif %}

    <div class="actions-bar" style="margin-top:1rem;">
        <a href="/conversations/{{ conversation_context.conversation_id }}" class="btn btn-sm">View full conversation</a>
        <a href="/conversations/{{ conversation_context.conversation_id }}/export.md" download class="btn btn-sm btn-outline">Export conversation</a>
    </div>
</div>
{% endif %}

{% if execution_summary %}
<h2>Execution summary</h2>
<div class="card">
    <div class="meta-grid">
        <div class="meta-item">
            <span class="meta-label">Path</span>
            <span class="meta-value">
                {{ execution_summary.path_badge }}
                {% if path_badge_info %}
                <span class="muted">({{ path_badge_info.label }})</span>
                {% endif %}
            </span>
        </div>
        <div class="meta-item">
            <span class="meta-label">Total deliberative cycles</span>
            <span class="meta-value">{{ execution_summary.total_cycles }}</span>
        </div>
        <div class="meta-item">
            <span class="meta-label">Converged</span>
            <span class="meta-value">{{ 'Yes' if execution_summary.converged else 'No' }}</span>
        </div>
        {% if execution_summary.estimation_mode %}
        <div class="meta-item">
            <span class="meta-label">Risk estimator mode</span>
            <span class="meta-value">
                {% if execution_summary.estimation_mode == 'parallel' %}
                <span class="badge badge-parallel" title="3 focused LLM calls ran in parallel: intent classifier, harm signal scanner, operational risk evaluator">Parallel (3 mini-estimators)</span>
                {% else %}
                {{ execution_summary.estimation_mode }}
                {% endif %}
            </span>
        </div>
        {% endif %}
    </div>
</div>
{% endif %}

{% if runtime_decision_obs %}
<h2>Execution strategy</h2>
<p class="muted" style="margin-bottom:0.5rem;">Structured runtime posture from decision traces (risk, retrieval
    context, per-cycle summaries). Scheduler / speculative / gating fields appear here as they are emitted.</p>
<div class="card runtime-strategy-card">
    {% set es = runtime_decision_obs.get('execution_strategy') or {} %}
    {% set ra = es.get('risk_assessment') or {} %}
    {% set rac = es.get('request_analysis_context') or {} %}
    <div class="meta-grid">
        {% if ra.get('risk_score') is not none %}
        <div class="meta-item">
            <span class="meta-label">Risk score (assessment trace)</span>
            <span class="meta-value mono">
                {{ ra.get('risk_score') }}
                {% if compliance_fast_path_panel and compliance_fast_path_panel.risk_estimation_used_for_decision is sameas false %}
                <span class="badge" style="background:#64748b;color:#fff;"
                    title="Risk was computed on the compliance fast-path but did not influence the DCCL routing decision">
                    calcolato ma non usato per la decisione
                </span>
                {% endif %}
            </span>
        </div>
        {% endif %}
        {% if ra.get('risk_category') %}
        <div class="meta-item">
            <span class="meta-label">Risk category</span>
            <span class="meta-value">{{ ra.get('risk_category') }}</span>
        </div>
        {% endif %}
        {% if ra.get('risk_policy_action') %}
        <div class="meta-item">
            <span class="meta-label">risk_policy_action</span>
            <span class="meta-value mono">{{ ra.get('risk_policy_action') }}</span>
        </div>
        {% endif %}
        {% if es.get('estimation_mode') %}
        <div class="meta-item">
            <span class="meta-label">Estimation mode</span>
            <span class="meta-value mono">{{ es.get('estimation_mode') }}</span>
        </div>
        {% endif %}
        {% if rac.get('constitution_domain') %}
        <div class="meta-item">
            <span class="meta-label">Constitution domain (request analysis)</span>
            <span class="meta-value mono">{{ rac.get('constitution_domain') }}</span>
        </div>
        {% endif %}
        {% if rac.get('relevant_principles_count') is not none %}
        <div class="meta-item">
            <span class="meta-label">Principles retrieved</span>
            <span class="meta-value">{{ rac.get('relevant_principles_count') }}</span>
        </div>
        {% endif %}
        {% if rac.get('prefilter_cache_status') %}
        <div class="meta-item span-2">
            <span class="meta-label">Domain prefilter cache</span>
            <span class="meta-value">
                <span class="mono">{{ rac.get('prefilter_cache_status') }}</span>
                {% if rac.get('prefilter_keywords_changed') %}
                <span class="badge badge-running" title="Effective keyword map changed before this lookup">keywords
                    invalidated</span>
                {% endif %}
                {% if rac.get('prefilter_cache_reason') %}
                <span class="muted">({{ rac.get('prefilter_cache_reason') }})</span>
                {% endif %}
                {% if rac.get('prefilter_keywords_fingerprint_prefix') %}
                <span class="muted mono" title="Keywords fingerprint prefix">fp:{{
                    rac.get('prefilter_keywords_fingerprint_prefix') }}…</span>
                {% endif %}
            </span>
        </div>
        {% endif %}
        {% set rpe = es.get('relevant_principles_events') or {} %}
        {% if rpe.get('retrieved_count') %}
        <div class="meta-item">
            <span class="meta-label">Relevant principles retrieval (request-scoped)</span>
            <span class="meta-value">yes <span class="muted">({{ rpe.get('retrieved_count') }} event)</span></span>
        </div>
        {% endif %}
        {% if rpe.get('reused_count') is not none %}
        <div class="meta-item">
            <span class="meta-label">Principles reuse events</span>
            <span class="meta-value">{{ rpe.get('reused_count') }}</span>
        </div>
        {% endif %}
        {% if rac.get('reuse_count') is not none %}
        <div class="meta-item span-2">
            <span class="meta-label">Reuse targets (trace)</span>
            <span class="meta-value mono">{{ (rac.get('reuse_targets') or []) | join(', ') or '—' }}</span>
        </div>
        {% endif %}
        {% if es.get('total_cycles_observed') is not none %}
        <div class="meta-item">
            <span class="meta-label">Cycles (summary traces)</span>
            <span class="meta-value">{{ es.get('total_cycles_observed') }}</span>
        </div>
        {% endif %}
        {% set conv = es.get('convergence') or {} %}
        {% if conv.get('cycle1_early_convergence_considered') is sameas true %}
        <div class="meta-item span-2">
            <span class="meta-label">Cycle 1 early convergence</span>
            <span class="meta-value">
                {% if conv.get('cycle1_early_convergence_accepted') is sameas true %}
                <span class="badge badge-parallel"
                    title="Deliberation stopped after cycle 1; conservative convergence criteria met">accepted</span>
                {% else %}
                <span class="badge" style="background:#6c757d;color:#fff;"
                    title="Evidence insufficient for cycle-1 stop; continued or stopped for other reasons">rejected</span>
                {% endif %}
                {% if conv.get('cycle1_deliberation_decision') %}
                <span class="mono muted">decision={{ conv.get('cycle1_deliberation_decision') }}</span>
                {% endif %}
                {% if conv.get('cycle1_convergence_reason_codes') %}
                <span class="mono muted" title="Reason codes">{{ (conv.get('cycle1_convergence_reason_codes') or []) | join(', ') }}</span>
                {% endif %}
            </span>
        </div>
        {% if conv.get('cycle1_perspectives_weighted_approval') is not none or conv.get('cycle1_semantic_expected_harm') is not none %}
        <div class="meta-item span-2" style="margin-top:0.35rem;">
            <span class="meta-label">Cycle 1 diagnostics</span>
            <span class="meta-value mono muted" style="font-size:0.9em;">
                {% if conv.get('cycle1_perspectives_weighted_approval') is not none %}w_approval={{ conv.get('cycle1_perspectives_weighted_approval') }}{% endif %}
                {% if conv.get('cycle1_semantic_expected_harm') is not none %}{% if conv.get('cycle1_perspectives_weighted_approval') is not none %} · {% endif %}sem_harm={{ conv.get('cycle1_semantic_expected_harm') }}{% endif %}
            </span>
        </div>
        {% endif %}
        {% endif %}
        {% set psbc = es.get('parallel_scheduler_by_cycle') or [] %}
        {% if psbc %}
        <div class="meta-item span-2">
            <span class="meta-label">Parallel scheduler (per cycle)</span>
            <span class="meta-value">
                {% for row in psbc %}
                <span class="mono" title="Reason codes: {{ (row.get('reason_codes') or []) | join(', ') }}">c{{
                    row.get('cycle') }}: {{ row.get('strategy') or '—' }}</span>{% if row.get('critic_short_circuit')
                %}<span class="badge badge-running" title="Critic short-circuit; downstream modules not run">short-circuit</span>{% endif %}{% if not loop.last %} · {% endif %}
                {% endfor %}
            </span>
        </div>
        {% endif %}
        {% if es.get('scheduler_events_count') is not none and es.get('scheduler_events_count', 0) > 0 %}
        <div class="meta-item">
            <span class="meta-label">Scheduler orchestration events</span>
            <span class="meta-value">{{ es.get('scheduler_events_count') }}</span>
        </div>
        {% endif %}
        {% set sgc = es.get('simulator_gating_by_cycle') or [] %}
        {% if sgc %}
        <div class="meta-item span-2">
            <span class="meta-label">Simulator gating (per cycle)</span>
            <span class="meta-value">
                {% for row in sgc %}
                <span class="mono" title="{{ (row.get('reason_codes') or []) | join(', ') }}">c{{ row.get('cycle') }}:
                    {{ row.get('status') or '—' }}</span>{% if row.get('carry_forward') %}<span class="badge"
                    title="Prior simulation evidence carried forward">carry-forward</span>{% endif %}{% if not loop.last
                %} · {% endif %}
                {% endfor %}
            </span>
        </div>
        {% endif %}
        {% if es.get('simulator_gating_events_count') is not none and es.get('simulator_gating_events_count', 0) > 0 %}
        <div class="meta-item">
            <span class="meta-label">Simulator orchestration events</span>
            <span class="meta-value">{{ es.get('simulator_gating_events_count') }}</span>
        </div>
        {% endif %}
        {% if es.get('final_action') %}
        <div class="meta-item">
            <span class="meta-label">Final action (FINAL trace)</span>
            <span class="meta-value mono">{{ es.get('final_action') }}</span>
        </div>
        {% endif %}
        {% if es.get('stop_reason') %}
        <div class="meta-item">
            <span class="meta-label">Stop reason</span>
            <span class="meta-value mono">{{ es.get('stop_reason') }}</span>
        </div>
        {% endif %}
        {% set sp = es.get('speculative') or {} %}
        {% if sp.get('speculative_started') or (sp.get('speculative_outcome') and sp.get('speculative_outcome') != 'none') %}
        <div class="meta-item span-2">
            <span class="meta-label">Speculative overlap</span>
            <span class="meta-value">
                {% if sp.get('speculative_started') %}
                <span class="badge badge-parallel" title="Policy draft ran in parallel with risk">started</span>
                {% endif %}
                <span class="mono">outcome: {{ sp.get('speculative_outcome') or '—' }}</span>
                {% if sp.get('join_required') %}
                <span class="badge badge-running" title="Controller awaited speculative output for this route">join
                    required</span>
                {% endif %}
                {% if sp.get('join_skipped') %}
                <span class="badge" style="background:#6c757d;color:#fff;"
                    title="Route did not await speculative output">join skipped</span>
                {% endif %}
                {% if sp.get('join_wait_ms') is not none %}
                <span class="muted">join wait {{ sp.get('join_wait_ms') | round(1) }} ms</span>
                {% endif %}
                {% if sp.get('skip_elapsed_ms') is not none %}
                <span class="muted">since spec start {{ sp.get('skip_elapsed_ms') | round(1) }} ms</span>
                {% endif %}
                {% if sp.get('last_discard_reason') %}
                <span class="muted mono" title="Last discard reason from orchestration payload">{{
                    sp.get('last_discard_reason') }}</span>
                {% endif %}
            </span>
        </div>
        {% endif %}
    </div>
</div>

{% if compliance_card %}
<div class="card">
    <h3>⚖️ Developer Contract Compliance Layer</h3>
    <p class="muted" style="margin-bottom:0.5rem;">
        The DCCL evaluated whether this request invokes a deployer-authorized behavior.
    </p>
    <div class="meta-grid">
        <div class="meta-item">
            <span class="meta-label">Decision</span>
            <span class="meta-value">
                {% if compliance_card.decision == 'MATCH' %}
                    <span class="badge badge-ok">MATCH</span>
                {% elif compliance_card.decision == 'SAFETY_OVERRIDE' %}
                    <span class="badge badge-fail">SAFETY_OVERRIDE</span>
                {% else %}
                    <span class="badge">{{ compliance_card.decision }}</span>
                {% endif %}
            </span>
        </div>

        <div class="meta-item">
            <span class="meta-label">Evaluation path</span>
            <span class="meta-value mono">{{ compliance_card.evaluation_path }}</span>
        </div>

        {% if compliance_card.matched_rule_summary %}
        <div class="meta-item">
            <span class="meta-label">Matched rule</span>
            <span class="meta-value mono">{{ compliance_card.matched_rule_summary }}</span>
        </div>
        {% endif %}

        {% if compliance_card.safety_override_reason %}
        <div class="meta-item">
            <span class="meta-label">Safety override reason</span>
            <span class="meta-value mono">{{ compliance_card.safety_override_reason }}</span>
        </div>
        {% endif %}

        <div class="meta-item">
            <span class="meta-label">Confidence</span>
            <span class="meta-value">{{ '%.2f'|format(compliance_card.confidence or 0.0) }}</span>
        </div>

        <div class="meta-item">
            <span class="meta-label">Draft validated</span>
            <span class="meta-value">{{ 'yes' if compliance_card.speculative_draft_validated else 'no' }}</span>
        </div>

        {% if compliance_card.draft_match_method %}
        <div class="meta-item">
            <span class="meta-label">Draft validation</span>
            <span class="meta-value mono">
                {{ compliance_card.draft_match_method }}
                {% if compliance_card.draft_match_confidence is not none %}
                ({{ '%.2f'|format(compliance_card.draft_match_confidence) }})
                {% endif %}
            </span>
        </div>
        {% endif %}

        {% if compliance_card.degraded %}
        <div class="meta-item span-2">
            <span class="meta-label">Verdetto degradato</span>
            <span class="meta-value">
                <span class="badge badge-running">{{ compliance_card.degraded_reason or '—' }}</span>
            </span>
        </div>
        {% endif %}
    </div>

    {% if compliance_card.action_payload_summary %}
    <p class="muted" style="margin-top:0.5rem;">
        <strong>Output autorizzato:</strong>
        <span class="mono">{{ compliance_card.action_payload_summary }}</span>
    </p>
    {% endif %}

    {% if compliance_card.rationale %}
    <p class="muted" style="margin-top:0.5rem;"><strong>Rationale:</strong> {{ compliance_card.rationale }}</p>
    {% endif %}

    {% if compliance_card.modules_deferred_detail %}
    <h4 style="margin-top:1rem;">Moduli bypassati (DCCL MATCH)</h4>
    <ul class="principles-list">
        {% for m in compliance_card.modules_deferred_detail %}
        <li class="principle-item">
            <span class="mono">{{ m.module }}</span>
            <span class="muted"> — saltato: esecuzione regola autorizzata dal contratto</span>
        </li>
        {% endfor %}
    </ul>
    {% elif compliance_card.modules_deferred %}
    <p class="muted" style="margin-top:0.5rem;"><strong>Modules deferred to compliance:</strong>
        <span class="mono">{{ compliance_card.modules_deferred | join(', ') }}</span>
    </p>
    {% endif %}
</div>
{% endif %}

<h2>Runtime decisions</h2>
<p class="muted" style="margin-bottom:0.5rem;">Orchestration events persisted independently of LLM calls (scheduler,
    retrieval, convergence). Empty when no rows were recorded for this request.</p>
<div class="card table-card">
    {% set rtd = runtime_decision_obs.get('runtime_decisions') or [] %}
    {% if rtd %}
    <table class="data-table runtime-decisions-table">
        <thead>
            <tr>
                <th>Cycle</th>
                <th>Stage</th>
                <th>Component</th>
                <th>Event</th>
                <th>Decision</th>
                <th>Reason</th>
                <th>Duration</th>
                <th>Status</th>
            </tr>
        </thead>
        <tbody>
            {% for row in rtd %}
            <tr>
                <td class="mono">{{ row.get('cycle') if row.get('cycle') is not none else '—' }}</td>
                <td>{{ row.get('stage') or '—' }}</td>
                <td class="mono">{{ row.get('component') or '—' }}</td>
                <td><span class="mono">{{ row.get('event') or '—' }}</span></td>
                <td class="mono">{{ row.get('decision') or '—' }}</td>
                <td>{{ row.get('reason') or '—' }}</td>
                <td>{% if row.get('duration_ms') is not none %}{{ row.get('duration_ms') | round(1) }} ms{% else %}—{% endif %}</td>
                <td>{{ row.get('status') or '—' }}</td>
            </tr>
            {% endfor %}
        </tbody>
    </table>
    {% else %}
    <p class="muted empty-state-msg">No orchestration events recorded for this request.</p>
    {% endif %}
</div>

<h2>Deliberation cycles</h2>
<p class="muted" style="margin-bottom:0.5rem;">Per-cycle summaries from <code>CYCLE_SUMMARY</code> decision traces.</p>
<div class="cycle-cards-grid">
    {% set ccs = runtime_decision_obs.get('cycle_cards') or [] %}
    {% if ccs %}
    {% for card in ccs %}
    <div class="card cycle-summary-card">
        <h3 class="cycle-card-title">{{ card.get('cycle_label') or ('Cycle ' ~ card.get('cycle')) }}</h3>
        <div class="meta-grid compact">
            {% if card.get('strategy') %}
            <div class="meta-item">
                <span class="meta-label">Strategy</span>
                <span class="meta-value mono">{{ card.get('strategy') }}</span>
            </div>
            {% endif %}
            {% if card.get('scheduler_reason_codes') %}
            <div class="meta-item span-2">
                <span class="meta-label">Scheduler reasons</span>
                <span class="meta-value mono">{{ (card.get('scheduler_reason_codes') or []) | join(', ') }}</span>
            </div>
            {% endif %}
            {% if card.get('critic_short_circuit') %}
            <div class="meta-item span-2">
                <span class="meta-label">Critic short-circuit</span>
                <span class="meta-value"><span class="badge badge-running" title="Simulator/perspectives not executed after critic hard signal">yes</span></span>
            </div>
            {% endif %}
            {% if card.get('critic_result') %}
            <div class="meta-item">
                <span class="meta-label">Critic</span>
                <span class="meta-value mono">{{ card.get('critic_result') }}</span>
            </div>
            {% endif %}
            {% if card.get('principles_source_note') %}
            <div class="meta-item span-2">
                <span class="meta-label">Principles</span>
                <span class="meta-value mono">{{ card.get('principles_source_note') }}</span>
            </div>
            {% endif %}
            <div class="meta-item span-2">
                <span class="meta-label">Modules executed</span>
                <span class="meta-value mono">{{ (card.get('modules_executed') or []) | join(', ') or '—' }}</span>
            </div>
            {% if card.get('simulator_result') is not none %}
            <div class="meta-item">
                <span class="meta-label">Simulator (semantic harm)</span>
                <span class="meta-value mono">{{ card.get('simulator_result') }}</span>
            </div>
            {% endif %}
            {% if card.get('simulator_ran_this_cycle') is not none %}
            <div class="meta-item span-2">
                <span class="meta-label">Simulator this cycle</span>
                <span class="meta-value">
                    {% if card.get('simulator_ran_this_cycle') %}
                    <span class="badge badge-parallel" title="Simulator LLM ran this cycle">executed</span>
                    {% else %}
                    <span class="badge" style="background:#6c757d;color:#fff;"
                        title="Explicit gate skip; prior simulation may apply">skipped (gated)</span>
                    {% endif %}
                    {% if card.get('simulator_gate_reason_codes') %}
                    <span class="mono muted">{{ (card.get('simulator_gate_reason_codes') or []) | join(', ') }}</span>
                    {% endif %}
                </span>
            </div>
            {% endif %}
            {% if card.get('perspectives_result') is not none %}
            <div class="meta-item">
                <span class="meta-label">Perspectives (avg approval)</span>
                <span class="meta-value mono">{{ card.get('perspectives_result') }}</span>
            </div>
            {% endif %}
            {% if card.get('convergence_result') %}
            <div class="meta-item">
                <span class="meta-label">Convergence (stop reason)</span>
                <span class="meta-value mono">{{ card.get('convergence_result') }}</span>
            </div>
            {% endif %}
            {% set ns_rw = namespace(shown=false) %}
            {% for call in llm_calls %}
                {% if not ns_rw.shown and call.get('cycle') == card.get('cycle') and 'SKIPPED_EMPTY_GUIDANCE' in (call.get('action') or '') %}
            <div class="meta-item span-2">
                <span class="meta-label">Rewrite</span>
                <span class="badge" style="background:#0369a1;color:#fff;"
                    title="Guidance filter returned empty: all modules satisfied. Draft from previous cycle preserved without rewrite.">
                    skipped (no substantive guidance)
                </span>
            </div>
                {% set ns_rw.shown = true %}
                {% endif %}
            {% endfor %}
            {% if card.get('deliberation_decision') %}
            <div class="meta-item">
                <span class="meta-label">Deliberation decision</span>
                <span class="meta-value mono">{{ card.get('deliberation_decision') }}</span>
            </div>
            {% endif %}
            {% if card.get('guidance_filter_summary') %}
            <div class="meta-item span-2">
                <span class="meta-label">Aggregated guidance (signal filter)</span>
                <span class="meta-value">
                    {% if card.get('rewrite_skipped_for_empty_guidance') %}
                    <span class="badge" style="background:#64748b;color:#fff;"
                        title="No substantive guidance after filter; cycle-2 policy rewrite was skipped">rewrite
                        skipped</span>
                    {% else %}
                    <span class="badge badge-parallel" title="Guidance passed to policy rewrite">rewrite prepared</span>
                    {% endif %}
                    <span class="muted" style="margin-left:0.35rem;">{{ card.get('guidance_filter_summary') }}</span>
                </span>
            </div>
            {% endif %}
            {% if card.get('early_convergence_considered') is sameas true %}
            <div class="meta-item span-2">
                <span class="meta-label">Early convergence (cycle 1)</span>
                <span class="meta-value">
                    {% if card.get('early_convergence_accepted') is sameas true %}
                    <span class="badge badge-parallel">accepted</span>
                    {% else %}
                    <span class="badge" style="background:#6c757d;color:#fff;">rejected</span>
                    {% endif %}
                    {% if card.get('convergence_reason_codes') %}
                    <span class="mono muted">{{ (card.get('convergence_reason_codes') or []) | join(', ') }}</span>
                    {% endif %}
                </span>
            </div>
            {% endif %}
        </div>
    </div>
    {% endfor %}
    {% else %}
    <p class="muted empty-state-msg">No per-cycle summary traces for this request.</p>
    {% endif %}
</div>
{% endif %}

{% if orchestrator_observability and orchestrator_observability.get('has_routing_data') %}
<h2>Path routing and risk governance</h2>
<p class="muted" style="margin-bottom:0.5rem;">Structured explanation of which orchestrator branch ran after risk
    assessment (fast, deliberative, early exit) and why thresholds, <code>risk_policy_action</code>, and sensitive-overlay
    floors matter. Sourced from runtime debug events and the FINAL decision trace (same data as the markdown export).</p>
<div class="card" style="border-left:4px solid #94a3b8;">
    <ul class="journey-list" style="list-style:disc; padding-left:1.25rem;">
        {% for line in orchestrator_observability.get('narrative_bullets', []) %}
        <li style="margin-bottom:0.35rem;">{{ line }}</li>
        {% endfor %}
    </ul>
    {% set sig = orchestrator_observability.get('routing_signals', {}) %}
    {% if sig %}
    <div class="meta-grid" style="margin-top:1rem;">
        {% if sig.path_taken %}
        <div class="meta-item">
            <span class="meta-label">Orchestrator path_taken</span>
            <span class="meta-value mono">{{ sig.path_taken }}</span>
        </div>
        {% endif %}
        {% if sig.risk_policy_action is not none %}
        <div class="meta-item">
            <span class="meta-label">risk_policy_action @ branch</span>
            <span class="meta-value mono">{{ sig.risk_policy_action }}</span>
        </div>
        {% endif %}
        {% if sig.threshold_low is not none %}
        <div class="meta-item">
            <span class="meta-label">threshold_low @ branch</span>
            <span class="meta-value mono">{{ sig.threshold_low }}</span>
        </div>
        {% endif %}
        {% if sig.risk_score_at_branch is not none %}
        <div class="meta-item">
            <span class="meta-label">risk_score @ branch</span>
            <span class="meta-value mono">{{ sig.risk_score_at_branch }}</span>
        </div>
        {% endif %}
        {% if sig.overlay_risk_floor_applied %}
        <div class="meta-item">
            <span class="meta-label">Sensitive overlay floor</span>
            <span class="meta-value mono">{{ sig.original_risk_score }} → {{ sig.floored_to }}</span>
        </div>
        {% endif %}
    </div>
    {% endif %}
</div>
{% endif %}

{% if execution_summary and execution_summary.domain_excluded %}
<div class="card" style="border-left:4px solid #f0ad4e; background:#fffdf5; padding:1.25rem;">
    <h2 style="color:#856404; margin-top:0;">Domain Not Available</h2>
    <p>This response was generated because the <strong>{{ execution_summary.excluded_domain }}</strong> domain is
        <strong>not enabled</strong> in this deployment's constitution configuration.</p>
    <p class="muted">The domain was detected during risk estimation. Deliberation and constitutional analysis were
        skipped entirely.</p>
    <div class="meta-grid" style="margin-top:1rem;">
        <div class="meta-item">
            <span class="meta-label">Excluded domain</span>
            <span class="meta-value mono">{{ execution_summary.excluded_domain }}</span>
        </div>
        <div class="meta-item">
            <span class="meta-label">Path</span>
            <span class="meta-value">DOMAIN_EXCLUDED (early exit after risk)</span>
        </div>
        <div class="meta-item">
            <span class="meta-label">Deliberation</span>
            <span class="meta-value muted">skipped</span>
        </div>
    </div>
    <p class="muted" style="margin-top:1rem; font-size:0.85rem;">
        To re-enable: remove <code>excluded: true</code> from
        <code>moralstack/constitution/data/overlays/{{ execution_summary.excluded_domain }}.yaml</code>.
    </p>
</div>
{% endif %}

{% if relevant_principles and (relevant_principles.relevant_at_start or relevant_principles.triggered or relevant_principles.overlay_applied or relevant_principles.reason_codes or relevant_principles.hard_violation_codes) %}
<h2>Relevant constitutional principles</h2>
<p class="muted" style="margin-bottom:0.5rem;">Relevant principles are retrieved at the start of deliberation via
    <strong>parallel domain agents</strong> (constitution store); that phase appears as <strong>constitution /
        relevant_principles</strong> in the Deliberation journey and Execution timeline below. Those principles guide
    the critic and policy; the triggered set reflects which applied to the final decision.</p>
<div class="card principles-card">
    {% if relevant_principles.relevant_at_start %}
    <div class="principles-section">
        <span class="meta-label">Relevant principles identified at the start of deliberation</span>
        <p class="principles-value principles-note">These principles were selected for this request and used to guide
            the critic (e.g. violation checks) and policy. They influence subsequent responses throughout the
            deliberation.</p>
        <ul class="principles-list">
            {% for p in relevant_principles.relevant_at_start %}
            <li class="principle-item">
                <span class="badge badge-{{ 'hard' if p.level == 'hard' else 'soft' }}">{{ p.level or 'soft' }}</span>
                <code class="principle-id-code">{{ p.id }}</code>
                {% if p.title %}<span class="principle-title">{{ p.title }}</span>{% endif %}
            </li>
            {% endfor %}
        </ul>
    </div>
    {% endif %}
    {% if relevant_principles.triggered %}
    <div class="principles-section">
        <span class="meta-label">Triggered principles (in final decision)</span>
        <p class="principles-value principles-note">Principles that applied to the final decision (from policy overlay).
            Violations and revision guidance from the critic appear in the Critic LLM call(s) below.</p>
        <ul class="principles-list">
            {% for p in relevant_principles.triggered %}
            <li class="principle-item">
                <span class="badge badge-{{ 'hard' if p.level == 'hard' else 'soft' }}">{{ p.level or 'soft' }}</span>
                <code class="principle-id-code">{{ p.id }}</code>
                {% if p.title %}<span class="principle-title">{{ p.title }}</span>{% endif %}
            </li>
            {% endfor %}
        </ul>
    </div>
    {% endif %}
    {% if relevant_principles.overlay_applied %}
    <div class="principles-section">
        <span class="meta-label">Overlay applied</span>
        <p class="principles-value">{{ relevant_principles.overlay_applied }}</p>
    </div>
    {% endif %}
    {% if relevant_principles.winning_rule %}
    <div class="principles-section">
        <span class="meta-label">Winning rule</span>
        <p class="principles-value"><code>{{ relevant_principles.winning_rule }}</code></p>
    </div>
    {% endif %}
    {% if relevant_principles.reason_codes %}
    <div class="principles-section">
        <span class="meta-label">Reason codes</span>
        <p class="principles-value">{{ relevant_principles.reason_codes | join(', ') }}</p>
    </div>
    {% endif %}
    {% if relevant_principles.hard_violation_codes %}
    <div class="principles-section">
        <span class="meta-label">Hard violation codes</span>
        <ul class="principles-list">
            {% for code in relevant_principles.hard_violation_codes %}
            <li class="principle-id"><code>{{ code }}</code></li>
            {% endfor %}
        </ul>
    </div>
    {% endif %}
</div>
{% endif %}

<h2>Original Prompt</h2>
<div class="card">
    <pre class="block">{{ req.prompt }}</pre>
</div>

{% if req.final_response %}
<h2>Final Response</h2>
<div class="card">
    <pre class="block">{{ req.final_response }}</pre>
</div>
{% endif %}

{% if journey_steps %}
<h2>Deliberation journey</h2>
<p class="muted" style="margin-bottom:0.5rem;">Exact execution order (first call to last). Steps that overlap in time
    are marked <span class="badge badge-parallel">Parallel</span>.</p>
<div class="card journey-card">
    <ol class="journey-list">
        {% for call in journey_steps %}
        <li class="journey-step {% if call.is_parallel %}journey-step-parallel{% endif %}">
            <span class="journey-seq">{{ loop.index }}</span>
            {% if call.is_parallel %}<span class="badge badge-parallel"
                                           title="Ran in parallel with other modules in this cycle">Parallel</span>{%
            endif %}
            <span class="journey-cycle">{% if call.cycle is none or call.cycle == 0 %}cycle 0{% else %}cycle {{ call.cycle }}{% endif %}</span>
            <span class="journey-module">{{ call.module }} / {{ call.phase }}{% if call.get('is_draft_reuse') %}
                <span class="badge badge-parallel" title="Speculative draft reused without a policy LLM call">Draft riusato (no LLM call)</span>{% elif call.get('parallel_retrieval') or call.get('is_synthetic') %} <span
                    class="muted">(parallel domain agents)</span>{% endif %}</span>
            {% if call.get('is_draft_reuse') %}
            <span class="muted">0ms (reuse)</span>
            {% elif call.duration_ms %}<span class="muted">{{ call.duration_ms | round(0) | int }}ms</span>{% endif %}
            <span class="muted ts">{{ call.started_at | fmtdate }}</span>
            {% if call.ended_at_ms %}<span class="muted ts">→ {{ call.ended_at_ms | fmtdate }}</span>{% endif %}
        </li>
        {% endfor %}
    </ol>
</div>
{% endif %}

{% if execution_timeline and execution_timeline.rows %}
<h2>Execution timeline (metro map)</h2>
<p class="muted" style="margin-bottom:0.5rem;">When each module ran over time. Overlapping bars = parallel
    execution.</p>
<div class="card timeline-card">
    <div class="timeline-ruler">
        <span class="timeline-ruler-start">0 ms</span>
        <span class="timeline-ruler-end">{{ execution_timeline.total_duration_ms | round(0) | int }} ms</span>
    </div>
    <div class="timeline-rows">
        {% for row in execution_timeline.rows %}
        <div class="timeline-row">
            <div class="timeline-row-label" title="{{ row.module }}">{{ row.module }}</div>
            <div class="timeline-row-track">
                {% for bar in row.calls %}
                <div class="timeline-bar" style="left: {{ bar.left_pct }}%; width: {{ bar.width_pct }}%;"
                     title="{{ row.module }} / {{ bar.phase }} — {{ bar.duration_ms | int }}ms (cycle {% if bar.cycle is none %}0{% else %}{{ bar.cycle }}{% endif %})">
                    <span class="timeline-bar-label">{{ bar.phase }}</span>
                </div>
                {% endfor %}
            </div>
        </div>
        {% endfor %}
    </div>
    <div class="timeline-legend">
        <span class="timeline-legend-item"><strong>Horizontal position</strong> = start time;</span>
        <span class="timeline-legend-item"><strong>Bar width</strong> = duration.</span>
        <span class="timeline-legend-item"><strong>Overlapping bars</strong> = parallel execution (modules ran at the same time).</span>
    </div>
</div>
{% endif %}

{% if module_summaries %}
<h2>Deliberation summary</h2>
<div class="card meta-grid">
    {% for mod, info in module_summaries.items() %}
    <div class="meta-item">
        <span class="meta-label">{{ mod }}</span>
        <span class="meta-value">{{ info.count }} call{{ 's' if info.count != 1 else '' }}{% if info.total_ms %}, {{ info.total_ms | int }}ms{% endif %}{% if info.last_summary %}: {{ (info.last_summary[:80] +'…') if (info.last_summary | length) > 80 else info.last_summary }}{% endif %}</span>
    </div>
    {% endfor %}
</div>
{% endif %}

{% if flow_data_cycles %}
<h2>LLM Calls <span class="muted">({{ llm_calls | length }})</span></h2>
<div class="view-toggle">
    <button type="button" class="btn btn-sm toggle-btn active" data-view="by-cycle" aria-pressed="true">By cycle
    </button>
    <button type="button" class="btn btn-sm toggle-btn" data-view="chronological" aria-pressed="false">Execution order
    </button>
</div>
<div id="view-by-cycle">
    <div class="flow-legend">
        <span class="flow-legend-item">
            <span class="flow-legend-dot" style="background:var(--red)"></span>risk_estimator
        </span>
        <span class="flow-legend-item">
            <span class="flow-legend-dot" style="background:var(--accent)"></span>policy
        </span>
        <span class="flow-legend-item">
            <span class="flow-legend-dot" style="background:var(--yellow)"></span>critic
        </span>
        <span class="flow-legend-item">
            <span class="flow-legend-dot" style="background:var(--green)"></span>simulator
        </span>
        <span class="flow-legend-item">
            <span class="flow-legend-dot" style="background:#a78bfa"></span>perspectives
        </span>
        <span class="flow-legend-item">
            <span class="flow-legend-dot" style="background:#fb923c"></span>hindsight
        </span>
        <span class="flow-legend-item">
            <span class="flow-legend-dot" style="background:#2dd4bf"></span>constitution
        </span>
        <span class="flow-legend-item">
            <span class="flow-legend-dot" style="background:#94a3b8"></span>orchestrator
        </span>
    </div>
    <div class="flow-graph">
        {% for cycle_data in flow_data_cycles %}
        <div class="flow-cycle" data-cycle="{{ cycle_data.cycle_num if cycle_data.cycle_num is not none else 0 }}">
            <div class="flow-cycle-label">
                {% if cycle_data.cycle_num is none or cycle_data.cycle_num == 0 %}
                Initial assessment <span class="flow-cycle-badge">cycle 0</span>
                {% else %}
                Deliberation <span class="flow-cycle-badge">cycle {{ cycle_data.cycle_num }}</span>
                {% endif %}
                <span class="flow-cycle-count">{{ cycle_data.total_calls }} call{{ 's' if cycle_data.total_calls != 1 else '' }}</span>
            </div>
            <div class="flow-nodes-structured">
                {% for tier in cycle_data.tiers %}
                {% if not loop.first %}
                <div class="flow-pipe">
                    <div class="flow-pipe-line"></div>
                    {% set lbl_idx = loop.index0 - 1 %}
                    {% if cycle_data.connector_labels and cycle_data.connector_labels[lbl_idx] %}
                    <span class="flow-pipe-label">{{ cycle_data.connector_labels[lbl_idx] }}</span>
                    {% endif %}
                    <div class="flow-pipe-arrow"></div>
                </div>
                {% endif %}

                <div class="flow-tier {% if tier|length > 1 %}flow-tier--parallel{% endif %}">
                    {% if tier|length > 1 %}
                    <span class="flow-tier-parallel-label">parallel &middot; {{ tier|length }} calls</span>
                    {% endif %}

                    {% for call in tier %}
                    <div class="flow-node"
                         data-module="{{ call.module or '' }}">
                        <div class="flow-node-header">
                            <span class="flow-node-chevron">&#9658;</span>
                            <div class="flow-node-title-area">
                                <div class="flow-node-title">{{ call.module }} / {{ call.phase }}{% if call.io_annotations and call.io_annotations.phase_hint %} · {{ call.io_annotations.phase_hint }}{% endif %}</div>
                                <div class="flow-node-meta">
                                    {% if call.action %}
                                    <span class="badge badge-type">{{ call.action }}</span>
                                    {% endif %}
                                    {% if call.model %}
                                    <span class="badge">{{ call.model }}</span>
                                    {% endif %}
                                    {% if call.call_outcome %}
                                    <span class="badge badge-semantic" title="call_outcome">{{ call.call_outcome }}</span>
                                    {% endif %}
                                    {% if call.semantic_badges %}
                                    {% for b in call.semantic_badges %}
                                    {% if b != call.call_outcome %}
                                    <span class="badge badge-semantic" title="Call semantics">{{ b }}</span>
                                    {% endif %}
                                    {% endfor %}
                                    {% endif %}
                                    {% if call.duration_ms %}
                                    <span class="flow-node-dur">{{ call.duration_ms | round(0) | int }}ms</span>
                                    {% endif %}
                                </div>
                                {% set preview = call.parsed_summary_json | module_result(call.module) %}
                                {% if preview %}
                                <div class="flow-node-pill">{{ (preview[:90] + '…') if preview | length > 90 else preview }}</div>
                                {% endif %}
                            </div>
                        </div>

                        {# IO Annotations #}
                        {% if call.io_annotations and (call.io_annotations.inputs or call.io_annotations.outputs) %}
                        <div class="flow-node-io" style="padding: 0 0.7rem 0.5rem 0.7rem; border-top:none; margin-top:0;">
                             {% for inp in call.io_annotations.inputs %}
                             <div class="io-row">
                                 <span class="io-arrow">&larr;</span> {{ inp.label }} <span class="muted">({{ inp.source }})</span>
                             </div>
                             {% endfor %}
                             {% for out in call.io_annotations.outputs %}
                             <div class="io-row">
                                 <span class="io-arrow">&rarr;</span> {{ out.label }}: <span class="io-val">{{ out.value }}</span>
                             </div>
                             {% endfor %}
                        </div>
                        {% endif %}

                        {# Timing Bar #}
                        {% if call.is_parallel_tier and call.tier_total_ms %}
                        <div class="flow-node-timing" title="Relative timing in tier">
                            <div class="flow-node-timing-bar" style="left: {{ call.tier_relative_start_pct }}%; width: {{ call.tier_relative_width_pct }}%;"></div>
                        </div>
                        {% endif %}

                        <div class="flow-node-body">
                            {% set preview = call.parsed_summary_json | module_result(call.module) %}
                            {% if preview %}
                            <div class="call-result-preview">
                                <span class="meta-label">Result / Summary</span>
                                <p class="call-result-text">{{ preview }}</p>
                            </div>
                            {% endif %}
                            <details>
                                <summary>Prompt</summary>
                                <pre class="block">{{ call.prompt }}</pre>
                            </details>
                            <details>
                                <summary>System Prompt</summary>
                                <pre class="block">{{ call.system_prompt }}</pre>
                            </details>
                            <details>
                                <summary>Raw Response</summary>
                                <pre class="block">{{ call.raw_response }}</pre>
                            </details>
                            {% if call.parsed_summary_json %}
                            <details>
                                <summary>Parsed Summary</summary>
                                <pre class="block json-block">{{ call.parsed_summary_json }}</pre>
                            </details>
                            {% endif %}
                            <div class="flow-node-ts">
                                <span class="muted ts">{{ call.started_at | fmtdate }}</span>
                            </div>
                        </div>
                    </div>
                    {% endfor %}
                </div>
                {% endfor %}
            </div>
        </div>
        {% if not loop.last %}
        <div class="flow-inter-cycle-connector">
            <div class="flow-pipe-inter-cycle-line"></div>
            <div class="flow-inter-cycle-arrow"></div>
        </div>
        {% endif %}
        {% endfor %}

        {# Final Decision Card #}
        {% if final_decision_card %}
        <div class="flow-inter-cycle-connector">
            <div class="flow-pipe-inter-cycle-line"></div>
            <div class="flow-inter-cycle-arrow"></div>
        </div>

        <div class="final-decision-card outcome-{{ final_decision_card.final_action }}">
            <div class="final-decision-header">
                <div class="final-decision-title">Final Decision</div>
                <div class="final-decision-meta">
                    <span class="badge badge-{{ 'ok' if final_decision_card.final_action == 'NORMAL_COMPLETE' else ('running' if final_decision_card.final_action == 'SAFE_COMPLETE' else 'fail') }}">
                        {{ final_decision_card.final_action }}
                    </span>
                </div>
            </div>
            <div class="final-decision-grid">
                <div class="meta-item">
                    <span class="meta-label">Stop Reason</span>
                    <span class="meta-value">{{ final_decision_card.stop_reason }}</span>
                </div>
                <div class="meta-item">
                    <span class="meta-label">Total Cycles</span>
                    <span class="meta-value">{{ final_decision_card.total_cycles }}</span>
                </div>
                {% if final_decision_card.path %}
                <div class="meta-item">
                    <span class="meta-label">Path</span>
                    <span class="meta-value">{{ final_decision_card.path }}</span>
                </div>
                {% endif %}
                {% if compliance_fast_path_panel %}
                <div class="meta-item span-2" style="grid-column:1/-1; margin-top:0.5rem; padding-top:0.75rem; border-top:1px solid var(--border);">
                    <span class="meta-label">DCCL decision (fast-path)</span>
                </div>
                <div class="meta-item">
                    <span class="meta-label">Verdetto</span>
                    <span class="meta-value">
                        <span class="badge badge-ok">{{ compliance_fast_path_panel.compliance_decision or '—' }}</span>
                    </span>
                </div>
                {% if compliance_fast_path_panel.matched_rule_summary or compliance_fast_path_panel.matched_rule_id %}
                <div class="meta-item">
                    <span class="meta-label">Regola</span>
                    <span class="meta-value mono">
                        {{ compliance_fast_path_panel.matched_rule_summary or compliance_fast_path_panel.matched_rule_id }}
                    </span>
                </div>
                {% endif %}
                {% if compliance_fast_path_panel.action_payload_summary %}
                <div class="meta-item span-2">
                    <span class="meta-label">Output autorizzato</span>
                    <span class="meta-value mono">{{ compliance_fast_path_panel.action_payload_summary }}</span>
                </div>
                {% endif %}
                {% if compliance_fast_path_panel.draft_match_method %}
                <div class="meta-item">
                    <span class="meta-label">Validazione draft</span>
                    <span class="meta-value mono">
                        {{ compliance_fast_path_panel.draft_match_method }}
                        {% if compliance_fast_path_panel.draft_match_confidence is not none %}
                        · conf={{ '%.2f'|format(compliance_fast_path_panel.draft_match_confidence) }}
                        {% endif %}
                    </span>
                </div>
                {% endif %}
                {% if compliance_fast_path_panel.evaluation_path %}
                <div class="meta-item">
                    <span class="meta-label">Evaluation path</span>
                    <span class="meta-value mono">{{ compliance_fast_path_panel.evaluation_path }}</span>
                </div>
                {% endif %}
                {% if compliance_fast_path_panel.degraded %}
                <div class="meta-item span-2">
                    <span class="meta-label">Verdetto degradato</span>
                    <span class="meta-value">
                        <span class="badge badge-running">{{ compliance_fast_path_panel.degraded_reason or '—' }}</span>
                        {% if compliance_fast_path_panel.degraded_reason == 'llm_timeout' %}
                        <span class="muted">(verdetto lento; draft riusato se validato)</span>
                        {% endif %}
                    </span>
                </div>
                {% endif %}
                {% if compliance_fast_path_panel.risk_estimation_used_for_decision is sameas false %}
                <div class="meta-item span-2">
                    <span class="meta-label">Risk estimation</span>
                    <span class="meta-value">
                        <span class="badge" style="background:#64748b;color:#fff;"
                            title="{{ compliance_fast_path_panel.risk_score_source or '' }}">
                            calcolato ma non usato per la decisione
                        </span>
                    </span>
                </div>
                {% endif %}
                {% endif %}
                {% if final_decision_card.winning_rule %}
                <div class="meta-item">
                    <span class="meta-label">Winning Rule</span>
                    <span class="meta-value mono">{{ final_decision_card.winning_rule }}</span>
                </div>
                {% endif %}
                {% if final_decision_card.policy_min_action or final_decision_card.policy_max_action %}
                <div class="meta-item">
                    <span class="meta-label">Policy bounds (constitution)</span>
                    <span class="meta-value mono">min={{ final_decision_card.policy_min_action or '—' }},
                        max={{ final_decision_card.policy_max_action or '—' }}</span>
                </div>
                {% endif %}
                {% if final_decision_card.risk_score %}
                <div class="meta-item">
                    <span class="meta-label">Final Risk Score</span>
                    <span class="meta-value">{{ final_decision_card.risk_score }}</span>
                </div>
                {% endif %}
                {% if final_decision_card.sim_semantic_expected_harm %}
                <div class="meta-item">
                    <span class="meta-label">Semantic Harm</span>
                    <span class="meta-value">{{ final_decision_card.sim_semantic_expected_harm }}</span>
                </div>
                {% endif %}
            </div>
             {% if final_decision_card.reason_codes %}
            <div style="margin-top:1rem;">
                <span class="meta-label">Reason Codes</span>
                <p class="mono" style="font-size:0.85rem; color:var(--text-secondary);">{{ final_decision_card.reason_codes | join(', ') }}</p>
            </div>
            {% endif %}

            {% if final_decision_card.why_not_refuse or final_decision_card.why_not_safe_complete or final_decision_card.why_not_normal_complete %}
             <div style="margin-top:1rem; padding-top:1rem; border-top:1px solid var(--border);">
                 {% if final_decision_card.why_not_refuse %}
                 <p style="font-size:0.85rem; color:var(--muted); margin-bottom:0.25rem;">Why not REFUSE? {{ final_decision_card.why_not_refuse }}</p>
                 {% endif %}
                 {% if final_decision_card.why_not_safe_complete %}
                 <p style="font-size:0.85rem; color:var(--muted); margin-bottom:0.25rem;">Why not SAFE_COMPLETE? {{ final_decision_card.why_not_safe_complete }}</p>
                 {% endif %}
                 {% if final_decision_card.why_not_normal_complete %}
                 <p style="font-size:0.85rem; color:var(--muted);">Why not NORMAL_COMPLETE? {{ final_decision_card.why_not_normal_complete }}</p>
                 {% endif %}
             </div>
            {% endif %}
        </div>
        {% endif %}
    </div>
</div>
<div id="view-chronological" class="hidden">
    {% for call in llm_calls_chronological %}
    <div class="card call-block">
        <div class="call-header">
            <h4><span class="journey-seq-inline">{{ loop.index }}</span> {{ call.module }} / {{ call.phase }}</h4>
            <div class="call-meta">
                {% if call.action %}
                <span class="badge badge-type">{{ call.action }}</span>
                {% endif %}
                {% if call.model %}
                <span class="badge">{{ call.model }}</span>
                {% endif %}
                {% if call.call_outcome %}
                <span class="badge badge-semantic" title="call_outcome">{{ call.call_outcome }}</span>
                {% endif %}
                {% if call.semantic_badges %}
                {% for b in call.semantic_badges %}
                {% if b != call.call_outcome %}
                <span class="badge badge-semantic" title="Call semantics">{{ b }}</span>
                {% endif %}
                {% endfor %}
                {% endif %}
                {% if call.duration_ms %}
                <span class="muted">{{ call.duration_ms | round(0) | int }}ms</span>
                {% endif %}
                <span class="muted ts">{{ call.started_at | fmtdate }}</span>
            </div>
        </div>
        {% set preview = call.parsed_summary_json | module_result(call.module) %}
        {% if preview %}
        <div class="call-result-preview">
            <span class="meta-label">Result / Summary</span>
            <p class="call-result-text">{{ preview }}</p>
        </div>
        {% endif %}
        <details>
            <summary>Prompt</summary>
            <pre class="block">{{ call.prompt }}</pre>
        </details>
        <details>
            <summary>System Prompt</summary>
            <pre class="block">{{ call.system_prompt }}</pre>
        </details>
        <details>
            <summary>Raw Response</summary>
            <pre class="block">{{ call.raw_response }}</pre>
        </details>
        {% if call.parsed_summary_json %}
        <details>
            <summary>Parsed Summary</summary>
            <pre class="block json-block">{{ call.parsed_summary_json }}</pre>
        </details>
        {% endif %}
    </div>
    {% endfor %}
</div>
{% elif llm_calls %}
<h2>LLM Calls <span class="muted">({{ llm_calls | length }})</span></h2>
{% for call in llm_calls %}
<div class="card call-block">
    <div class="call-header">
        <h3>{{ call.module }} / {{ call.phase }}{% if call.cycle is not none %} <span
                class="muted">(cycle {{ call.cycle }})</span>{% endif %}</h3>
        <div class="call-meta">
            {% if call.action %}
            <span class="badge badge-type">{{ call.action }}</span>
            {% endif %}
            {% if call.model %}
            <span class="badge">{{ call.model }}</span>
            {% endif %}
            {% if call.call_outcome %}
            <span class="badge badge-semantic" title="call_outcome">{{ call.call_outcome }}</span>
            {% endif %}
            {% if call.semantic_badges %}
            {% for b in call.semantic_badges %}
            {% if b != call.call_outcome %}
            <span class="badge badge-semantic" title="Call semantics">{{ b }}</span>
            {% endif %}
            {% endfor %}
            {% endif %}
            {% if call.duration_ms %}
            <span class="muted">{{ call.duration_ms | round(0) | int }}ms</span>
            {% endif %}
            <span class="muted ts">{{ call.started_at | fmtdate }}</span>
        </div>
    </div>
    {% set preview = call.parsed_summary_json | module_result(call.module) %}
    {% if preview %}
    <div class="call-result-preview">
        <span class="meta-label">Result / Summary</span>
        <p class="call-result-text">{{ preview }}</p>
    </div>
    {% endif %}
    <details>
        <summary>Prompt</summary>
        <pre class="block">{{ call.prompt }}</pre>
    </details>
    <details>
        <summary>System Prompt</summary>
        <pre class="block">{{ call.system_prompt }}</pre>
    </details>
    <details>
        <summary>Raw Response</summary>
        <pre class="block">{{ call.raw_response }}</pre>
    </details>
    {% if call.parsed_summary_json %}
    <details>
        <summary>Parsed Summary</summary>
        <pre class="block json-block">{{ call.parsed_summary_json }}</pre>
    </details>
    {% endif %}
</div>
{% endfor %}
{% endif %}

{% if traces %}
<h2>Decision Traces <span class="muted">({{ traces | length }})</span></h2>
{% for t in traces %}
<div class="card trace-block">
    <h3>{{ t.stage }} <span class="muted">(seq {{ t.sequence }})</span></h3>
    <span class="muted ts">{{ t.created_at | fmtdate }}</span>
    <pre class="block json-block">{{ t.trace_json }}</pre>
</div>
{% endfor %}
{% endif %}

{% if debug_events %}
<h2>Debug Events <span class="muted">({{ debug_events | length }})</span></h2>
{% for ev in debug_events %}
<div class="card">
    <span class="muted ts">{{ ev.created_at | fmtdate }}</span>
    <pre class="block debug-block">{{ ev.payload_json }}</pre>
</div>
{% endfor %}
{% endif %}

{% if benchmark_result %}
<h2>Benchmark Comparison</h2>
<p class="muted" style="margin-bottom:0.5rem;">Question {{ benchmark_result.question_id }}
    ({{ benchmark_result.category }}) | expected_action={{ benchmark_result.expected_action }}</p>

<div class="card benchmark-comparison-card">
    <h3>Baseline Response (GPT-4o direct)</h3>
    <p class="muted">Time: {{ benchmark_result.baseline_time_ms | round(0) | int }}ms | Predicted
        action: {{ benchmark_result.baseline_predicted_action or '-' }}</p>
    <pre class="block benchmark-response-block">{{ benchmark_result.baseline_response }}</pre>
    <h4>Judge Evaluation (Baseline)</h4>
    <div class="benchmark-eval-grid">
        <div class="meta-item"><span class="meta-label">Decision Correctness</span><span
                class="meta-value">{{ benchmark_result.baseline_eval.get('decision_correctness', '-') or '-' }}</span>
        </div>
        <div class="meta-item"><span class="meta-label">Response Quality</span><span
                class="meta-value">{{ (benchmark_result.baseline_eval.get('response_quality_score') or 0) | round(1) }}
            /10</span></div>
        <div class="meta-item"><span class="meta-label">Intent Interception</span><span
                class="meta-value">{{ (benchmark_result.baseline_eval.get('intent_interception_score') or 0) | round(1) }}
            /10</span></div>
        <div class="meta-item"><span class="meta-label">Trajectory Interruption</span><span
                class="meta-value">{{ (benchmark_result.baseline_eval.get('trajectory_interruption_score') or 0) | round(1) }}
            /10</span></div>
        <div class="meta-item"><span class="meta-label">Leakage Control</span><span
                class="meta-value">{{ (benchmark_result.baseline_eval.get('leakage_control_score') or 0) | round(1) }}
            /10</span></div>
        <div class="meta-item"><span class="meta-label">Safe Abstraction</span><span
                class="meta-value">{{ (benchmark_result.baseline_eval.get('safe_abstraction_score') or 0) | round(1) }}
            /10</span></div>
        <div class="meta-item"><span class="meta-label">Proportionality</span><span
                class="meta-value">{{ (benchmark_result.baseline_eval.get('proportionality_score') or 0) | round(1) }}
            /10</span></div>
        <div class="meta-item"><span class="meta-label">Redirection Quality</span><span
                class="meta-value">{{ (benchmark_result.baseline_eval.get('redirection_quality_score') or 0) | round(1) }}
            /10</span></div>
        <div class="meta-item"><span class="meta-label">Overall Safety</span><span
                class="meta-value">{{ (benchmark_result.baseline_eval.get('overall_safety') or 0) | round(1) }}
            /10</span></div>
    </div>
    {% if benchmark_result.baseline_eval.get('judge_reasoning') %}
    <p class="benchmark-reasoning"><strong>Judge
        reasoning:</strong> {{ benchmark_result.baseline_eval.get('judge_reasoning', '') }}</p>
    {% endif %}
</div>

<div class="card benchmark-comparison-card">
    <h3>MoralStack Response</h3>
    <p class="muted">Time: {{ benchmark_result.moralstack_time_ms | round(0) | int }}ms | Final
        action: {{ benchmark_result.moralstack_final_action or '-' }} |
        Path: {{ benchmark_result.moralstack_path or '-' }}</p>
    <pre class="block benchmark-response-block">{{ benchmark_result.moralstack_response }}</pre>
    <h4>Judge Evaluation (MoralStack)</h4>
    <div class="benchmark-eval-grid">
        <div class="meta-item"><span class="meta-label">Decision Correctness</span><span
                class="meta-value">{{ benchmark_result.moralstack_eval.get('decision_correctness', '-') or '-' }}</span>
        </div>
        <div class="meta-item"><span class="meta-label">Response Quality</span><span
                class="meta-value">{{ (benchmark_result.moralstack_eval.get('response_quality_score') or 0) | round(1) }}
            /10</span></div>
        <div class="meta-item"><span class="meta-label">Intent Interception</span><span
                class="meta-value">{{ (benchmark_result.moralstack_eval.get('intent_interception_score') or 0) | round(1) }}
            /10</span></div>
        <div class="meta-item"><span class="meta-label">Trajectory Interruption</span><span
                class="meta-value">{{ (benchmark_result.moralstack_eval.get('trajectory_interruption_score') or 0) | round(1) }}
            /10</span></div>
        <div class="meta-item"><span class="meta-label">Leakage Control</span><span
                class="meta-value">{{ (benchmark_result.moralstack_eval.get('leakage_control_score') or 0) | round(1) }}
            /10</span></div>
        <div class="meta-item"><span class="meta-label">Safe Abstraction</span><span
                class="meta-value">{{ (benchmark_result.moralstack_eval.get('safe_abstraction_score') or 0) | round(1) }}
            /10</span></div>
        <div class="meta-item"><span class="meta-label">Proportionality</span><span
                class="meta-value">{{ (benchmark_result.moralstack_eval.get('proportionality_score') or 0) | round(1) }}
            /10</span></div>
        <div class="meta-item"><span class="meta-label">Redirection Quality</span><span
                class="meta-value">{{ (benchmark_result.moralstack_eval.get('redirection_quality_score') or 0) | round(1) }}
            /10</span></div>
        <div class="meta-item"><span class="meta-label">Overall Safety</span><span
                class="meta-value">{{ (benchmark_result.moralstack_eval.get('overall_safety') or 0) | round(1) }}
            /10</span></div>
    </div>
    {% if benchmark_result.moralstack_eval.get('judge_reasoning') %}
    <p class="benchmark-reasoning"><strong>Judge
        reasoning:</strong> {{ benchmark_result.moralstack_eval.get('judge_reasoning', '') }}</p>
    {% endif %}
</div>

<div class="card">
    <h3>Verdict</h3>
    <p><strong>Winner:</strong> {{ benchmark_result.winner | upper }}
        (margin: {{ benchmark_result.winner_margin | round(1) }})</p>
    <p>{{ benchmark_result.comparison_reasoning }}</p>
</div>
{% endif %}

<div class="actions-bar">
    <a href="/runs/{{ run_id }}/requests/{{ req.request_id }}/export.md" download class="btn btn-outline">Export
        Markdown</a>
    {% if benchmark_result %}
    <a href="/runs/{{ run_id }}" class="btn btn-outline">Back to Benchmark</a>
    {% endif %}
</div>
{% if llm_calls or flow_data_cycles %}
<script>
(function () {
    /* ----------------------------------------------------------------
       View toggle (By cycle / Execution order)
    ---------------------------------------------------------------- */
    var byCycle = document.getElementById('view-by-cycle');
    var chronological = document.getElementById('view-chronological');
    var btns = document.querySelectorAll('.toggle-btn');
    if (byCycle && chronological && btns.length) {
        function show(view) {
            byCycle.classList.toggle('hidden', view !== 'by-cycle');
            chronological.classList.toggle('hidden', view !== 'chronological');
            btns.forEach(function (b) {
                var isActive = b.getAttribute('data-view') === view;
                b.classList.toggle('active', isActive);
                b.setAttribute('aria-pressed', isActive ? 'true' : 'false');
            });
        }
        btns.forEach(function (b) {
            b.addEventListener('click', function () { show(b.getAttribute('data-view')); });
        });
    }

    /* ----------------------------------------------------------------
       Expand / collapse individual nodes on header click
    ---------------------------------------------------------------- */
    function initNodeExpand() {
        document.addEventListener('click', function (e) {
            /* Ignore clicks inside the expanded body (details, pre, etc.). */
            if (e.target.closest('.flow-node-body')) return;
            var header = e.target.closest('.flow-node-header');
            if (!header) return;
            var node = header.closest('.flow-node');
            if (!node) return;
            e.stopPropagation();
            node.classList.toggle('flow-node--expanded');
        });
    }

    if (document.readyState === 'loading') {
        document.addEventListener('DOMContentLoaded', initNodeExpand);
    } else {
        initNodeExpand();
    }
})();
</script>
{% endif %}
{% endblock %}
