1---2name: ase-task-edit3description: Iteratively edit and refine a named plan for a task through a conversational loop. 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 preflight. Use when the user wants to plan a task purely through chat-driven refinement.4---5
6@${CLAUDE_SKILL_DIR}/../../meta/ase-control.md
7@${CLAUDE_SKILL_DIR}/../../meta/ase-skill.md
8@${CLAUDE_SKILL_DIR}/../../meta/ase-dialog.md
9@${CLAUDE_SKILL_DIR}/../../meta/ase-getopt.md
10
11<skill name="ase-task-edit">
12Iteratively Edit a Task Plan
13</skill>
14
15<expand name="getopt"
16 arg1="ase-task-edit"
17 arg2="--plan|-p=(none|OVERWRITE|REFINE|PRESERVE) --dry|-d --next|-n=(none|DONE|GRILL|PREFLIGHT|IMPLEMENT)... --int-reuse-task">
18 $ARGUMENTS
19</expand>
20
21<objective>
22Establish and refine the *task plan* purely through a *chat-driven
23loop*. The user steers each round via an interactive dialog that offers
24continued refinement, finalization, or hand-off to implementation or
25preflight.
26</objective>
27
28@${CLAUDE_SKILL_DIR}/../../meta/ase-format-task.md
29
30Procedure
31---------
32
33<define name="apply-refinement">
34Treat the <instruction/> as a *refinement instruction* for
35the plan, and update <content/> in-place by *applying* the
36requested <instruction/> to the *plan*.
37
38When refining the plan this way, preserve the overall structure of the
39plan and only modify what the user actually requested. Do *not* rewrite
40unrelated sections of the plan.
41
42Calculate the number of words <words/> of <content/>.
43Set <content-dirty>true</content-dirty>.
44</define>
45
46<define name="generate-plan">
47Create a new plan from scratch and store the result as
48<content/> by closely following the defined plan format
49<format/> and injecting into it all the information from
50the <instruction/> and all decisions you derived from the
51<instruction/>.
52
53If a `CHANGELOG.md` file exists in the project (or in any
54affected sub-package), the plan *MUST* include, as part of
55its `## CHANGES` section, an explicit bullet point
56describing the addition of a corresponding new entry to
57that `CHANGELOG.md` file, aligned with its existing style
58and conventions.
59
60<if condition="<getopt-option-dry/> is equal `true`">
61You *MUST* completely omit the `## VERIFICATION` section
62(including its heading and all of its bullet points) from
63<content/>.
64</if>
65
66Call the `ase_timestamp(format: "yyyy-LL-dd HH:mm")` tool of the
67`ase` MCP server and use the `text` field of its response
68for fresh <timestamp-created/> and <timestamp-modified/>
69information. Then insert the current <ase-task-id/>,
70<timestamp-created/>, and <timestamp-modified/> information
71and calculate the number of words <words/> of <content/>.
72Set <content-dirty>true</content-dirty>.
73</define>
74
751. **Determine Task and Instruction:**
76
77 1. Set <instruction><getopt-arguments/></instruction> initially.
78 Inherit the always existing <ase-task-id/> from the current context.
79 Inherit the always existing <ase-session-id/> from the current context.
80 Do not output anything.
81
82 2. React on task and/or instruction:
83
84 1. <if condition="
85 <instruction/> matches the regexp `^[a-zA-Z][a-zA-Z0-9_-]*$`
86 ">
87 Set <ase-task-id><instruction/></ase-task-id> (set task
88 id to instruction) and <instruction></instruction> (set
89 instruction empty), call the `ase_task_id(id: "<ase-task-id/>",
90 session: "<ase-session-id/>")` tool from the `ase` MCP
91 server to switch the task, and then only output the
92 following <template/>:
93
94 <template>
95 ⧉ **ASE**: ◉ task: **<ase-task-id/>**, ▶ status: **task given**
96 </template>
97 </if>
98
99 2. <elseif condition="
100 <instruction/> has the format `<id/>: <text/>` where
101 <id/> matches the regexp `^[a-zA-Z][a-zA-Z0-9_-]*$` and
102 <text/> is *empty*
103 ">
104 Set <instruction></instruction> (set instruction to empty)
105 and <ase-task-id><id/></ase-task-id> (set task id to
106 id) and call the `ase_task_id(id: "<ase-task-id/>", session:
107 "<ase-session-id/>")` tool from the `ase` MCP server to
108 switch the task, and then only output the following
109 <template/>:
110
111 <template>
112 ⧉ **ASE**: ◉ task: **<ase-task-id/>**, ▶ status: **task given**
113 </template>
114 </elseif>
115
116 3. <elseif condition="
117 <instruction/> has the format `<id/>: <text/>` where
118 <id/> matches the regexp `^[a-zA-Z][a-zA-Z0-9_-]*$` and
119 <text/> is *not empty*
120 ">
121 Set <instruction><text/></instruction> (set instruction to
122 text) and <ase-task-id><id/></ase-task-id> (set task id
123 to id) and call the `ase_task_id(id: "<ase-task-id/>", session:
124 "<ase-session-id/>")` tool from the `ase` MCP server to
125 switch the task, and then only output the following
126 <template/>:
127
128 <template>
129 ⧉ **ASE**: ◉ task: **<ase-task-id/>**, ▶ status: **task given**
130 ⧉ **ASE**: ◉ task: **<ase-task-id/>**, ⇌ instruction: **<instruction/>**, ▶ status: **instruction given**
131 </template>
132 </elseif>
133
134 4. <elseif condition="
135 <instruction/> is not empty
136 ">
137 Only output the following <template/>:
138
139 <template>
140 ⧉ **ASE**: ◉ task: **<ase-task-id/>**, ▶ status: **task inherited**
141 ⧉ **ASE**: ◉ task: **<ase-task-id/>**, ⇌ instruction: **<instruction/>**, ▶ status: **instruction given**
142 </template>
143 </elseif>
144
145 5. <elseif condition="
146 <instruction/> is empty
147 ">
148 Only output the following <template/>:
149
150 <template>
151 ⧉ **ASE**: ◉ task: **<ase-task-id/>**, ▶ status: **task inherited**
152 </template>
153 </elseif>
154
1552. **Determine Plan:**
156
157 1. Determine any existing plan content:
158
159 <if condition="
160 <getopt-option-int-reuse-task/> is equal `true`
161 *and* a `ase_task_save(id: '<ase-task-id/>', ...)` tool call
162 exists earlier in the current session
163 ">
164 Set <text/> to the `text` argument of the most recent
165 `ase_task_save(id: '<ase-task-id/>', ...)` tool call,
166 *without* calling `ase_task_load` again. Set <status>plan
167 reused</status>. Do not output anything.
168 </if>
169 <else>
170 Call the `ase_task_load(id: "<ase-task-id/>")` tool of the
171 `ase` MCP server to load any existing plan content and set
172 <text/> to the `text` output field of this `ase_task_load`
173 tool call. Do not output anything related to this MCP tool
174 call. Set <status>plan loaded</status>.
175 </else>
176
177 Set <content-dirty>false</content-dirty>.
178
179 - If <text/> starts with `ERROR:`:
180 Silently ignore the MCP error.
181 Set <content/> to empty.
182 Set <words/> to "0".
183 Do not output anything.
184
185 - If <text/> starts NOT with `ERROR:`:
186 Set <content><text/></content> (set content to text).
187 Calculate the number of words <words/> of <content/>.
188 Only output the following <template/>:
189
190 <template>
191 ⧉ **ASE**: ◉ task: **<ase-task-id/>**, ✪ plan: **<words/>** words, ▶ status: **<status/>**
192 </template>
193
194 2. <if condition="<content/> is empty AND <instruction/> is empty">
195 Ask the user interactively, without a special tool, for the
196 initial plan content with a single question:
197
198 `**No plan content yet. What is the task you want to plan?**`
199
200 Then set <instruction/> to the response of the user and only
201 output the following <template/>:
202
203 <template>
204 ⧉ **ASE**: ◉ task: **<ase-task-id/>**, ⇌ instruction: **<instruction/>**, ▶ status: **instruction given**
205 </template>
206 </if>
207
208 3. <if condition="<content/> is not empty AND
209 <instruction/> is not empty AND
210 <instruction/> is not equal <content/>">
211 *Determine previous-plan handling*:
212
213 - If <getopt-option-plan/> matches the regex `^(OVERWRITE|REFINE|PRESERVE)$`:
214 Honor the pre-selection what to do with the previous plan.
215 Set <result><getopt-option-plan/></result>.
216
217 - If <getopt-option-plan/> is equal to `none`:
218
219 In the following, you *MUST* *NOT* use your built-in
220 <user-dialog-tool/> tool! Instead, you *MUST* just show a
221 custom dialog according to the expanded `custom-dialog`
222 definition. You *MUST* closely follow this definition:
223
224 <expand name="custom-dialog" arg1="--other">
225 Previous Plan: Should the previous plan content be overwritten, refined, or preserved?
226 OVERWRITE: Continue operation, overwrite previous plan.
227 REFINE: Continue operation, refine previous plan.
228 PRESERVE: Cancel operation, preserve previous plan.
229 </expand>
230
231 Check the tool <result/> and dispatch accordingly:
232
233 - If <result/> is `CANCEL` or `PRESERVE`:
234
235 Only output the following <template/> and then immediately
236 *STOP* processing this skill:
237
238 <template>
239 ⧉ **ASE**: ◉ task: **<ase-task-id/>**, ✪ plan: **<words/>** words, ▶ status: **plan preserved**
240 </template>
241
242 - If <result/> is `OVERWRITE`:
243
244 <expand name="generate-plan"/>
245
246 Only output the following <template/> and continue processing:
247
248 <template>
249 ⧉ **ASE**: ◉ task: **<ase-task-id/>**, ✪ plan: **<words/>** words, ▶ status: **plan overwritten**
250 ⧉ **ASE**: ◉ task: **<ase-task-id/>**, ⇌ instruction: **<instruction/>**, ▶ status: **instruction given**
251 </template>
252
253 - If <result/> is `REFINE`:
254
255 <expand name="apply-refinement"/>
256
257 Only output the following <template/> and continue processing:
258
259 <template>
260 ⧉ **ASE**: ◉ task: **<ase-task-id/>**, ✪ plan: **<words/>** words, ▶ status: **plan refined**
261 ⧉ **ASE**: ◉ task: **<ase-task-id/>**, ⇌ instruction: **<instruction/>**, ▶ status: **instruction given**
262 </template>
263
264 - If <result/> matches `OTHER: <text/>`:
265
266 Set <instruction><instruction/> <text/></instruction> (append
267 the user's free-text hint to the existing instruction).
268
269 <expand name="apply-refinement"/>
270
271 Only output the following <template/> and continue processing:
272
273 <template>
274 ⧉ **ASE**: ◉ task: **<ase-task-id/>**, ✪ plan: **<words/>** words, ▶ status: **plan refined**
275 ⧉ **ASE**: ◉ task: **<ase-task-id/>**, ⇌ instruction: **<instruction/>**, ▶ status: **instruction given**
276 </template>
277 </if>
278
279 4. <if condition="no line of <content/> matches the case-insensitive regex `^\s*#+\s*TASK\b` AND <instruction/> is empty">
280 Set <instruction><content/></instruction> (set instruction to content).
281 Set <content></content> (set content to empty).
282 Set <content-dirty>true</content-dirty>.
283 Do not output anything.
284 </if>
285
286 5. <if condition="<content/> is empty AND <instruction/> is not empty">
287 <expand name="generate-plan"/>
288
289 Only output the following <template/> and continue processing:
290
291 <template>
292 ⧉ **ASE**: ◉ task: **<ase-task-id/>**, ⇌ instruction: **<instruction/>**, ▶ status: **instruction given**
293 ⧉ **ASE**: ◉ task: **<ase-task-id/>**, ✪ plan: **<words/>** words, ▶ status: **plan generated**
294 </template>
295 </if>
296
2973. **Iterative Plan Refinement Loop:**
298
299 *REPEAT* the following steps from 3.1 up to and including 3.4 in
300 a *LOOP* until the user selects `DONE`, `GRILL`, `IMPLEMENT`, or
301 `PREFLIGHT`, or declines/cancels in the dialog of step 3.4:
302
303 1. *Update timestamp*:
304 <if condition="<content/> contains '⚙ Modified:' AND <content-dirty/> is 'true'">
305 Update <timestamp-modified/> with the current time in
306 ISO-style format, which has to be determined by calling the
307 `ase_timestamp(format: "yyyy-LL-dd HH:mm")` tool of the `ase`
308 MCP server and use the `text` field of its response. Update
309 the `⚙ Modified: ...` line of <content/> with the new
310 `⚙ Modified: <timestamp-modified/>`.
311 Do not output anything.
312 </if>
313
314 2. *Persist plan*:
315 <if condition="<content-dirty/> is 'true'">
316 Call the `ase_task_save(id: "<ase-task-id/>", text: "<content/>")` tool
317 of the `ase` MCP server to persist the current plan, and then
318 set <content-dirty>false</content-dirty> again. Calculate the
319 number of words <words/> of <content/>. Do not output anything
320 related to this MCP tool call except the following <template/>:
321
322 <template>
323 ⧉ **ASE**: ◉ task: **<ase-task-id/>**, ✪ plan: **<words/>** words, ▶ status: **plan saved**
324 </template>
325 </if>
326
327 3. *Render plan*: Treat <content/> as *verbatim* Markdown.
328 Only output the following <template/>, so the user
329 can read the plan and react to it. If <content/> is longer
330 than 90 lines and a `## IMPLEMENTATION DRAFT` section (from the
331 companion skill `ase-task-preflight`) exists, replace the entire
332 content of the `## IMPLEMENTATION DRAFT` section with `[...]`.
333 Else, do *not* truncate, summarize, or partially show the plan.
334 Use the following <template/>:
335
336 <template>
337 <ase-tpl-head title="TASK"/>
338 <content/>
339 <ase-tpl-foot title="TASK"/>
340 </template>
341
342 4. *Determine next step*:
343
344 - If <getopt-option-next/> is not equal to `none`:
345 Treat <getopt-option-next/> as a comma-separated chronological
346 list of pre-selected next-step tokens. *Split* it on `,`,
347 take the *first* token as <head/>, and store the remaining
348 tokens (joined back with `,`, or `none` if empty) into
349 <getopt-option-next/> so subsequent loop iterations or
350 downstream skills can consume the tail.
351
352 - If <head/> matches the regex `^(DONE|GRILL|IMPLEMENT|PREFLIGHT)$`:
353 Honor the pre-selected token.
354 Set <result><head/></result>.
355
356 Set <instruction></instruction> (clear the instruction, as
357 any instruction carried in via the arguments was already
358 applied to the plan in step 2 before this loop), so that a
359 later `OTHER: <text/>` refinement correctly starts from a
360 *fresh* refinement instruction below.
361
362 - else:
363 Only output the following <template/> and then immediately
364 *STOP* processing the entire current skill:
365
366 <template>
367 ⧉ **ASE**: ☻ skill: **ase-task-edit**, ▶ ERROR: invalid `--next` token: **<head/>**
368 </template>
369
370 - If <getopt-option-next/> is equal to `none`:
371
372 In the following, you *MUST* *NOT* use your built-in
373 <user-dialog-tool/> tool! Instead, you *MUST* just show a
374 custom dialog according to the expanded `custom-dialog`
375 definition. You *MUST* closely follow this definition:
376
377 <expand name="custom-dialog" arg1="--other">
378 Next Step: How would you like to proceed with the plan?
379 DONE: Mark plan finalized, exit planning loop.
380 GRILL: Hand off plan to grilling.
381 PREFLIGHT: Hand off plan to pre-flighting.
382 IMPLEMENT: Hand off plan to implementation.
383 </expand>
384
385 Check the tool <result/> and dispatch accordingly:
386
387 - If <result/> is `DONE`:
388
389 *Break* out of the *loop*, only output the following <template/>
390 and then *STOP*. Do *not* implement the plan.
391
392 <template>
393 ⧉ **ASE**: ◉ task: **<ase-task-id/>**, ✪ plan: **<words/>** words, ▶ status: **plan finalized -- done**
394 </template>
395
396 - If <result/> is `GRILL`:
397
398 *Break* out of the *loop*.
399 Set <args></args> (set args to empty).
400 <if condition="the plan was saved via `ase_task_save` in step 3.2">
401 Set <args>--int-reuse-task</args>.
402 </if>
403 <if condition="<getopt-option-next/> is not equal `none`">
404 Set <args><args/> --next <getopt-option-next/></args>
405 </if>
406 Only output the following <template/> and then call the
407 `Skill(skill: "ase:ase-task-grill", args: "<args/>")` tool
408 to *grill* the finalized plan.
409
410 <template>
411 ⧉ **ASE**: ◉ task: **<ase-task-id/>**, ✪ plan: **<words/>** words, ▶ status: **plan finalized -- hand-off to grilling**
412 </template>
413
414 - If <result/> is `PREFLIGHT`:
415
416 *Break* out of the *loop*.
417 Set <args></args> (set args to empty).
418 <if condition="the plan was saved via `ase_task_save` in step 3.2">
419 Set <args>--int-reuse-task</args>.
420 </if>
421 <if condition="<getopt-option-next/> is not equal `none`">
422 Set <args><args/> --next <getopt-option-next/></args>
423 </if>
424 Only output the following <template/> and then call the
425 `Skill(skill: "ase:ase-task-preflight", args: "<args/>")` tool
426 to *apply* the finalized plan.
427
428 <template>
429 ⧉ **ASE**: ◉ task: **<ase-task-id/>**, ✪ plan: **<words/>** words, ▶ status: **plan finalized -- hand-off to pre-flight**
430 </template>
431
432 - If <result/> is `IMPLEMENT`:
433
434 *Break* out of the *loop*.
435 Set <args></args> (set args to empty).
436 <if condition="the plan was saved via `ase_task_save` in step 3.2">
437 Set <args>--int-reuse-task</args>.
438 </if>
439 <if condition="<getopt-option-next/> is not equal `none`">
440 Set <args><args/> --next <getopt-option-next/></args>
441 </if>
442 Only output the following <template/> and then call the
443 `Skill(skill: "ase:ase-task-implement", args: "<args/>")` tool
444 to *apply* the finalized plan.
445
446 <template>
447 ⧉ **ASE**: ◉ task: **<ase-task-id/>**, ✪ plan: **<words/>** words, ▶ status: **plan finalized -- hand-off to implementation**
448 </template>
449
450 - If <result/> matches `OTHER: <text/>`:
451
452 Set <instruction><text/></instruction> (replace existing instruction).
453
454 <expand name="apply-refinement"/>
455
456 Finally, only output the following <template/> and then
457 *continue* the *loop* at step **3.1**!
458
459 <template>
460 ⧉ **ASE**: ◉ task: **<ase-task-id/>**, ⇌ instruction: **<instruction/>**, ▶ status: **plan refined**
461 </template>
462
463 - If <result/> is `CANCEL`:
464
465 *Break* out of the *loop*, only output the following <template/>
466 and then *STOP*. Do *not* implement the plan.
467
468 <template>
469 ⧉ **ASE**: ◉ task: **<ase-task-id/>**, ✪ plan: **<words/>** words, ▶ status: **plan refinement cancelled**
470 </template>
471