ase-task-edit · git:20261017.19ede76 · 2026-10-17 · sha256 975db4af149a74cf
ase-task-edit git:20261017.19ede76A
Immutable. This exact content never changes and is served at /api/v1/blob/975db4af149a74cf.
---
name: ase-task-edit
argument-hint: "[--help|-h] [--plan|-p <option>] [--mode|-m auto|craft|refactor|resolve|specify] [--approach|-a] [--unverified|-u] [--next|-n <option>[,...]] [<id> | <id>: <instruction> | <instruction> | <issue-id>]"
description: >
Iteratively edit and refine a named plan for a task through a
conversational loop. A new plan is optionally composed along the
chosen one of several proposed crafting, refactoring, resolution, or
specification approaches. Each round, the current plan is shown and the user is
asked whether to keep refining, mark the plan as done, or proceed to
the implementation or draft. Use when the user wants to plan a task
purely through chat-driven refinement, or wants a plan to "craft" a
new feature, "refactor" the code base, or "resolve" a problem (also
from a bare analyzer issue id like "P1").
user-invocable: true
disable-model-invocation: false
effort: high
---
@${CLAUDE_SKILL_DIR}/../../meta/ase-control.md
@${CLAUDE_SKILL_DIR}/../../meta/ase-skill.md
@${CLAUDE_SKILL_DIR}/../../meta/ase-dialog.md
@${CLAUDE_SKILL_DIR}/../../meta/ase-getopt.md
<purpose name="ase-task-edit">
Iteratively Edit a Task Plan
</purpose>
<expand name="getopt"
arg1="ase-task-edit"
arg2="--plan|-p=(none|OVERWRITE|REFINE|PRESERVE) --mode|-m=(auto|craft|refactor|resolve|specify) --approach|-a --unverified|-u --next|-n=(none|DONE|GRILL|DRAFT|IMPLEMENT)... --int-reuse-task --int-source-dir=">
$ARGUMENTS
</expand>
<objective>
Establish and refine the *task plan* purely through a *chat-driven
loop*. The user steers each round via an interactive dialog that offers
continued refinement, finalization, or hand-off to implementation or
draft.
</objective>
@${CLAUDE_SKILL_DIR}/../../meta/ase-format-task.md
@${CLAUDE_SKILL_DIR}/../../meta/ase-format-meta.md
@${CLAUDE_SKILL_DIR}/../../meta/ase-common-task.md
@${CLAUDE_SKILL_DIR}/../../meta/ase-common-approach.md
@${CLAUDE_SKILL_DIR}/../../meta/ase-tenets.md
Procedure
---------
<define name="apply-refinement">
Determine the *kind of change* of the refined plan:
- If <getopt-option-mode/> is `craft`, `refactor`, `resolve`, or
`specify`: Set <task-kind/> to `CRAFTING`, `REFACTORING`,
`RESOLVING`, or `SPECIFYING` correspondingly, and set
<task-kind-changed>true</task-kind-changed>.
- Else if <issue-id/> is not empty (`auto` with a retrieved analyzer
issue): Set <task-kind/> to `RESOLVING`, as the refinement fixes a
reported problem, and set <task-kind-changed>true</task-kind-changed>.
- Else (`auto`): Set <task-kind/> to the value of the `Kind:`
frontmatter key of <task-content/> (or, if it is absent or invalid,
*infer* it from the plan content, defaulting to `CRAFTING`), and set
<task-kind-changed>false</task-kind-changed>.
You *MUST* then first forget all previous internalized tenets and then
freshly internalize and strictly honor the **GENERIC TENETS** and the
**<task-kind/> TENETS** of the **ASE Tenets** in the following
refinement of the plan. Do not output anything.
<if condition="<task-kind/> is equal `SPECIFYING`">
<expand name="task-spec-format"/>
</if>
Treat the <instruction/> as a *refinement instruction* for
the plan, and update <task-content/> in-place by *applying* the
requested <instruction/> to the *plan*.
When refining the plan this way, preserve the overall structure of the
plan and only modify what the user actually requested. Do *not* rewrite
unrelated sections of the plan.
<if condition="<getopt-option-int-source-dir/> is not empty">
The *code basis* of the task is the separate working copy
<getopt-option-int-source-dir/> (e.g. a checkout of the branch of its
`Source` key): read every project file the <instruction/> requires
*exclusively* from there, instead of from the current working copy.
</if>
Attachment blocks of the "backmatter" are *never* dropped by a
refinement, unless the <instruction/> explicitly asks for it. Their
`Data` payloads are *elided* to `[elided: <n/> lines]` markers, which
you *MUST* keep *verbatim*, as `ase_task_save` restores them. Only if
the <instruction/> requires reading or changing the payload of an
attachment, fetch it via the `ase_task_attachment(id:
"<ase-task-id/>", type: "<type/>")` tool of the `ase` MCP server (with
<type/> being the value of its `Type` key), and replace its marker with
the *complete* changed payload as a `|4+` (or `|4-`) literal block
scalar according to the plan <format/>. *Remember* every attachment block whose content the
applied <instruction/> changed as *touched*, so its `Modified` key is
refreshed together with the frontmatter in step 3.1. An attachment the
<instruction/> did not change stays *verbatim* -- an implementation
draft attachment (`Type` key value `text/x-diff; charset=utf-8;
kind="draft"`, from `ase-task-implement --draft`) hence
turns *stale* through a "body" change by its `Modified` key falling
behind the frontmatter, which step 3.3 reports.
<if condition="<task-kind-changed/> is equal `true`">
Set the `Kind:` frontmatter key of <task-content/> to <task-kind/> --
*creating* the key at its position in the key order of the plan
<format/> if it is absent.
</if>
Set <task-content-dirty>true</task-content-dirty>.
</define>
<define name="generate-plan">
<expand name="task-ground-plan" arg1="<getopt-option-int-source-dir/>"/>
Determine the *kind of change* of the new plan:
- If <getopt-option-mode/> is `craft`, `refactor`, `resolve`, or
`specify`: Set <task-kind/> to `CRAFTING`, `REFACTORING`,
`RESOLVING`, or `SPECIFYING` correspondingly.
- Else if <issue-id/> is not empty (`auto` with a retrieved analyzer
issue): Set <task-kind/> to `RESOLVING`, as the plan fixes a
reported problem.
- Else (`auto`): *Infer* the <task-kind/> from the <instruction/>:
set to `SPECIFYING` if the plan predominantly creates or revises the
statements of the `SPEC` artifacts, set to `RESOLVING` if it
predominantly fixes a defect, set to `REFACTORING` if it
predominantly re-structures existing artifacts without changing
their observable behavior, and set to `CRAFTING` otherwise (also
the default if the inference stays inconclusive).
Set <approach-kind/> to `specification`, `resolution`, `refactoring`,
or `crafting` for the <task-kind/> `SPECIFYING`, `RESOLVING`,
`REFACTORING`, or `CRAFTING` correspondingly. You *MUST* then first
forget all previous internalized tenets and then freshly internalize
and strictly honor the **GENERIC TENETS** and the **<task-kind/>
TENETS** of the **ASE Tenets** in the following composition of the
plan. Do not output anything.
<if condition="<task-kind/> is equal `SPECIFYING`">
<expand name="task-spec-format"/>
</if>
<if condition="
<task-kind/> is equal `RESOLVING` and
<ase-project-boxing/> is not equal `black` and
<ase-headless/> is not equal `true`
">
Investigate and *figure out details* related to the problem of the
<instruction/> and report them with the following <template/>:
<template>
<ase-tpl-bullet-signal/> **PROBLEM CONTEXT**: *<context/>*
<affected-code-excerpt/>
<optional-diagram/>
<ase-tpl-bullet-signal/> **PROBLEM DETAILS**: *<summary/>*
● [...]
● [...]
● [...]
</template>
Hints:
- Give a short one-sentence <context/> of the problem plus a short
excerpt of the affected code <affected-code-excerpt/>.
- Give a short one-sentence <summary/> of the problem plus *precise*
but *brief* code processing information to understand the problem.
Try to keep the number of bullet points (●) in the range of 1-4.
- In case of a *complex context situation* with complex *structure*
(layout, components, dependencies, etc.), complex *control flow*
(branching, concurrency, etc.), complex *state machine* (states,
transitions, etc.), complex *data flow* (actors, messages, etc.), or
complex *data structure* (classes, entities, relationships, etc.),
visualize it with an optional diagram <optional-diagram/> by
building a Mermaid specification <mermaid-spec/> (e.g. `flowchart
TB`, `stateDiagram-v2`, `sequenceDiagram`, `classDiagram`, or
`erDiagram`, depending on intent) and dispatching the rendering
to the `ase-meta-diagram` sub-agent by calling the tool
`Agent(description: "Diagram Rendering", subagent_type:
"ase:ase-meta-diagram", prompt: <mermaid-spec/>,
run_in_background: false)`, reproducing its
returned fenced code block verbatim. Omit <optional-diagram/>
entirely for simple or purely local situations.
</if>
<if condition="<getopt-option-approach/> is equal `true`">
Determine the overall approach of the new plan, based on the
<instruction/> and the grounding in the project:
<expand name="approach-select"
arg1="<approach-kind/>"
arg2="◉ task: **<ase-task-id/>**"></expand>
If <chosen-approach/> is empty, only output the following <template/> and
then immediately *STOP* processing the entire current skill:
<template>
⧉ **ASE**: ◉ task: **<ase-task-id/>**, ▶ status: **plan generation cancelled**
</template>
</if>
<else>
Set <chosen-approach></chosen-approach> (empty). Do not output anything.
</else>
Create a new plan from scratch and store the result as
<task-content/> by closely following the defined plan format
<format/> and injecting into it all the information from
the <instruction/>, the <chosen-approach/> (if not empty), all
decisions you derived from the <instruction/> and the <chosen-approach/>, and
the grounding in the project. Set the `Kind:` frontmatter key to
<task-kind/>.
<if condition="<task-kind/> is equal `RESOLVING`">
The plan *MUST* carry code references, a precise description of the
problem, the resolution approach, a preview of the *unified
diff* of the necessary code changes, and -- unless
<getopt-option-unverified/> is equal `true` -- a possible way to verify the
success of the resolution.
</if>
<if condition="<getopt-option-unverified/> is equal `true`">
You *MUST* completely omit the `## VERIFICATION (WHEN)` section
(including its heading and all of its bullet points) from
<task-content/>.
</if>
Call the `ase_timestamp(format: "yyyy-LL-dd HH:mm")` tool of the
`ase` MCP server and use the `text` field of its response
for fresh <timestamp-created/> and <timestamp-modified/>
information. Then insert the current <ase-task-id/>,
<timestamp-created/>, and <timestamp-modified/> information.
Set <task-content-dirty>true</task-content-dirty>.
</define>
<define name="handoff-args">
Set <args></args> (set args to empty).
<if condition="the plan was saved via `ase_task_save` in step 3.2">
Set <args>--int-reuse-task</args>.
</if>
<if condition="<getopt-option-next/> is not equal `none`">
Set <args><args/> --next <getopt-option-next/></args>
</if>
</define>
1. **Determine Task and Instruction:**
1. Set <instruction><getopt-arguments/></instruction> initially.
Set <issue-id></issue-id> (empty),
<task-allocated>false</task-allocated>, and
<task-origin>task inherited</task-origin>.
Inherit the always existing <ase-task-id/> from the current context.
Inherit the always existing <ase-session-id/> from the current context.
Do not output anything.
2. Resolve a potential analyzer issue:
<if condition="
<instruction/> has the format `[<id/>:] <candidate/>` where
the optional <id/> matches the regexp `^[a-zA-Z0-9#][a-zA-Z0-9#_-]*$` and
<candidate/> matches the regexp `^([a-zA-Z][a-zA-Z0-9_]*-)?[PT]\d+$`
">
The <candidate/> may be a bare issue identifier (like `P1`,
`T1`, or `<prefix>-P1`) previously produced by
`ase-code-analyze` or `ase-arch-analyze`. Call the
`ase_kv_get(key: "ase-issue-<candidate/>")` tool of the `ase`
MCP server to retrieve the persisted problem description. If the
returned `text` is non-empty:
1. Set <issue-id><candidate/></issue-id> and
<instruction><text/></instruction>.
2. If <id/> is given, set <ase-task-id><id/></ase-task-id> and
<task-origin>task given</task-origin>, and call the
`ase_task_id(id: "<ase-task-id/>", session:
"<ase-session-id/>")` tool from the `ase` MCP server to
switch the task.
3. Only output the following <template/>:
<template>
⧉ **ASE**: ◉ task: **<ase-task-id/>**, ⇌ issue: **<issue-id/>**, ▶ status: **issue retrieved**
</template>
Otherwise, keep <instruction/> unchanged, so it is treated as a
task id resp. as an instruction below. Do not output anything.
</if>
3. React on task and/or instruction:
1. <if condition="
<issue-id/> is empty and
<instruction/> matches the regexp `^[a-zA-Z0-9#][a-zA-Z0-9#_-]*$`
">
Set <ase-task-id><instruction/></ase-task-id> (set task
id to instruction) and <instruction></instruction> (set
instruction empty), call the `ase_task_id(id: "<ase-task-id/>",
session: "<ase-session-id/>")` tool from the `ase` MCP
server to switch the task, and then only output the
following <template/>:
<template>
⧉ **ASE**: ◉ task: **<ase-task-id/>**, ▶ status: **task given**
</template>
</if>
2. <elseif condition="
<issue-id/> is empty and
<instruction/> has the format `<id/>: <text/>` where
<id/> matches the regexp `^[a-zA-Z0-9#][a-zA-Z0-9#_-]*$` and
<text/> is *empty*
">
Set <instruction></instruction> (set instruction to empty)
and <ase-task-id><id/></ase-task-id> (set task id to
id) and call the `ase_task_id(id: "<ase-task-id/>", session:
"<ase-session-id/>")` tool from the `ase` MCP server to
switch the task, and then only output the following
<template/>:
<template>
⧉ **ASE**: ◉ task: **<ase-task-id/>**, ▶ status: **task given**
</template>
</elseif>
3. <elseif condition="
<issue-id/> is empty and
<instruction/> has the format `<id/>: <text/>` where
<id/> matches the regexp `^[a-zA-Z0-9#][a-zA-Z0-9#_-]*$` and
<text/> is *not empty*
">
Set <instruction><text/></instruction> (set instruction to
text) and <ase-task-id><id/></ase-task-id> (set task id
to id) and call the `ase_task_id(id: "<ase-task-id/>", session:
"<ase-session-id/>")` tool from the `ase` MCP server to
switch the task, and then only output the following
<template/>:
<template>
⧉ **ASE**: ◉ task: **<ase-task-id/>**, ▶ status: **task given**
⧉ **ASE**: ◉ task: **<ase-task-id/>**, ⇌ instruction: **<instruction/>**, ▶ status: **instruction given**
</template>
</elseif>
4. <elseif condition="
<instruction/> is not empty
">
Only output the following <template/>, where <task-origin/>
is `task given` if step 1.2 switched the task:
<template>
⧉ **ASE**: ◉ task: **<ase-task-id/>**, ▶ status: **<task-origin/>**
⧉ **ASE**: ◉ task: **<ase-task-id/>**, ⇌ instruction: **<instruction/>**, ▶ status: **instruction given**
</template>
</elseif>
5. <elseif condition="
<instruction/> is empty
">
Only output the following <template/>:
<template>
⧉ **ASE**: ◉ task: **<ase-task-id/>**, ▶ status: **task inherited**
</template>
</elseif>
2. **Determine Plan:**
1. Determine any existing plan content:
<if condition="
<getopt-option-int-reuse-task/> is equal `true`
*and* an `ase_task_save(id: '<ase-task-id/>', ...)` tool call
exists earlier in the current session
*and* the `text` *output* field of the most recent such
`ase_task_save` tool call carries a `<task-plan-tag>`
delimiter line
*and* the `text` *argument* of that call carries no `Effort:`
frontmatter key without <hash/> (a bare size like `Effort: M`,
which the task store stamped or dropped on that save, see the
plan <format/>)
">
Set <text/> to the `text` *argument* of the most recent
`ase_task_save(id: '<ase-task-id/>', ...)` tool call -- this
is the *authoring form* of the plan and *MUST NOT* be
confused with the `text` *output* field of that call --
*without* calling `ase_task_load` again. Set
<task-render></task-render> (set the rendering-prepared plan
to empty, as it is re-derived in step 3.2 or 3.3). Set
<task-tag/> to the content enclosed in the `<task-plan-tag>`
delimiter line of the `text` *output* field of that
`ase_task_save` tool call (the *entity tag* of the plan as
saved by it). Set <status>plan reused</status>. Do not
output anything.
</if>
<else>
Call the `ase_task_load(id: "<ase-task-id/>", variant:
"both", tag: true)` tool of the `ase` MCP server to load any existing
plan content in *both* of its forms, with the payloads of all
attachments *elided* to `[elided: <n/> lines]` markers (the
default of its `attachments` argument). From the `text` output
field of this `ase_task_load` tool call, set <text/> to the
content enclosed in the `<task-plan-source>` delimiter lines
(the *authoring form*, the only form which is ever edited and
persisted), set <task-render/> to the content enclosed in
the `<task-plan-render>` delimiter lines (the
*rendering-prepared* form, used for *display only*), and set
<task-tag/> to the content enclosed in the `<task-plan-tag>`
delimiter line (the *entity tag* of the loaded plan, or empty
if absent, as no plan exists yet). The delimiter lines themselves are *never* part of
any form. Do not output anything related to this MCP tool call. Set
<status>plan loaded</status>.
</else>
Set <task-content-dirty>false</task-content-dirty>.
- If <text/> starts with `ERROR:` or `WARNING:`:
Silently ignore the MCP error.
Set <task-content/> to empty.
Set <task-render/> to empty.
Do not output anything.
- If <text/> starts NOT with `ERROR:` and NOT with `WARNING:`:
Set <task-content><text/></task-content> (set task content to text).
Only output the following <template/>:
<template>
⧉ **ASE**: ◉ task: **<ase-task-id/>**, ▶ status: **<status/>**
</template>
2. <if condition="<task-content/> is empty AND <instruction/> is empty">
Ask the user interactively, without a special tool, for the
initial plan content with a single question:
`**No plan content yet. What is the task you want to plan?**`
Then set <instruction/> to the response of the user and only
output the following <template/>:
<template>
⧉ **ASE**: ◉ task: **<ase-task-id/>**, ⇌ instruction: **<instruction/>**, ▶ status: **instruction given**
</template>
</if>
3. <if condition="
<ase-task-id/> is equal `default` AND
<task-content/> is empty AND
<instruction/> is not empty
">
Call the `ase_task_newid(title: "<title/>", proposal:
"<proposal/>")` tool from the `ase` MCP server, where <title/> is
a brief title summarizing <instruction/> and <proposal/> is a
task id derived from <instruction/>, which consists of two
lower-case words concatenated with a `-` character, and set
<ase-task-id/> to the `id` field of its response -- the tool
derives the id according to the task id scheme of the project,
so you *MUST* *NEVER* assemble it yourself. Then call the
`ase_task_id(id: "<ase-task-id/>", session: "<ase-session-id/>")`
tool from the `ase` MCP server to switch the task, set
<task-tag></task-tag> (empty, as no plan exists yet under the
new id) and <task-allocated>true</task-allocated>, and only
output the following <template/>:
<template>
⧉ **ASE**: ◉ task: **<ase-task-id/>**, ▶ status: **task allocated**
</template>
</if>
4. <if condition="<task-content/> is not empty AND
<instruction/> is not empty AND
<instruction/> is not equal <task-content/>">
*Determine previous-plan handling*:
- If <getopt-option-plan/> matches the regex `^(OVERWRITE|REFINE|PRESERVE)$`:
Honor the pre-selection of what to do with the previous plan.
Set <result><getopt-option-plan/></result>.
- If <getopt-option-plan/> is equal to `none`:
In the following, you *MUST* *NOT* use your built-in
<user-dialog-tool/> tool! Instead, you *MUST* just show a
custom dialog according to the expanded `custom-dialog`
definition. You *MUST* closely follow this definition:
<expand name="custom-dialog" arg1="--other">
Previous Plan: Should the previous plan content be overwritten, refined, or preserved?
OVERWRITE: Continue operation, overwrite previous plan.
REFINE: Continue operation, refine previous plan.
PRESERVE: Cancel operation, preserve previous plan.
</expand>
Check the tool <result/> and dispatch accordingly:
- If <result/> is `CANCEL` or `PRESERVE`:
Only output the following <template/> and then immediately
*STOP* processing this skill:
<template>
⧉ **ASE**: ◉ task: **<ase-task-id/>**, ▶ status: **plan preserved**
</template>
- If <result/> is `OVERWRITE`:
<expand name="generate-plan"/>
Only output the following <template/> and continue processing:
<template>
⧉ **ASE**: ◉ task: **<ase-task-id/>**, ▶ status: **plan overwritten**
⧉ **ASE**: ◉ task: **<ase-task-id/>**, ⇌ instruction: **<instruction/>**, ▶ status: **instruction given**
</template>
- If <result/> is `REFINE`:
<expand name="apply-refinement"/>
Only output the following <template/> and continue processing:
<template>
⧉ **ASE**: ◉ task: **<ase-task-id/>**, ▶ status: **plan refined**
⧉ **ASE**: ◉ task: **<ase-task-id/>**, ⇌ instruction: **<instruction/>**, ▶ status: **instruction given**
</template>
- If <result/> matches `OTHER: <text/>`:
Set <instruction><instruction/> <text/></instruction> (append
the user's free-text hint to the existing instruction).
<expand name="apply-refinement"/>
Only output the following <template/> and continue processing:
<template>
⧉ **ASE**: ◉ task: **<ase-task-id/>**, ▶ status: **plan refined**
⧉ **ASE**: ◉ task: **<ase-task-id/>**, ⇌ instruction: **<instruction/>**, ▶ status: **instruction given**
</template>
</if>
5. <if condition="no line of <task-content/> matches the case-insensitive regex `^\s*#+\s*TASK\b` AND <instruction/> is empty">
Set <instruction><task-content/></instruction> (set instruction to task content).
Set <task-content></task-content> (set task content to empty).
Set <task-content-dirty>true</task-content-dirty>.
Do not output anything.
</if>
6. <if condition="<task-content/> is empty AND <instruction/> is not empty">
<expand name="generate-plan"/>
Only output the following <template/> and continue processing:
<template>
⧉ **ASE**: ◉ task: **<ase-task-id/>**, ⇌ instruction: **<instruction/>**, ▶ status: **instruction given**
⧉ **ASE**: ◉ task: **<ase-task-id/>**, ▶ status: **plan generated**
</template>
</if>
3. **Iterative Plan Refinement Loop:**
*REPEAT* the following steps from 3.1 up to and including 3.4 in
a *LOOP* until the user selects `DONE`, `GRILL`, `IMPLEMENT`, or
`DRAFT`, or declines/cancels in the dialog of step 3.4:
1. *Update timestamp*:
<if condition="<task-content-dirty/> is 'true'">
Update <timestamp-modified/> with the current time in
ISO-style format, which has to be determined by calling the
`ase_timestamp(format: "yyyy-LL-dd HH:mm")` tool of the `ase`
MCP server and using the `text` field of its response. If the
frontmatter of <task-content/> carries a `Modified:` key *and*
the refinement changed the "body" (not only frontmatter keys or
attachments), update it with the new <timestamp-modified/>
value, as the key tracks "body" changes only. Then set the
`Modified:` key of every attachment block *touched* by the
refinement (see `apply-refinement`) to the very same
<timestamp-modified/> value -- *creating* the key at its position
in the key order of the plan <format/> if the block does not
carry it yet -- and forget the touched marks again, so a changed
attachment never falls behind the frontmatter.
Do not output anything.
</if>
2. *Persist plan*:
<if condition="<task-content-dirty/> is 'true'">
Call the `ase_task_save(id: "<ase-task-id/>", text:
"<task-content/>", render: true, tag: true)` tool of the `ase` MCP server --
if <task-tag/> is not empty, additionally with the argument
`base: "<task-tag/>"`, so the save is refused if the plan was
changed meanwhile by anybody else (instead of silently
overwriting that change), and if <task-tag/> is empty (no plan
existed yet), additionally with the argument `create: true`, so
the save is refused if the plan was created meanwhile by anybody
else -- to
persist the current plan -- <task-content/> always is the
*authoring form* of the plan and hence is persisted *as is* --
and then set <task-content-dirty>false</task-content-dirty>
again. If this call fails because the task already exists *and*
<task-allocated/> is `true` (a concurrent session took the
allocated id), allocate and switch to a new <ase-task-id/>
exactly as in step 2.3, set the `Id:` frontmatter key of
<task-content/> to it, and save again. This `ase_task_save` MCP
tool call is the *only* permitted way to persist the plan -- *NEVER* write the plan
file via `Write`/`Edit` or by executing a shell command.
Finally, *always* set <task-tag/> to the content enclosed in the
`<task-plan-tag>` delimiter line of the `text` *output* field of
this `ase_task_save` tool call (the entity tag of the just-saved
plan, to be passed as `base` on the next save of every
subsequent loop round), and set <task-render/> to the remaining
`text` *output* field
of this `ase_task_save` tool call (without this delimiter line) -- the rendering-prepared form
of the just-persisted plan, which is for *display only* and
*MUST NOT* be confused with the `text` *argument* passed into
that call -- so the rendering in step 3.3 stays consistent across
all loop rounds. Then take over the `Effort:` key *as stored*
into the authoring form, as the task store stamps a key without
<hash/> or drops a stale one on save (see the plan <format/>):
set the `Effort:` frontmatter key of <task-content/> to the one
of the frontmatter of <task-render/> (rendered from the stored
plan) -- *replacing* it, *creating* it at its position in the key
order of the plan <format/>, or *removing* it if <task-render/>
carries none -- changing *nothing else* of <task-content/> and
leaving <task-content-dirty/> untouched. Do not output anything
related to this MCP tool call except the following <template/>:
<template>
⧉ **ASE**: ◉ task: **<ase-task-id/>**, ▶ status: **plan saved**
</template>
Then set <task-allocated>false</task-allocated>, as the
allocated id is now taken by the saved plan. If <issue-id/> is
not empty, call the `ase_kv_delete(key: "ase-issue-<issue-id/>")`
tool of the `ase` MCP server to remove the now-planned analyzer
result from the key/value store and set <issue-id></issue-id>
(empty). Do not output anything related to these steps.
</if>
3. *Render plan*:
If <ase-headless/> is `true`, nobody reads the rendering, so
silently *skip* this entire step 3.3 (no MCP tool call and no
output at all) and continue with step 3.4.
<if condition="<task-render/> is empty">
Call the `ase_markdown_prepare(text: "<task-content/>")` tool of
the `ase` MCP server and set <task-render/> to the `text` output
field of this tool call. Do not output anything related to this
MCP tool call.
</if>
Treat <task-render/> as *verbatim* Markdown.
For the *rendering only*, drop the leading *frontmatter* block --
both `---` delimiters and all of their keys -- and instead place
the following column-aligned glyph lines *before* the
`# TASK: <title/>` heading, separated from it by an empty line,
omitting the line of every key absent from the frontmatter and
always omitting the `Type` key. The glyph lines *MUST* stay
*above* the heading, exactly where the frontmatter block sits in
the plan file, and *MUST NOT* be moved below it. This keeps the
`---` delimiters from rendering as a horizontal rule plus a
*setext heading*. This rewrite is *display-only* and *MUST NOT*
change <task-render/> or <task-content/> itself:
<format>
◉ **Id:** <task-id/>
⎈ **Created:** <timestamp-created/>
⚙ **Modified:** <timestamp-modified/>
⊞ **Group:** <task-group/>
◷ **Phase:** <task-phase/>
⇢ **After:** <task-after/>
◐ **Status:** <task-status/>
☯ **Kind:** <task-kind/>
⚖ **Effort:** <task-effort/>
⚑ **Tags:** <task-tags/>
⇤ **Source:** <task-source/>
⇢ **Changeset:** <task-changeset/>
⇥ **Target:** <task-target/>
</format>
Only output the following <template/>, so the user
can read the plan and react to it. Do *not* truncate,
summarize, or partially show the plan. Use the
following <template/>:
<template>
<ase-tpl-head title="TASK" subtitle="<task-id/>"/>
<task-render/>
<ase-tpl-foot title="TASK" subtitle="<task-id/>"/>
</template>
<if condition="the backmatter of <task-content/> contains an attachment
block with the `Type` key value `text/x-diff; charset=utf-8; kind="draft"`
which is *stale* according to the plan <format/> (its `Modified` key
is absent or older than the `Modified` key of the frontmatter)">
Directly *after* this <template/>, only output the following
<template/> and then give the corrective hint by expanding the
subsequent construct (which, depending on the configured
<ase-guidance-level/>, may expand into nothing and hence emit
no output at all):
<template>
⧉ **ASE**: ◉ task: **<ase-task-id/>**, ▶ WARNING: implementation draft attachment is **stale** (older than the plan)
</template>
<ase-tpl-hint level="minimal">
Run `/ase-task-implement --draft` again to re-create the implementation draft for the changed plan, as `/ase-task-integrate --draft` refuses a stale draft.
</ase-tpl-hint>
</if>
4. *Determine next step*:
- If <getopt-option-next/> is not equal to `none`:
Treat <getopt-option-next/> as a comma-separated chronological
list of pre-selected next-step tokens. *Split* it on `,`,
take the *first* token as <head/>, and store the remaining
tokens (joined back with `,`, or `none` if empty) into
<getopt-option-next/> so subsequent loop iterations or
downstream skills can consume the tail.
- If <head/> matches the regex `^(DONE|GRILL|IMPLEMENT|DRAFT)$`:
Honor the pre-selected token.
Set <result><head/></result>.
Set <instruction></instruction> (clear the instruction, as
any instruction carried in via the arguments was already
applied to the plan in step 2 before this loop), so that a
later `OTHER: <text/>` refinement correctly starts from a
*fresh* refinement instruction below.
- else:
Only output the following <template/> and then immediately
*STOP* processing the entire current skill:
<template>
⧉ **ASE**: ☻ skill: **ase-task-edit**, ▶ ERROR: invalid `--next` token: **<head/>**
</template>
- If <getopt-option-next/> is equal to `none`:
In the following, you *MUST* *NOT* use your built-in
<user-dialog-tool/> tool! Instead, you *MUST* just show a
custom dialog according to the expanded `custom-dialog`
definition. You *MUST* closely follow this definition:
<expand name="custom-dialog" arg1="--other">
Next Step: How would you like to proceed with the plan?
DONE: Mark plan finalized, exit planning loop.
GRILL: Hand off plan to grilling.
DRAFT: Hand off plan to implementation drafting.
IMPLEMENT: Hand off plan to implementation.
</expand>
Check the tool <result/> and dispatch accordingly:
- If <result/> is `DONE`:
*Break* out of the *loop*, only output the following <template/>
and then *STOP*. Do *not* implement the plan.
<template>
⧉ **ASE**: ◉ task: **<ase-task-id/>**, ▶ status: **plan finalized -- done**
</template>
- If <result/> is `GRILL`:
*Break* out of the *loop*.
<expand name="handoff-args"/>
Only output the following <template/> and then call the
`Skill(skill: "ase:ase-task-grill", args: "<args/>")` tool
to *grill* the finalized plan.
<template>
⧉ **ASE**: ◉ task: **<ase-task-id/>**, ▶ status: **plan finalized -- hand-off to grilling**
</template>
- If <result/> is `DRAFT`:
*Break* out of the *loop*.
<expand name="handoff-args"/>
Set <args><args/> --draft</args>. Only output the following
<template/> and then call the
`Skill(skill: "ase:ase-task-implement", args: "<args/>")` tool
to *draft* the implementation of the finalized plan.
<template>
⧉ **ASE**: ◉ task: **<ase-task-id/>**, ▶ status: **plan finalized -- hand-off to implementation draft**
</template>
- If <result/> is `IMPLEMENT`:
*Break* out of the *loop*.
<expand name="handoff-args"/>
Only output the following <template/> and then call the
`Skill(skill: "ase:ase-task-implement", args: "<args/>")` tool
to *apply* the finalized plan.
<template>
⧉ **ASE**: ◉ task: **<ase-task-id/>**, ▶ status: **plan finalized -- hand-off to implementation**
</template>
- If <result/> matches `OTHER: <text/>`:
Set <instruction><text/></instruction> (replace existing instruction).
<expand name="apply-refinement"/>
Finally, only output the following <template/> and then
*continue* the *loop* at step **3.1**!
<template>
⧉ **ASE**: ◉ task: **<ase-task-id/>**, ⇌ instruction: **<instruction/>**, ▶ status: **plan refined**
</template>
- If <result/> is `CANCEL`:
*Break* out of the *loop*, only output the following <template/>
and then *STOP*. Do *not* implement the plan.
<template>
⧉ **ASE**: ◉ task: **<ase-task-id/>**, ▶ status: **plan refinement cancelled**
</template>