ase-task-implement · diff
git:20260813.5985917 to git:20260914.a549cab
225 added, 65 removed. Audit A to A.
---
name: ase-task-implement
argument-hint: "[--help|-h] [--next|-n <option>[,...]] [--worktree|-w] [<id>]"
description: >
Implement current or given task plan.
Use when the user calls to "implement", "realize" or "apply" 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|DELETE)... --worktree|-w --int-reuse-task">
$ARGUMENTS
</expand>
<objective>
*Implement* the task plan by modifying the *artifacts*
with a corresponding, complete *change set*.
</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
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>
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-code-resolve`, `ase-code-refactor`, `ase-code-craft`,
or `ase-task-edit` skills first to create a task plan. Then
immediately stop processing this skill.
- 3. Internalize the tenets stated by the plan:
+ 3. <if condition="the backmatter of <task-content/> contains an attachment
+ block with the `Type` key value `text/x-diff; charset=utf-8; kind="preflight"`
+ which is *stale* according to the plan <format/> (its `Modified` key
+ is absent or older than the `Modified` key of the frontmatter)">
+ The implementation draft was created for an *earlier* version of
+ the plan, so taking it over *1:1* would implement the wrong plan,
+ while silently ignoring it would discard the user's review. Only
+ output the following <template/> and then immediately *STOP*
+ processing the entire current skill, leaving the plan and the
+ artifacts *untouched*:
+ <template>
+ ⧉ **ASE**: ◉ task: **<ase-task-id/>**, ▶ ERROR: implementation draft attachment is **stale** (older than the plan) -- run `/ase-task-preflight` again or remove the attachment
+ </template>
+ </if>
+
+ 4. Internalize the tenets stated by the plan:
+
<expand name="code-tenets-from-plan"></expand>
- 3. **Prepare WorkTree:**
+ 3. **Prepare Branch and WorkTree:**
- <if condition="<getopt-option-worktree/> is not equal `true`">
- No worktree was requested, so the implementation is applied directly
- to the *current* working copy. Set <worktree-dir></worktree-dir>
- (empty) and *skip* all remaining sub-steps of this step. Do not
- output anything.
- </if>
+ The *branch* the change set lands on is controlled *exclusively*
+ by the `Branch:` frontmatter key of the plan, while the *working
+ copy* it lands in -- the current one or an isolated worktree -- is
+ controlled *exclusively* by the `--worktree` option. Both are
+ orthogonal, except that Git cannot check out the already
+ checked-out branch a second time in a worktree.
- 1. Set <worktree-name><ase-task-id/></worktree-name>. The worktree
- is *never* named by its own option value: it always carries the
- unique *task id*, so the worktree directory and its branch stay
- unambiguously tied to the very task plan implemented in them.
- The task id is a plain identifier by construction, hence it is
- directly usable as both a directory and a branch name. Do not
- output anything.
+ 1. Determine the *target branch* <target-branch/>: Set
+ <task-branch/> to the value of the `Branch:` frontmatter key of
+ <task-content/>, or to the literal `current` if the key is
+ absent. Determine the *checked-out branch* by running the
+ command `git branch --show-current` (taken exactly as given)
+ and capturing its output into <current-branch/>. If
+ <task-branch/> is `current` or equal to <current-branch/>, set
+ <target-branch></target-branch> (empty: the change set lands
+ on the checked-out branch); otherwise set
+ <target-branch><task-branch/></target-branch>. Do not output
+ anything.
- 2. Determine the *worktree directory* by calling the
+ 2. <if condition="<getopt-option-worktree/> is not equal `true` and <target-branch/> is empty">
+ The change set lands on the checked-out branch of the *current*
+ working copy. Set <worktree-dir></worktree-dir> and
+ <worktree-branch></worktree-branch> (both empty) and *skip* all
+ remaining sub-steps of this step. Do not output anything.
+ </if>
+
+ 3. <if condition="<getopt-option-worktree/> is not equal `true` and <target-branch/> is not empty">
+ The change set lands on a *different* branch inside the
+ *current* working copy, so the working copy is *switched* to
+ <target-branch/> in place. Set <worktree-dir></worktree-dir>
+ and <worktree-branch></worktree-branch> (both empty).
+
+ 1. Determine the *uncommitted changes* by running the command
+ `git status --porcelain` (taken exactly as given) and
+ capturing its output. If the output is *not* empty, the
+ working copy is *dirty* and switching would drag the
+ uncommitted changes onto the other branch. 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: working copy has uncommitted changes -- cannot switch to branch **<target-branch/>** in place
+ </template>
+
+ Directly *after* this error <template/>, and *before*
+ stopping, give the corrective hint by expanding the
+ following (which, depending on the configured
+ <ase-guidance-level/>, may expand into nothing and hence
+ emit no output at all):
+
+ <ase-tpl-hint level="minimal">
+ Commit or stash the uncommitted changes first, or use `--worktree` to implement inside an isolated worktree instead.
+ </ase-tpl-hint>
+
+ 2. Determine the *existing branches* by running the command
+ `git branch --list` (taken exactly as given) and capturing
+ its output. If the branch <target-branch/> already exists,
+ switch to it by running the command
+ `git switch "<target-branch/>"`, otherwise create it from
+ `HEAD` and switch to it by running the command
+ `git switch -c "<target-branch/>"` (each taken exactly as
+ given). If the command fails, 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: branch **<target-branch/>** failed to switch
+ </template>
+
+ 3. Only output the following <template/> and then *skip* all
+ remaining sub-steps of this step:
+
+ <template>
+ ⧉ **ASE**: ◉ task: **<ase-task-id/>**, ⎇ branch: **<target-branch/>**, ▶ status: **branch switched**
+ </template>
+ </if>
+
+ 4. Determine the *worktree branch* <worktree-branch/>: Set
+ <worktree-branch><target-branch/></worktree-branch> if
+ <target-branch/> is not empty. Otherwise set
+ <worktree-branch><ase-task-id/></worktree-branch>, as the
+ checked-out branch cannot be checked out a second time in the
+ worktree: the *implied* branch carries the unique *task id*, so
+ it stays unambiguously tied to the very task plan implemented
+ on it, and is recorded in the plan's `Branch:` key on save. Do
+ not output anything.
+
+ 5. Set <worktree-name><ase-task-id/></worktree-name>. The worktree
+ *directory* always carries the unique *task id* -- a plain
+ identifier by construction and hence directly usable as a
+ directory name --, independent of the branch checked out in it.
+ Do not output anything.
+
+ 6. Determine the *worktree directory* by calling the
`ase_worktree_path(id: "<worktree-name/>", create: true)` tool of
the `ase` MCP server and capturing its output into
<worktree-dir/>.
You *MUST* *NEVER* assemble this path yourself, as only this tool
rejects a path leading through a symbolic link, through a
non-directory, or out of the repository -- a path `git worktree
add` would otherwise silently follow and thereby write outside
the repository.
<if condition="this tool call fails">
Either the current directory is not a Git repository or the
worktree directory is unsafe, so no worktree can be created. Only
output the following <template/> and then immediately *STOP*
processing the entire current skill, leaving the working copy
*untouched*:
<template>
⧉ **ASE**: ☻ skill: **ase-task-implement**, ▶ ERROR: no Git repository or unsafe worktree directory -- cannot create worktree
</template>
</if>
- 3. Determine the *existing worktrees* and *existing branches* by
+ 7. Determine the *existing worktrees* and *existing branches* by
running the corresponding commands (taken exactly as given) and
capturing their outputs:
`git worktree list --porcelain`
`git branch --list`
- <if condition="the worktree directory <worktree-dir/> or the branch <worktree-name/> already exists">
+ <if condition="the branch <worktree-branch/> already exists">
+ The branch already *exists*, so it is *checked out* into the
+ worktree instead of being created. Set
+ <worktree-add-args>"<worktree-dir/>" "<worktree-branch/>"</worktree-add-args>.
+ Do not output anything.
+ </if>
+ <else>
+ The branch is *created* from `HEAD` together with the worktree.
+ Set <worktree-add-args>-b "<worktree-branch/>" "<worktree-dir/>"</worktree-add-args>.
+ Do not output anything.
+ </else>
+
+ <if condition="the worktree directory <worktree-dir/> already exists">
Only output the following <template/> and then immediately *STOP*
processing the entire current skill, leaving the existing
- worktree, its branch, and the working copy *untouched*:
+ worktree and the working copy *untouched*:
<template>
- ⧉ **ASE**: ◉ task: **<ase-task-id/>**, ▶ ERROR: worktree or branch **<worktree-name/>** already exists
+ ⧉ **ASE**: ◉ task: **<ase-task-id/>**, ▶ ERROR: worktree **<worktree-name/>** already exists
</template>
Directly *after* this error <template/>, and *before* stopping,
give the corrective hint by expanding the following (which,
depending on the configured <ase-guidance-level/>, may expand
into nothing and hence emit no output at all):
<ase-tpl-hint level="minimal">
- Remove the existing worktree via `git worktree remove` and `git branch -d`, or rename the task via `/ase-task-rename` to implement it under a still unused worktree name.
+ Remove the existing worktree via `git worktree remove`, or rename the task via `/ase-task-rename` to implement it under a still unused worktree name.
</ase-tpl-hint>
</if>
- 4. Create the worktree by running the corresponding command (taken
- exactly as given), which creates the directory *and* -- named
- after its last path component -- the branch <worktree-name/> from
- `HEAD`. The `.ase` directory is usually git-ignored, so the
- worktree itself never shows up as a change:
+ 8. Create the worktree by running the corresponding command (taken
+ exactly as given), which creates the directory <worktree-dir/>
+ with the branch <worktree-branch/> checked out. The `.ase`
+ directory is usually git-ignored, so the worktree itself never
+ shows up as a change:
- `git worktree add "<worktree-dir/>"`
+ `git worktree add <worktree-add-args/>`
<if condition="this command fails">
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: worktree **<worktree-name/>** failed to create
</template>
</if>
- 5. Only output the following <template/>:
+ 9. Only output the following <template/>:
<template>
- ⧉ **ASE**: ◉ task: **<ase-task-id/>**, ◉ worktree: **.ase/worktree/<worktree-name/>**, ▶ status: **worktree created**
+ ⧉ **ASE**: ◉ task: **<ase-task-id/>**, ◉ worktree: **.ase/worktree/<worktree-name/>**, ⎇ branch: **<worktree-branch/>**, ▶ status: **worktree created**
</template>
4. **Create Implementation:**
1. Perform a *final implementation* of the task plan
by modifying the *artifacts* with a corresponding, complete
*change set*.
- <if condition="<task-content/> contains an `## IMPLEMENTATION DRAFT` section (from skill `ase-task-preflight`)">
- Take over the implementation draft of this section *1:1* as
- the change set: the draft is assumed to have been *reviewed*
- by the user, so you *MUST* *NOT* create a fresh implementation
- from scratch. Apply the draft *verbatim* and *adjust* only
- those parts which actually *fail* -- because a hunk no longer
- applies to meanwhile drifted artifacts, or because the
- verification phase rejects the result. For such adjusted parts,
- and for aspects the draft does not cover at all, follow the
- task plan in <task-content/>.
+ <if condition="the backmatter of <task-content/> contains an attachment block with the `Type` key value `text/x-diff; charset=utf-8; kind="preflight"` (the implementation draft from skill `ase-task-preflight`)">
+ Take over the implementation draft carried by the `Data` key of
+ this attachment block *1:1* as the change set: the draft is
+ assumed to have been *reviewed* by the user, so you *MUST* *NOT*
+ create a fresh implementation from scratch. Apply the draft
+ *verbatim* and *adjust* only those parts which actually *fail*
+ -- because a hunk no longer applies to meanwhile drifted
+ artifacts, or because the verification phase rejects the result.
+ For such adjusted parts, and for aspects the draft does not cover
+ at all, follow the task plan in <task-content/>.
</if>
- <if condition="<task-content/> contains NO `## IMPLEMENTATION DRAFT` section">
+ <if condition="the backmatter of <task-content/> contains NO attachment block with the `Type` key value `text/x-diff; charset=utf-8; kind="preflight"`">
Follow and honor the task plan in <task-content/>.
</if>
+ 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.
+
<if condition="<worktree-dir/> is not empty">
The change set *MUST* land *exclusively inside* the worktree
<worktree-dir/>: resolve *every* file path of the task plan
relative to <worktree-dir/> instead of the original working copy,
and run *every* verification command (build, tests, linter,
type-checker, program execution) with <worktree-dir/> as its
working directory. You *MUST* *NEVER* modify, stage, stash,
revert, or commit anything *outside* of this worktree. Leave the
worktree *uncommitted*: do *not* run `git add` and do *not* run
`git commit`, so the user keeps full control over the final
commit.
</if>
- <if condition="<task-content/> does NOT contain a `## VERIFICATION` section heading">
- The task plan deliberately *omits* the `## VERIFICATION`
+ <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>
- 2. Update the frontmatter of <task-content/> as follows, *creating*
- each of the `Properties:`, `Status:`, and `Modified:` keys the
- plan does not carry yet at its position in the key order of the
- plan <format/>:
+ 2. Update the checkboxes of the body bullet-points of <task-content/>
+ as follows, changing *nothing else* of a bullet-point:
- - *Add* the value `implemented` to the `Properties:` key if it
- is still absent, keeping all already present values.
+ - 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*.
- - *Add* the value `verified` to the `Properties:` key as well,
- but *only* if the verification phase was actually performed
- and succeeded -- hence *never* for a plan whose
- `## VERIFICATION` section is deliberately omitted.
+ - 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.
- - Set the `Status:` key to `COMPLETED`, but *only* if the
- change set was applied *completely* and *successfully* --
- this traverses the `approve`, `start`, and `complete`
- transitions of the state machine of the plan <format/> in one
- go, starting from the `DRAFTED` state which a freshly authored
- plan carries. Otherwise leave the `Status:` key *untouched*,
- as an incomplete run transitioned nowhere.
+ - Leave the checkbox of every skipped `[-]` and `[>]`
+ bullet-point *untouched*, as only the user resolves its
+ cancelled or deferred state.
+ 3. Update the frontmatter of <task-content/> as follows, *creating*
+ each of the `Status:`, `Modified:`, and `Branch:` keys the plan
+ does not carry yet at its position in the key order of the plan
+ <format/>:
+
+ - Set the `Status:` key to the *implemented* state of the task
+ lifecycle model <ase-project-task-lifecycle/> (`CLOSED` for
+ the `solo` model, `IMPLEMENTED` for the `team` and
+ `enterprise` models), but *only* if the change set was
+ applied *completely* and *successfully* (with the skipped
+ `[-]` and `[>]` bullet-points not counting) -- this traverses
+ the transitions of the state machine from the current state
+ up to the implemented state in one go (for the `solo` model
+ directly from the initial `OPEN` state, for the `team` model
+ from the initial `PLANNING` state via `IMPLEMENTING`, for
+ the `enterprise` model from the initial `DRAFTED` state via
+ `PLANNING`, `PLANNED`, and `IMPLEMENTING`). Otherwise leave
+ the `Status:` key *untouched*, as an incomplete run
+ transitioned nowhere.
+
- 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.
+ MCP server, but *only* if step 2 changed at least one
+ checkbox, as the key tracks "body" changes only -- a
+ frontmatter-only update leaves it *untouched*. If the
+ draft attachment (the block with the `Type` key value
+ `text/x-diff; charset=utf-8; kind="preflight"`) was
+ consumed, set its `Modified:` key to the very same value
+ (*creating* the key at its position in the key order of the
+ plan <format/> if the block does not carry it yet), so the
+ consumed draft never falls behind the plan it was applied
+ to.
- Apart from the frontmatter keys above, the plan body *MUST* stay
- *exactly* as loaded.
+ - Set the `Branch:` key to <worktree-branch/> if it is not
+ empty and differs from <task-branch/>, i.e. if `--worktree`
+ *implied* the task-id branch, so the plan records the branch
+ the change set actually landed on. Otherwise leave the
+ `Branch:` key *untouched*.
+ Apart from the checkboxes, the frontmatter keys, and the
+ `Modified:` key of the consumed draft attachment above, the plan
+ *MUST* stay *exactly* as loaded -- in particular, the
+ "backmatter" with its attachment blocks is otherwise passed
+ through *verbatim*.
+
Finally call the `ase_task_save(id: "<ase-task-id/>", text:
"<task-content/>")` tool of the `ase` MCP server to persist the
updated task plan. 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.
- 3. Only output the following <template/>:
+ 4. Only output the following <template/>:
<template>
⧉ **ASE**: ◉ task: **<ase-task-id/>**, ▶ status: **plan implemented**
</template>
- 4. <if condition="<worktree-dir/> is not empty">
+ 5. <if condition="<worktree-dir/> is not empty">
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):
<ase-tpl-hint level="minimal">
- The change set is uncommitted in `.ase/worktree/<worktree-name/>` on branch `<worktree-name/>` -- review and commit it there, then remove the worktree via `git worktree remove`.
+ The change set is uncommitted in `.ase/worktree/<worktree-name/>` on branch `<worktree-branch/>` -- review and commit it there, then remove the worktree via `git worktree remove`.
</ase-tpl-hint>
</if>
+ <elseif condition="<target-branch/> is not empty">
+ 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):
+
+ <ase-tpl-hint level="minimal">
+ The change set is uncommitted on branch `<target-branch/>`, which is now checked out in the working copy -- review and commit it there.
+ </ase-tpl-hint>
+ </elseif>
5. **Decide Next Step:**
1. *Determine next step*:
<expand name="task-next-select"
arg1="ase-task-implement"
arg2="DONE|DELETE">
Next Step: How would you like to proceed with the plan?
DONE: Stop processing and PRESERVE task plan.
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 `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>