{# web/templates/cockpit.html — Watchtower Cockpit (Phase 4) #} {# --- Header ------------------------------------------------ #}

Watchtower

Scan: {{ scan_age }} {% set audit_status = health.get('audit_status', 'UNKNOWN') %} audit: {{ audit_status }}
{# --- Focus Task (T-398) ------------------------------------ #} {% if focus_task %}
Focus {{ focus_task.id }} {{ focus_task.name }}
{% endif %} {# --- Arcs in flight (T-1661) -------------------------------- #} {% if arcs_in_flight %}
Arcs in flight
{% for arc in arcs_in_flight %}
{% if arc.focused %}{% else %}{% endif %} {{ arc.id }} {{ arc.name }} {{ arc.task_count }} task{% if arc.task_count != 1 %}s{% endif %}
{% endfor %}
{% endif %} {# --- Token Usage Widget (T-803) ------------------------------ #} {% if token_usage %}
Tokens {{ token_usage.current_tokens }} this session ({{ token_usage.current_turns }} turns)
{{ token_usage.project_tokens }} project total · {{ token_usage.cache_hit }}% cache · {{ token_usage.sessions }} sessions
Details →
{% endif %} {% if scan_status == 'partial' %}
Scan partially completed — some data sources were unavailable.
{% endif %} {# --- Needs Decision (amber) -------------------------------- #} {% if needs_decision %}

Needs Your Decision ({{ needs_decision_total }}) {% if needs_decision_total > 3 %} Show all {% endif %}

{% for item in scan.get('needs_decision', []) %}
{{ item.summary }}
{% if item.priority_factors %}
{{ item.priority_factors[0].detail if item.priority_factors else '' }}
{% endif %}
{% if item.suggested_action is mapping %} {% endif %}
{% endfor %}
{% endif %} {# --- Action Required — unified summary card (T-645) ---------- #} {% if action_summary and action_summary.total > 0 %}

Action Required View all in Approvals →

{% if action_summary.tier0_count %} {{ action_summary.tier0_count }} Tier 0 {% endif %} {% if action_summary.go_count %} {{ action_summary.go_count }} GO Decisions {% endif %} {% if action_summary.human_ac_count %} {{ action_summary.human_ac_count }} Human ACs ({{ action_summary.human_ac_task_count }} tasks) {# T-1533: per-verdict count pills next to the AC count #} {% if action_summary.go_ac_count %} {{ action_summary.go_ac_count }} GO {% endif %} {% if action_summary.defer_ac_count %} {{ action_summary.defer_ac_count }} DEFER {% endif %} {% if action_summary.nogo_ac_count %} {{ action_summary.nogo_ac_count }} NO-GO {% endif %} {# T-1577: NO-REC distinguishes 'agent owes a recommendation' (no Recommendation block) from `?` (block exists but verdict unparseable). Same convention as /approvals filter buttons (T-1576). #} {% if action_summary.no_rec_ac_count %} {{ action_summary.no_rec_ac_count }} NO-REC {% endif %} {# T-1540 iter1: ? verdict was unaccounted for in pill sum (count vs pill mismatch). Surface it. T-1577: now means 'Recommendation block present but verdict unparseable' — NO-REC is split out above. #} {% if action_summary.unknown_ac_count %} {{ action_summary.unknown_ac_count }} ? {% endif %} {% endif %}
{% for task in action_summary.top_tasks %}
{{ task.task_id }}: {{ task.name[:60] }}{% if task.name|length > 60 %}...{% endif %} ({{ task.total - task.checked }} unchecked)
{% endfor %}
{% endif %} {# --- Framework Recommends (blue) --------------------------- #} {% if framework_recommends %}

Framework Recommends ({{ framework_recommends_total }}) {% if framework_recommends_total > 3 %} Show all {% endif %}

{% for item in scan.get('framework_recommends', []) %}
{{ item.summary }}
{% if item.priority_factors %}
{{ item.priority_factors[0].detail if item.priority_factors else '' }}
{% endif %}
{% endfor %}
{% endif %} {# --- Work Direction ---------------------------------------- #}

Work Direction

{% if work_queue %} {% for item in work_queue %}
{{ item.priority }}. {{ item.task_id }}: {{ item.name }} {{ item.status }}
{% endfor %} {% else %}

No active tasks.

{% endif %}
{# --- Opportunities (green) --------------------------------- #} {% if opportunities %}

Opportunities ({{ opportunities_total }})

{% for item in scan.get('opportunities', [])[:3] %}
{{ item.summary }}
{% endfor %}
{% endif %} {# --- All Clear banner -------------------------------------- #} {% if not needs_decision and not framework_recommends and not opportunities and not risks %}

All Clear — no items requiring attention.

{% endif %} {# --- Mobile Approvals QR (T-671) ------------------------------ #} {% if approval_summary and approval_summary.total > 0 and qr_approvals_data %}
QR: /approvals

Mobile Approvals

Scan to review {{ approval_summary.total }} pending item{{ 's' if approval_summary.total != 1 }} on your phone

View approvals →
{% endif %} {# --- Recent activity (arc-007 S6d, T-2020) ----------------- #} {# Polled htmx fragment — recent commits as the framework activity feed. Read-only; refreshes every 15s without a page reload. #}

Recent Activity

Loading activity…

{# --- System Health + Concerns (T-398) ---------------------- #}

System Health

{% if concerns_summary %}
{{ concerns_summary.total_watching }}
Concerns
{{ concerns_summary.gaps }}
Gaps
{{ concerns_summary.risks }}
Risks
{% if concerns_summary.high > 0 %}
{{ concerns_summary.high }}
High
{% endif %}
{% endif %} {% if stale_tasks %}
{{ stale_tasks | length }} stale task{{ 's' if stale_tasks | length != 1 }}: {% for t in stale_tasks[:3] %}{{ t.id }}{% if not loop.last %}, {% endif %}{% endfor %}
{% endif %}

Full metrics →   Concerns →

Scan Summary

{{ summary }}

{% if risks %}
Risks
{% for risk in risks %}
{{ risk.summary }}
{% endfor %} {% endif %}