ase-task-implement · git:20260914.a549cab · 2026-09-14 · sha256 049ffe9eee782b86

ase-task-implement git:20260914.a549cabA

Immutable. This exact content is served forever at /api/v1/blob/049ffe9eee782b86.

---
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.  <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 Branch and WorkTree:**

    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.  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.  <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>

    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 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 and the working copy *untouched*:

        <template>
        ⧉ **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`, or rename the task via `/ase-task-rename` to implement it under a still unused worktree name.
        </ase-tpl-hint>
        </if>

    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-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>

    9.  Only output the following <template/>:

        <template>
        ⧉ **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="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="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 (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 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.

        -   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, 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.

        -   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.

    4.  Only output the following <template/>:

        <template>
        ⧉ **ASE**: ◉ task: **<ase-task-id/>**, ▶ status: **plan implemented**
        </template>

    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-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>