{% from "_macros.html" import icon %} {# A plan: what was found, what it is for, and the work as phases of tasks. Rendered from `message.plan` -- the property, which normalises -- rather than from `plan_json`, so a row written before version 2 comes through as one phase and this template never sees two shapes. The Execute button still posts the message id and the server still reads the flattened `steps`, so it sends exactly what was proposed. 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. It does not re-render in place as work goes on. The newest bubble carries the current plan and older ones carry the plan as it was then -- that is what a transcript is, and it makes "what did it think at step three" answerable. Execute switches the chat 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. The confirm dialog says so. #} {% set plan = message.plan %}

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

{% if plan.summary %}

{{ plan.summary }}

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

What was found

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

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 != "Plan" %}

{{ phase.title }}

{% endif %}
    {% for task in phase.tasks %}
  1. {{ task.text }} {% if task.note %}{{ task.note }}{% endif %}
  2. {% endfor %}
{% endfor %} {% if chat.kind == "agent" %}
Switches to Edit — commands still ask.
{% endif %}