{# P5 recovery / gate / escalation panel (FR-4/FR-5). Rendered inside the detail body so it lives-swaps with the rest; the heavier phase diff is a link to the deliberate /runs/{slug}/diff page (not recomputed per SSE tick). `intel` is the resume_intel verdict; `gate` (when present) is the resolved gate/escalation evidence. Control forms are POSTed by control.js to the sanctioned CLI-verb endpoints; destructive verbs (reject) carry the FR-10.7 confirm. #} {% set controls = intel.available_controls %} {% if intel.state not in ("running", "done") %}

{% if intel.state == "gate" %}Pending gate — your decision {% elif intel.state == "escalation" %}Escalation — reconcile, then resume {% elif intel.state == "interrupted" %}Interrupted — resume available {% elif intel.state.startswith("halted") %}Halted — recovery {% elif intel.state == "failed" %}Failed {% elif intel.state == "rejected" %}Rejected (terminal) {% else %}Recovery{% endif %}

Recommended: {{ intel.recommended_action }}

{{ intel.rationale }}

{# --- fail closed (review F-001): gate evidence could not be assembled (unsafe show: path / unreadable artifact). Surface it and suppress the controls below so no decision is made without the required evidence. #} {% if gate_error %} {% endif %} {# --- escalation evidence (FR-4.6): findings + triage verdicts assembled --- #} {% if gate and gate.kind == "escalation" %} {% if gate.target_artifacts %} {% endif %} {% for f in gate.escalated %} {% endfor %}
IDSevCategoryLocationClaimVerdictActionTargetReasoning
{{ f.finding_id }}{{ f.severity or "—" }}{{ f.category or "—" }} {{ f.location or "—" }}{{ f.claim or "—" }} {{ f.verdict or "—" }}{{ f.action or "—" }} {{ f.target_artifact or "—" }}{{ f.reasoning or "—" }}
{% endif %} {# --- gate show: artifacts (FR-4.3): rendered readably --- #} {% if gate and gate.kind == "gate" %} {% if gate.upstream_conflict %}
⚠ UPSTREAM CONFLICT (builder-signalled, FR-4.5)
{{ gate.upstream_conflict }}
{% endif %} {% for a in gate.artifacts %}
{{ a.name }} ({{ a.kind }}{% if a.source %} · {{ a.source }}{% endif %}) {% if a.error %}

could not parse: {{ a.error }}

{% endif %} {# FR-4.3: findings/triage/confirm as readable tables, markdown as markdown. #} {% if a.kind == "findings" and a.parsed is not none %} {% for f in a.parsed.get("findings") or [] %} {% endfor %}
IDSevCategoryLocationClaimEvidenceSuggested fix
{{ f.get("id") or "—" }}{{ f.get("severity") or "—" }} {{ f.get("category") or "—" }}{{ f.get("location") or "—" }} {{ f.get("claim") or "—" }}{{ f.get("evidence") or "—" }} {{ f.get("suggested_fix") or "—" }}
{% if a.parsed.get("summary") %}

{{ a.parsed.get("summary") }}

{% endif %} {% elif a.kind == "triage" and a.parsed is not none %} {% for v in a.parsed.get("verdicts") or [] %} {% endfor %}
FindingVerdictActionConfidenceTargetReasoning
{{ v.get("finding_id") or "—" }}{{ v.get("verdict") or "—" }} {{ v.get("action") or "—" }}{{ v.get("confidence") or "—" }} {{ v.get("target_artifact") or "—" }}{{ v.get("reasoning") or "—" }}
{% elif a.kind == "confirm" and a.parsed is not none %} {% for v in a.parsed.get("verdicts") or [] %} {% endfor %}
FindingVerdictNotes
{{ v.get("finding_id") or "—" }}{{ v.get("verdict") or "—" }} {{ v.get("notes") or "—" }}
{% set newf = a.parsed.get("new_findings") or [] %} {% if newf %}

New findings in this round's diff:

{% for nf in newf %} {% endfor %}
SevClaimLocation
{{ nf.get("severity") or "—" }}{{ nf.get("claim") or "—" }}{{ nf.get("location") or "—" }}
{% endif %} {% if a.parsed.get("summary") %}

{{ a.parsed.get("summary") }}

{% endif %} {% elif a.kind == "json" and a.parsed is not none %}
{{ a.parsed | tojson(indent=2) }}
{% elif a.kind == "markdown" and a.content is not none %}
{{ a.content | markdown }}
{% elif a.content is not none %}
{{ a.content }}
{% elif a.kind == "missing" %}

not written yet

{% endif %}
{% endfor %} {% endif %}

View phase diff → · Judge audit →

{# --- FR-4.7 scoped-analysis hand-off (opt-in). Only when enabled AND parked at a gate/escalation. The console makes NO model call and spawns NOTHING — it fetches the assembled prompt and shows it in a read-only, copy-pasteable textarea (D8). control.js wires the button. #} {% if handoff_enabled and intel.state in ("gate", "escalation") %}

Assembles a read-only, copy-pasteable prompt for a separate analysis session. The console runs nothing (FR-4.7/D8).

{% endif %} {# --- control forms: only the verbs resume_intel permits (FR-5.3), and never when gate evidence failed to assemble (review F-001, fail closed). --- #} {% if not external and not gate_error %}
{% if "approve" in controls %}
{% endif %} {% if "reject" in controls %}
{% endif %} {% if "resume" in controls %}
{% endif %}
{% endif %}
{% endif %}