ase-task-implement · git:20261020.4616a6a · 2026-10-20 · sha256 a4531a39d1a3d13c
ase-task-implement git:20261020.4616a6aA
Immutable. This exact content never changes and is served at /api/v1/blob/a4531a39d1a3d13c.
---
name: ase-task-implement
argument-hint: "[--help|-h] [--next|-n <option>[,...]] [--worktree|-w <name>] [--source|-s <source>] [--changeset|-c <changeset>] [--draft|-d] [--no-cleanup|-K] [--stateless|-S] [<id>]"
description: >
Implement current or given task plan, optionally as an implementation
draft attachment only. Use when the user calls to "implement", "realize",
"draft", "dry-run", or "test-drive" the "task", "plan", "spec", or
"specification".
user-invocable: true
disable-model-invocation: false
effort: xhigh
---
@${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-implement">
Implement a Task Plan
</purpose>
<expand name="getopt"
arg1="ase-task-implement"
arg2="--next|-n=(none|DONE|EDIT|INTEGRATE|DELETE)... --worktree|-w= --source|-s= --changeset|-c= --draft|-d --no-cleanup|-K --stateless|-S --int-reuse-task">
$ARGUMENTS
</expand>
<objective>
*Implement* the task plan by creating a corresponding, complete
*change set* from its *source* into its *changeset* location.
</objective>
@${CLAUDE_SKILL_DIR}/../../meta/ase-format-task.md
@${CLAUDE_SKILL_DIR}/../../meta/ase-common-task.md
@${CLAUDE_SKILL_DIR}/../../meta/ase-tenets.md
@${CLAUDE_SKILL_DIR}/../../meta/ase-common-code.md
@${CLAUDE_SKILL_DIR}/../../meta/ase-common-changeset.md
Procedure
---------
1. **Determine Task:**
1. Set <instruction><getopt-arguments/></instruction> initially, with any
leading and trailing whitespace stripped.
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. React on task id:
<expand name="task-react-id" arg1="ase-task-implement"></expand>
3. Resolve the draft shorthand: if <getopt-option-draft/> is `true`
and <getopt-option-changeset/> is not empty, only output the
following <template/> and then immediately *STOP* processing the
entire current skill:
<template>
⧉ **ASE**: ◉ task: **<ase-task-id/>**, ▶ ERROR: options `--draft` and `--changeset` are mutually exclusive
</template>
Otherwise, if <getopt-option-draft/> is `true`, set
<getopt-option-changeset>attachment:draft</getopt-option-changeset>,
so the change set lands as the *implementation draft* in the
attachment `draft` of the plan only. Do not output anything.
2. **Determine Operation:**
1. Determine the current task plan content:
<expand name="task-load-content"></expand>
2. If the <task-content/> is still empty, complain and tell the user to
use the `ase-task-edit` skill first to create a task plan. Then
immediately stop processing this skill.
3. Internalize the tenets stated by the plan:
<expand name="code-tenets-from-plan"></expand>
3. **Prepare Source and Changeset:**
The *source* (code basis) and the *changeset* (location of the
change set) are controlled by the `Source:` and `Changeset:`
frontmatter keys of the plan, which the `--source` and
`--changeset` options override *ad-hoc* without changing the plan.
The `worktree` value of the source refers to the *origin working
copy* the skill was started in, the `worktree` value of the
changeset to the *context worktree*, selected by the `--worktree`
option (both are the same without `--worktree`). A context worktree
created by `--worktree` carries its *own* branch, which starts at
the source, so the source branch itself is never checked out there
and stays available as the integration target.
1. Set <task-source/> to <getopt-option-source/> if it is not
empty, otherwise to the value of the `Source:` frontmatter key
of <task-content/>, or to the configured default
<ase-project-task-default-source/> if the key is absent, and
parse it:
<expand name="changeset-value"
arg1="Source"
arg2="<task-source/>"
arg3="`worktree`, `branch`"
arg4="◉ task: **<ase-task-id/>**"></expand>
Set <source-type><value-type/></source-type> and
<source-name><value-name/></source-name>.
2. Set <task-changeset/> to <getopt-option-changeset/> if it is not
empty, otherwise to the value of the `Changeset:` frontmatter key
of <task-content/>, or to the configured default
<ase-project-task-default-changeset/> if the key is absent, and
parse it:
<expand name="changeset-value"
arg1="Changeset"
arg2="<task-changeset/>"
arg3="`worktree`, `branch`, `attachment`"
arg4="◉ task: **<ase-task-id/>**"></expand>
Set <changeset-type><value-type/></changeset-type> and
<changeset-name><value-name/></changeset-name>.
<if condition="<task-changeset/> is not `attachment:draft` and the backmatter of <task-content/> contains an attachment block with the `Type` key value `text/x-diff; charset=utf-8; kind="draft"`, whose `Desc` key carries no `merged <commit/>` value">
The plan carries an undelivered *implementation draft*, which
only an `attachment:draft` changeset builds upon, so this run
*ignores* it and implements the plan from scratch into
<task-changeset/>. Only output the following <template/>,
directly followed by the hint, and then *continue* processing:
<template>
⧉ **ASE**: ◉ task: **<ase-task-id/>**, ▶ WARNING: implementation draft attachment is **ignored** for changeset **<task-changeset/>**
</template>
<ase-tpl-hint level="minimal">
Use `/ase-task-implement --draft` to build upon the draft, or `/ase-task-integrate --draft` to deliver it.
</ase-tpl-hint>
</if>
3. Determine the *source commit* <source-commit/>: if
<source-type/> is `worktree`, capture the output of the command
`git rev-parse HEAD` (the skill runs inside the origin working
copy); if it is `branch`, capture the output of the command
`git rev-parse --verify --quiet "refs/heads/<source-name/>"`.
If the command fails, only output the following <template/> and
then immediately *STOP* processing the entire current skill,
leaving the working copy *untouched* (so a bad source never
leaves a context worktree behind):
<template>
⧉ **ASE**: ◉ task: **<ase-task-id/>**, ▶ ERROR: source **<task-source/>** does not exist
</template>
4. <if condition="<getopt-option-worktree/> is not empty and <changeset-type/> is not `worktree`">
The context worktree serves the `worktree` changeset only, so a
`branch:` or `attachment:` changeset would leave it unused (e.g.
on a mistyped option). Only output the following <template/> and
then immediately *STOP* processing the entire current skill,
leaving the working copy *untouched*:
<template>
⧉ **ASE**: ◉ task: **<ase-task-id/>**, ▶ ERROR: option `--worktree` requires a `worktree` changeset (got **<task-changeset/>**)
</template>
</if>
Otherwise, prepare the context worktree, whose own branch -- if
created together with it -- starts at <source-commit/>:
<expand name="changeset-context"
arg1="<getopt-option-worktree/>"
arg2="◉ task: **<ase-task-id/>**"
arg3="false"
arg4="true"
arg5="<source-commit/>"></expand>
5. Determine the *work directory* <work-dir/> -- the worktree in
which the implementation happens -- according to <changeset-type/>:
- `worktree`: The change set stays *uncommitted* in the context
worktree, so set <work-dir><context-dir/></work-dir>.
- <if condition="<context-dir/> differs from <origin-dir/>">
The context worktree carries its *own* branch: a freshly
created one already starts at <source-commit/>, while a
reused one keeps its own base, so earlier work in it is
*continued*. The source branch is *never* checked out in
the context worktree (it may be checked out in the origin
working copy, and it is the integration target of
`Target: source`), so nothing is switched. Do not output
anything.
</if>
- <elseif condition="<source-type/> is `branch` and the branch checked out in <origin-dir/> (according to the command `git branch --show-current`) differs from <source-name/>">
The origin working copy is *switched* to <source-name/>
in place: if the command `git status --porcelain` reports
any output, switching would drag the uncommitted changes
onto the other branch, so only output the following
<template/>, directly followed by the hint, and then
immediately *STOP* processing the entire current skill,
leaving the working copy *untouched*:
<template>
⧉ **ASE**: ◉ task: **<ase-task-id/>**, ▶ ERROR: working copy has uncommitted changes -- cannot switch to branch **<source-name/>** in place
</template>
<ase-tpl-hint level="minimal">
Commit or stash the uncommitted changes first, or use `--worktree <name>` to implement inside an isolated worktree instead.
</ase-tpl-hint>
Otherwise, run the command
`git switch "<source-name/>"`, and, if it fails (e.g.
because the branch is checked out in another worktree),
only output the following <template/> and then
immediately *STOP* processing the entire current skill:
<template>
⧉ **ASE**: ◉ task: **<ase-task-id/>**, ▶ ERROR: branch **<source-name/>** failed to switch
</template>
Otherwise, only output the following <template/>:
<template>
⧉ **ASE**: ◉ task: **<ase-task-id/>**, ⎇ branch: **<source-name/>**, ▶ status: **branch switched**
</template>
</elseif>
- `branch`: The change set is *committed* onto the branch
<changeset-name/> inside a worktree carrying this branch.
Determine the *existing worktrees* by running the command
`git worktree list --porcelain` (taken exactly as given).
- If the branch <changeset-name/> is checked out in a
registered worktree, set <work-dir/> to its directory,
<work-label/> to its path, and
<work-created>false</work-created>, as this *pre-existing*
worktree is never removed by this skill. If the command
`git -C "<work-dir/>" status --porcelain` reports any
output, the change set could not be committed separately,
so only output the following <template/> and then
immediately *STOP* processing the entire current skill:
<template>
⧉ **ASE**: ◉ task: **<ase-task-id/>**, ▶ ERROR: worktree **<work-label/>** of branch **<changeset-name/>** has uncommitted changes
</template>
- Otherwise, set <work-id/> to <changeset-name/> with every
character other than `A-Z`, `a-z`, `0-9`, `_`, and `-`
replaced by `-`, then every run of multiple `-` reduced
to a single `-`, and finally all leading and trailing `-`
and `_` removed (e.g., `feature-x` for `feature/-x`),
determine <work-dir/> by calling the
`ase_worktree_path(id: "<work-id/>", create: true)` tool of
the `ase` MCP server (you *MUST* *NEVER* assemble this
path yourself), and set
<work-label>.ase/worktree/<work-id/></work-label>. If
this tool call fails or the directory <work-dir/> already
exists, only output the following <template/> and then
immediately *STOP* processing the entire current skill:
<template>
⧉ **ASE**: ◉ task: **<ase-task-id/>**, ▶ ERROR: worktree **<work-id/>** for branch **<changeset-name/>** cannot be created
</template>
If the branch <changeset-name/> exists according to
`git branch --list`, create the worktree by running the
command `git worktree add "<work-dir/>" "<changeset-name/>"`,
otherwise create the branch from the source together with
the worktree by running the command
`git worktree add -b "<changeset-name/>" "<work-dir/>" "<source-commit/>"`
(each taken exactly as given). If the command fails, only
output the same error <template/> as above and then
immediately *STOP* processing the entire current skill.
Otherwise, set <work-created>true</work-created> and only
output the following <template/>:
<template>
⧉ **ASE**: ◉ task: **<ase-task-id/>**, ◉ worktree: **<work-label/>**, ⎇ branch: **<changeset-name/>**, ▶ status: **worktree created**
</template>
- `attachment`: The change set is made and verified in a
*temporary* worktree, detached at <source-commit/>, and
afterwards stored as an attachment of the plan only, leaving
all artifacts untouched.
1. <if condition="the backmatter of <task-content/> contains an attachment block with the `Type` key value `text/x-diff; charset=utf-8; kind="<changeset-name/>"`, whose `Desc` key carries no `merged <commit/>` value, and which is *stale* according to the plan <format/> (its `Modified` key is absent or older than the `Modified` key of the frontmatter)">
The change set of a *previous* run was created for an
*earlier* version of the plan, so building on it would
silently carry over changes the plan no longer asks for,
and dropping it would leave its `[x]` and `[/]`
bullet-points unrealized. Only output the following
<template/>, directly followed by the hint, and then
immediately *STOP* processing the entire current skill,
leaving the plan and the artifacts *untouched*:
<template>
⧉ **ASE**: ◉ task: **<ase-task-id/>**, ▶ ERROR: change set attachment **<changeset-name/>** is **stale** (older than the plan)
</template>
<ase-tpl-hint level="minimal">
Remove the attachment and reset the `[x]` and `[/]` checkboxes of the plan, then run `/ase-task-implement --changeset <task-changeset/>` again.
</ase-tpl-hint>
</if>
2. Set <work-hash/> to the first 8 characters of the output
of the `ase_mint(type: "sha1", hint:
"<ase-task-id/>:<changeset-name/>:implement")` tool of the
`ase` MCP server, which keeps <work-id/> *unique* per task
and attachment. Set <work-id/> to <ase-task-id/> with all
characters other than `A-Z`, `a-z`, `0-9`, `_`, and `-`
stripped, followed by
`-<changeset-name/>-implement-<work-hash/>`, and
determine <work-dir/> by calling the
`ase_worktree_path(id: "<work-id/>", temp: true, create:
true)` tool of the `ase` MCP server, which places it into
the namespace of the *temporary* worktrees, disjoint from
all other worktrees. You *MUST* *NEVER* assemble this path
yourself.
3. <if condition="<work-dir/> exists">
If <work-dir/> is a worktree registered according to
`git worktree list --porcelain` and its record carries a
`detached` line, it is the *leftover* of an earlier run
which stopped before its cleanup, and its partial state
must *not* be reused: remove it by running the commands
`git worktree remove --force "<work-dir/>"` and
`git worktree prune` (taken exactly as given), ignoring
any failure. Otherwise, it is *not* owned by this skill,
so only output the following <template/> and then
immediately *STOP* processing the entire current skill,
leaving <work-dir/> and the task plan *untouched*:
<template>
⧉ **ASE**: ◉ task: **<ase-task-id/>**, ▶ ERROR: directory **<work-id/>** for attachment **<changeset-name/>** exists, but is no temporary worktree
</template>
</if>
4. Create the worktree by running the command
`git worktree add --detach "<work-dir/>" "<source-commit/>"`
(taken exactly as given). As it starts at the source
commit, *uncommitted* changes of the source are *not*
carried over.
5. <if condition="the backmatter of <task-content/> contains an attachment block with the `Type` key value `text/x-diff; charset=utf-8; kind="<changeset-name/>"`, whose `Desc` key carries no `merged <commit/>` value">
This block carries the change set of a *previous* run,
which realized the `[x]` and `[/]` bullet-points. A block
whose `Desc` key carries a `merged <commit/>` value was
already *delivered* by `ase-task-integrate`, so it is *not*
re-applied, and the change set of this run starts afresh
at the source commit and replaces it below. As its `Data`
payload is *elided* in <task-content/>, fetch it via the
`ase_task_attachment(id: "<ase-task-id/>", type: "text/x-diff;
charset=utf-8; kind=\"<changeset-name/>\"")` tool of the `ase`
MCP server, whose `text` output field is the payload
*verbatim* (without any indentation). Re-establish
it in the worktree by applying this payload *verbatim*, e.g. via
`git -C "<work-dir/>" apply --3way`, and re-apply hunks
which no longer apply to a meanwhile drifted source
manually. The change set of this run is built *on top* of
it, so the change set captured below is *cumulative*.
</if>
If any of these sub-steps fails, remove the worktree as above
(if created by sub-step 4), only output the following
<template/>, and then immediately *STOP* processing the
entire current skill, leaving the task plan *untouched*:
<template>
⧉ **ASE**: ◉ task: **<ase-task-id/>**, ▶ ERROR: temporary worktree for attachment **<changeset-name/>** cannot be prepared
</template>
4. **Create Implementation:**
1. <if condition="<getopt-option-stateless/> is not equal `true` and <ase-project-task-lifecycle/> is `team` or `enterprise`">
Mark the plan as being implemented: set the `Status:` key of
<task-content/> to `IMPLEMENTING` (*creating* the key at its
position in the key order of the plan <format/> if absent), but
*only* if `IMPLEMENTING` is reachable from the current state
along the transitions of the task lifecycle model (for the
`team` model from `PLANNING` or `STALLED`, for the `enterprise`
model from `DRAFTED` via `PLANNING` and `PLANNED`, or from
`PLANNED` or `STALLED`), and persist this frontmatter-only change
-- without refreshing the `Modified:` key -- by taking over the
stored `Effort:` key and calling the `ase_task_save` tool of the
`ase` MCP server *exactly* as described for the final save in
sub-step 5 below. Do not output anything.
</if>
2. Perform a *final implementation* of the task plan inside
<work-dir/> by modifying the *artifacts* with a corresponding,
complete *change set*, following and honoring the task plan in
<task-content/>:
<expand name="changeset-land" arg1="<work-dir/>"></expand>
<if condition="<task-kind/> is `SPECIFYING`, or the task plan otherwise creates, revises, or removes statements of `SPEC` artifacts">
<expand name="task-spec-format"/>
Keep every changed `SPEC` artifact conformant to the `SPEC`
format (structure, object kinds, properties, ids, `[[xxx]]`
references, and the `Modified:` timestamp rule). Read the
**SpecBook SCHEMA Model** of the project (resolved as described in
`ase-format-spec.md`) to learn the allowed object kinds,
properties, nestings, and value constraints, and resolve the
`SPEC` artifacts by running the command
`ase artifact list --kind spec` *once* with <work-dir/> as its
working directory and parsing its `- <file/>` output lines into
the file list -- the `ase_artifact_list` tool always resolves
against the *project* working copy and hence *MUST* *NOT* be used
here. Do not output anything.
</if>
Set <decisions></decisions> (empty) and
<open-points></open-points> (empty). They collect, one entry
each, the decisions you take on your own while implementing and
whatever ends up waiting for the *user*.
The implementation is *complete or it is not done*: you *MUST*
*NEVER* conclude this step while any point of the task plan is
still unimplemented -- not because the change set already grew
large, not because the remaining points look secondary or
cosmetic, and not because an open question stands in the way.
Work through *every* point of the plan within this single run.
Open questions therefore *MUST* *NOT* end the run: whenever the
plan leaves a detail undecided or admits several defensible
alternatives, *decide it yourself* -- picking what best fits the
surrounding artifacts and the internalized tenets -- and append
the decision plus a half-sentence rationale to <decisions/>,
instead of asking the user and stopping. Only a *genuine
blocker*, which no defensible assumption can bridge (a missing
credential, an inaccessible external system), may leave a point
unimplemented; append such a point to <open-points/> instead,
naming what remains open and why. Append to <open-points/> as
well whatever else now waits for the user once this run ends --
follow-ups you deliberately left out of scope, each with its
reason, and results which genuinely need their review.
You *MUST* *skip* every bullet-point of <task-content/> in
checkbox state `[-]` (cancelled) or `[>]` (deferred): neither
realize its <text/> in the change set nor perform its check, and
do *not* count it against the completeness of the change set.
Its <text/> stays *context only*, e.g. to understand the other
bullet-points.
You *MUST* also *skip* every bullet-point of <task-content/> in
checkbox state `[x]` (done), as it was already fully resolved by
a previous run: neither realize its <text/> again nor perform its
check again, but *do* count it as *complete* for the change set.
Its <text/> stays *context only*, too.
You *MUST* treat every bullet-point of <task-content/> in
checkbox state `[?]` (question) exactly like one in state `[ ]`
(todo), i.e., as a *regular* todo, as its grilling question just
stayed unanswered: realize its <text/> or perform its check.
You *MUST* *re-examine* every bullet-point of <task-content/> in
checkbox state `[/]` (incomplete), as a previous run resolved it
only *partially*: check which parts of its <text/> are not yet
realized or verified by the artifacts, and then realize or check
*only* these remaining parts.
<if condition="<task-content/> does NOT contain a `## VERIFICATION (WHEN)` section heading">
The task plan deliberately *omits* the `## VERIFICATION (WHEN)`
section. You *MUST* therefore *strictly skip* the entire
verification phase after modifying the source files: do *NOT*
run any build, do *NOT* run any tests, do *NOT* run any linter,
do *NOT* run any type-checker, do *NOT* execute the modified
program, and do *NOT* otherwise verify the change set in any
way.
</if>
3. Store the change set according to <changeset-type/>:
- `worktree`: Leave the change set *uncommitted* in
<work-dir/>. Do not output anything.
- `branch`: Stage the change set by running the command
`git -C "<work-dir/>" add --all`. If the command
`git -C "<work-dir/>" diff --cached --quiet` fails (i.e.
something is staged), craft a commit <message/> in the
format `<type/>: <summary/>`, where <type/> is one of
`FEATURE`, `IMPROVEMENT`, `BUGFIX`, `UPDATE`, `CLEANUP`, or
`REFACTOR` and <summary/> is a 60-80 character,
imperative-mood summary of the task plan without a trailing
period, without Markdown formatting, and without any
double-quote (`"`), backtick (`` ` ``), dollar (`$`), or
backslash (`\`) characters, and commit the change set by
running the command
`git -C "<work-dir/>" commit -m "<message/>"`. Never add
`Co-Authored-By` trailers to commit messages. If the commit
fails, treat the change set as *not* applied successfully.
Set <work-removed>false</work-removed>. If
<getopt-option-no-cleanup/> is not equal `true`,
<work-created/> is `true`, and the commit (if any) succeeded,
the change set lives on the branch alone, so remove the
worktree created by this run by running the commands
`git worktree remove "<work-dir/>"` and `git worktree prune`
(taken exactly as given, *never* with `--force`, so a
worktree with uncommitted changes is kept), and set
<work-removed>true</work-removed> if the removal succeeded.
Do not output anything.
- `attachment`: Capture the *cumulative* change set into
<unified-diff/> by running the commands
`git -C "<work-dir/>" add --all` and
`git -C "<work-dir/>" diff --cached --no-color --binary HEAD`
(taken exactly as given). Then remove the temporary worktree
by running the command
`git worktree remove --force "<work-dir/>"` (taken exactly as
given). Do not output anything.
4. Update the checkboxes of the body bullet-points of <task-content/>
as follows, changing *nothing else* of a bullet-point:
- Set the checkbox of every `DOM`, `IFC`, `ARC`, and `IMP`
bullet-point to `[x]` whose <text/> was *fully* realized by
the change set, and to `[/]` whose <text/> was realized only
*partially*. Leave the checkbox of every other bullet-point
*untouched*.
- Set the checkbox of every `REG` and `CON` bullet-point to `[x]`
whose check was actually performed *and* succeeded, and to
`[/]` whose check was performed but succeeded only *partially*.
Leave the checkbox of every other bullet-point *untouched* --
hence *all* of them for a plan whose `## VERIFICATION (WHEN)`
section is deliberately omitted.
- The rules above apply to bullet-points in the states `[ ]`,
`[?]`, and `[/]` alike, so a `[?]` bullet-point which was
not resolved at all stays `[?]`, and a re-examined `[/]`
bullet-point becomes `[x]` once its remaining parts were
resolved, or otherwise stays `[/]`.
- Leave the checkbox of every skipped `[x]` bullet-point
*untouched*, as it was already resolved by a previous run.
- Leave the checkbox of every skipped `[-]` and `[>]`
bullet-point *untouched*, as only the user resolves its
cancelled or deferred state.
5. Update the frontmatter and backmatter of <task-content/> as
follows, *creating* each of the `Status:` and `Modified:` keys
the plan does not carry yet at its position in the key order of
the plan <format/>:
- <if condition="<getopt-option-stateless/> is not equal `true` and <ase-project-task-lifecycle/> is `team` or `enterprise` and the `Status:` key was set to `IMPLEMENTING` in step 1 above">
Set the `Status:` key to `IMPLEMENTED` if the change set was
applied *completely* and *successfully* (with the skipped
`[-]` and `[>]` bullet-points not counting, and the skipped
`[x]` bullet-points counting as complete), or to `STALLED`
otherwise.
</if>
<else>
Leave the `Status:` key *untouched* -- especially for the
`solo` model, whose task is closed by `ase-task-integrate`
only, and under `--stateless`.
</else>
- Refresh the `Modified:` key with the current time in
ISO-style format, determined by calling the
`ase_timestamp(format: "yyyy-LL-dd HH:mm")` tool of the `ase`
MCP server, but *only* if step 4 changed at least one
checkbox, as the key tracks "body" changes only -- a
frontmatter-only update leaves it *untouched*. Set
<timestamp-modified/> to the resulting `Modified:` key value,
or to the current time determined the same way if the key
was left untouched.
- <if condition="<changeset-type/> is `attachment`">
Append the change set <unified-diff/> as an *attachment
block* to the "backmatter" of <task-content/> with the
following <template/>, closely following the plan <format/>.
If an attachment block with the `Type` key value
`text/x-diff; charset=utf-8; kind="<changeset-name/>"`
already exists from a previous run, *replace* this entire
existing attachment block in place. Set
<timestamp-attachment-created/> to the value of the `Created`
key of the *replaced* attachment block, so the creation time
of the change set survives its replacement, or to
<timestamp-modified/> if no such block or key exists. Set
<payload/> to <unified-diff/> with *every* line -- including
empty lines -- indented by *exactly* 4 spaces, so the YAML
literal block scalar of the `Data` key carries the diff
*verbatim*. The "body" keeps its trailing empty line directly
before the `---` line of the attachment block.
<template>
---
Type: text/x-diff; charset=utf-8; kind="<changeset-name/>"
Desc: base <source-commit/>
Created: <timestamp-attachment-created/>
Modified: <timestamp-modified/>
Data: |4+
<payload/>
</template>
</if>
Apart from the checkboxes, the frontmatter keys, and the change
set attachment above, the plan *MUST* stay *exactly* as loaded --
in particular, the "backmatter" with its other attachment blocks
(including a *change set snapshot*, which is maintained by the
`ase agent` agents only) is passed through *verbatim*.
Right before persisting, take over a concurrently stored effort
estimation, as the `estimator` agent and the `ase-task-estimate`
skill can set the `Effort:` key while the task is implemented
(and the checkbox changes above keep it valid): call the
`ase_task_load(id: "<ase-task-id/>", tag: true)` tool of the
`ase` MCP server, set <task-tag/> to the content of the trailing
`<task-plan-tag>` delimiter line of its `text` output field, and
set the `Effort:` frontmatter key of <task-content/> to the one
of the loaded plan -- *replacing* it, *creating* it at its
position in the key order of the plan <format/>, or *removing*
it if the loaded plan carries none -- changing *nothing else* of
<task-content/>.
Finally call the `ase_task_save(id: "<ase-task-id/>", text:
"<task-content/>", base: "<task-tag/>")` tool of the `ase` MCP
server to persist the updated task plan. If the save is refused
because the plan was *changed* meanwhile, repeat the take-over
above and the save, at most *three* times in total, and then
save once more *without* the `base` argument. 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.
Do not output anything in this sub-step.
6. Only output the following <template/>:
<template>
⧉ **ASE**: ◉ task: **<ase-task-id/>**, ⇢ changeset: **<task-changeset/>**, ▶ status: **plan implemented**
</template>
7. Close the implementation with the boxed summary of what this run
left open and what it decided on its own. Both boxes are written
in the conversation language and the active persona style, list
*one entry per line*, and are *omitted entirely* when they carry
no content -- a run which implemented every point and took no
decision of its own outputs no box at all.
<if condition="<open-points/> is not empty">
Output everything which now waits for the *user* with the
following <template/>:
<template>
<ase-tpl-boxed title="OPEN POINTS">
○ <open-point/>
</ase-tpl-boxed>
</template>
</if>
<if condition="<decisions/> is not empty">
The run decided open questions *on the user's behalf*, so they
*MUST* be able to revisit or overrule each of them. Output the
collected decisions -- each naming the chosen option and its
rationale -- directly below, with the following <template/>:
<template>
<ase-tpl-boxed title="DECISIONS">
○ <decision/> -- <rationale/>
</ase-tpl-boxed>
</template>
</if>
8. Give the closing hint by expanding the following (which,
depending on the configured <ase-guidance-level/>, may expand
into nothing and hence emit no output at all):
<if condition="<changeset-type/> is `worktree` and <context-label/> is not `.`">
<ase-tpl-hint level="minimal">
The change set is uncommitted in `<context-label/>` -- review it there, then use `/ase-task-integrate` to deliver it.
</ase-tpl-hint>
</if>
<elseif condition="<changeset-type/> is `branch` and <work-removed/> is `true`">
<ase-tpl-hint level="minimal">
The change set is committed on branch `<changeset-name/>` -- review it via `git diff <source-commit/>...<changeset-name/>`, then use `/ase-task-integrate` to deliver it.
</ase-tpl-hint>
</elseif>
<elseif condition="<changeset-type/> is `branch`">
<ase-tpl-hint level="minimal">
The change set is committed on branch `<changeset-name/>` in `<work-label/>` -- review it there, then use `/ase-task-integrate` to deliver it.
</ase-tpl-hint>
</elseif>
<elseif condition="<task-changeset/> is `attachment:draft`">
<ase-tpl-hint level="minimal">
The change set is attached to the plan as its implementation draft only -- review it via `/ase-task-view --full`, then use `/ase-task-integrate --draft` to deliver it.
</ase-tpl-hint>
</elseif>
<elseif condition="<changeset-type/> is `attachment`">
<ase-tpl-hint level="minimal">
The change set is attached to the plan only -- review it via `/ase-task-view --full`, then use `/ase-task-integrate --changeset <task-changeset/>` to deliver it.
</ase-tpl-hint>
</elseif>
5. **Decide Next Step:**
1. *Determine next step*:
<expand name="task-next-select"
arg1="ase-task-implement"
arg2="DONE|EDIT|INTEGRATE|DELETE">
Next Step: How would you like to proceed with the plan?
DONE: Stop processing and PRESERVE task plan.
EDIT: Hand processing off to editing.
INTEGRATE: Hand processing off to integration.
DELETE: Stop processing and DELETE the task plan.
</expand>
2. Check the tool <result/> and dispatch accordingly:
- If <result/> is `DONE` or `CANCEL`:
Only output the following <template/> and then *STOP*.
<template>
⧉ **ASE**: ◉ task: **<ase-task-id/>**, ▶ status: **plan implemented -- done**
</template>
- If <result/> is `EDIT`:
<expand name="task-next-handoff" arg1="ase-task-edit"
arg2="plan implemented -- hand-off to edit"></expand>
- If <result/> is `INTEGRATE`:
Set <handoff-args></handoff-args> (empty). If
<getopt-option-worktree/> is not empty, append
` --worktree <getopt-option-worktree/>`; if
<getopt-option-changeset/> is not empty, append
` --changeset <getopt-option-changeset/>`; if
<getopt-option-source/> is not empty and the `Target:`
frontmatter key of <task-content/> (or, if absent, the
configured default <ase-project-task-default-target/>) is `source`,
append ` --target <getopt-option-source/>`; and if
<getopt-option-stateless/> is `true`, append ` --stateless`
to <handoff-args/>, so the integration delivers the very
change set just created into the very source it is based on.
<expand name="task-next-handoff" arg1="ase-task-integrate"
arg2="plan implemented -- hand-off to integration"
arg3="<handoff-args/>"></expand>
- If <result/> is `DELETE`:
Set <args></args> (empty). Do *not* forward any remaining
`--next` list tokens, because the `ase:ase-task-delete`
skill accepts only an optional `[<id>]` argument and no
`--next` option; remaining tokens are intentionally discarded.
Only output the following <template/> and then call the
tool `Skill(skill: "ase:ase-task-delete", args: "<args/>")`
to invoke the `ase:ase-task-delete` skill in order to
*delete* the updated plan. Immediately stop processing the
current skill once the `Skill` tool was used.
<template>
⧉ **ASE**: ◉ task: **<ase-task-id/>**, ▶ status: **plan implemented -- hand-off to delete task**
</template>