{% from "_macros.html" import icon %} {# The plan card: what was found, what it is for, and the work as phases of tasks -- the one structure the harness spec has LLeMbas and the LLeMbas CLI keep per conversation (services/plans.py). Rendered from `plan`, already normalised: a message's snapshot (`message.plan`, in a bubble), the chat's own (`chat.plan`, in the panel above the composer), or the one on a card waiting to be approved (`item.plan`). Every caller sets `plan`, so this template never sees two shapes; a row written before version 2 came through `normalise` as one phase. Every line is model output and is escaped; a task is shown as text, never as Markdown, because a plan is the last thing that should be able to emit a link. A status is a CLASS, never a character in the text: a tick written into the string would be indistinguishable from a tick the model wrote itself. A bubble's card does not re-render as work goes on: the newest bubble carries the plan as it was then and the panel carries it now -- that is what a transcript is, and it makes "what did it think at step three" answerable. `plan_actions` (default on) draws the Execute button: on a message, for that snapshot; in the panel, for the plan as it stands (`current`). Off on the approval card, whose own buttons are the decision. In an agent chat Execute switches to Edit, never Auto -- the plan was written under a mode where every command stopped for approval, and a button that also removed the asking is not the button anybody pressed; in a chat it leaves Plan mode and carries on. The confirm dialog says which. #} {% set plan_actions = plan_actions if plan_actions is defined else true %} {% set plan_message_id = message.id if message is defined and message else "current" %}

{{ icon("check", "icon--sm") }} {{ plan.title or "A plan" }}

{% if plan.summary %}

{{ plan.summary }}

{% endif %} {% if plan.findings %}

{{ t("What was found") }}

{% endif %} {% if plan.objectives %}

{{ t("What it is for") }}

{% endif %} {% for phase in plan.phases %}
{# A single unnamed phase is what a version-1 row becomes, and heading it "Plan" above a plan headed "Plan" reads as a mistake. #} {% if plan.phases | length > 1 or phase.title not in ("Plan", "Work") %}

{{ phase.title }}

{% endif %}
    {% for task in phase.tasks %}
  1. {{ task.text }} {% if task.note %}{{ task.note }}{% endif %}
  2. {% endfor %}
{% endfor %} {% if plan_actions and chat and plan.steps %}
{% if chat.kind == "agent" %} {{ t("Switches to Edit — commands still ask.") }} {% else %} {% endif %}
{% endif %}