ase-spec-edit · diff
git:20260512.725dd8d to git:20260826.0d92ccc
493 added, 75 removed. Audit A to A.
---
name: ase-spec-edit
- argument-hint: "[<task-id>|[<task-id>: ]<content>]"
+ argument-hint: "[--help|-h] [--grill|-g] [--grill-rounds|-r <n>] [--verify|-v] [--worktree|-w] [--loop|-l] [<query>]"
description: >
- Load and save a named plan for a task and apply Claude Code *Plan Mode* on it.
- Use when the user wants to plan a task.
+ Edit Specification: Use when the user wants to "edit" the
+ SpecBook-based specification (SPEC) in one shot from a query, with
+ optional grilling, SpecBook validation, looping, and Git worktree
+ isolation.
user-invocable: true
disable-model-invocation: false
- effort: medium
+ 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
- Manage the Plan for a Task
- ==========================
+ <purpose name="ase-spec-edit">
+ Edit Specification
+ </purpose>
- 1. Enter *Plan Mode* by using the `EnterPlanMode` tool and clear any old
- plan content of the *Plan Mode* and start planning from scratch with an
- empty initial plan.
+ <expand name="getopt"
+ arg1="ase-spec-edit"
+ arg2="--grill|-g --grill-rounds|-r=1 --verify|-v --worktree|-w --loop|-l">
+ $ARGUMENTS
+ </expand>
- 2. Determine the new plan content by setting
- <content>$ARGUMENTS</content> initially.
+ <objective>
+ *Edit* the specification directly from a query -- creating, revising, or
+ pruning its statements in one shot -- through the states *querying*,
+ *discovering*, *grilling*, *implementing*, and *verifying*.
+ </objective>
- If <content/> matches the regexp `^[a-zA-Z][a-zA-Z0-9_-]+$`, then set
- <ase-task-id/><content></ase-task-id> (set task id to content) and
- <content></content> (set content empty) and call the `task_id(id:
- <ase-task-id/>, session: <ase-session-id/>)` tool from the `ase` MCP
- service to implicitly switch the task.
+ @${CLAUDE_SKILL_DIR}/../../meta/ase-format-meta.md
+ @${CLAUDE_SKILL_DIR}/../../meta/ase-format-spec.md
+ @${CLAUDE_SKILL_DIR}/../../meta/ase-tenets.md
+ @${CLAUDE_SKILL_DIR}/../../meta/ase-common-grill.md
- Else, if <content/> has the format `<id/>: <text/>` where
- <id/> matches the regexp `^[a-zA-Z][a-zA-Z0-9_-]+$`, then set
- <content><text/></content> and <ase-task-id><id/></ase-task-id> and
- call the `task_id(id: <ase-task-id/>, session: <ase-session-id/>)`
- tool from the `ase` MCP service to implicitly switch the task.
+ Procedure
+ ---------
- Do not output anything related to this entire step.
+ This skill is *plan-less*: it *never* composes or persists a task plan
+ and *MUST* *NOT* call `ase_task_save(...)`. Instead, it applies the
+ requested edit *in place*, so the *implementing* state *requires* `Edit`
+ and `Write` to modify the affected artifacts. Every modification *MUST*
+ stay restricted to the `SPEC` artifacts the edit actually demands -- the
+ kinds `CODE`, `DOCS`, `TASK`, `INFR`, and `OTHR` are *never* touched.
- 3. Output the current plan id with the following <template/>:
+ <define name="todo-box">
- <template>
- ⚪ task: **<ase-task-id/>**
- </template>
+ On finishing the state `<arg1/>`, only output the following <template/>,
+ which shows the established <todo-what/> and <todo-how/>, where a still
+ empty <todo-what/> or <todo-how/> renders as `(none)`:
- 4. <if condition="<content/> is empty">
- Call the `task_load` tool (`id` set to <ase-task-id/>) of the `ase`
- MCP service to load the new plan content and set <content/> to the
- `text` output field of the `task_load` tool call. Calculate the
- number of words <words/> of <content/>. Do not output anything
- related to this MCP tool call except the following <template/>:
+ <template>
+ <ase-tpl-head title="EDIT TODO" subtitle="<arg1/>"/>
- <template>
- 🔵 task: **<ase-task-id/>**, plan: **<words/>** words, status: plan **loaded**
- </template>
- </if>
+ **WHAT**: <todo-what/>
- 5. <if condition="<content/> is still empty">
- Ask the user interactively for the plan <content/> with a single
- question `Still no plan content. What is the task you want
- to plan?`. Then set <content/> to the response of the user. Do not
- output anything further in this step.
- </if>
+ **HOW**: <todo-how/>
- 6. If a <timestamp-modified/> is present in the plan, set the
- <timestamp-modified/> to the current time in ISO-style format
- value, which has to be determined by calling the `timestamp(format:
- "yyyy-LL-dd HH:mm")` tool of the `ase` MCP service and use the `text`
- field of its response.
+ <ase-tpl-foot title="EDIT TODO" subtitle="<arg1/>"/>
+ </template>
- 7. Now use <content/> for the new plan content in *Plan Mode*.
- For this, you *MUST* immediately *replace* the plan content of the
- *Plan Mode* with the new <content/>. It doesn't matter what the
- resulting plan content <content/> actually is, especially even if it
- *still* not an actionable task in your opinion! You always *MUST*
- accept any <content/> and continue the planning with this particular
- plan content.
+ </define>
- 8. You *MUST* output the following <template/>:
+ 1. **Initialize:**
- <template>
- ◉ **NOTICE**: In the following, we will try to exit the *Plan Mode*
- again. You can still *chat* on the plan in order to still change it.
- Or just press **SHIFT+TAB** twice to finally exit the *Plan Mode*. We
- will then just exit the *Plan Mode* and do nothing more, especially
- we will *NOT* execute the plan at this time anyway!
- </template>
+ 1. Set <query><getopt-arguments/></query> (with any leading and
+ trailing whitespace stripped), set <todo-what></todo-what> and
+ <todo-how></todo-how> (both empty), and set
+ <worktree-dir></worktree-dir> (empty). Do not output anything.
- 9. You *MUST* then immediately exit *Plan Mode* by calling the
- `ExitPlanMode` tool.
+ 2. If <getopt-option-grill-rounds/> is not a positive integer,
+ only output the following <template/> and then immediately
+ *STOP* processing the entire current skill:
- 10. Once the user will leave *Plan Mode* by using the `ExitPlanMode` tool,
- you *always* *MUST* update <content/> to be the last plan content
- from the *Plan Mode*. Then you *always* *MUST* *save* the updated
- <content/> with the `task_save` tool (`id` set to <ase-task-id/>, `text`
- set to <content/>) before proceeding with any further operations.
- Calculate the number of words <words/> of <content/>. Do not output
- anything related to this MCP tool call, except the following
- <template/>:
+ <template>
+ ⧉ **ASE**: ✪ skill: **ase-spec-edit**, ▶ ERROR: invalid `--grill-rounds` value: **<getopt-option-grill-rounds/>**
+ </template>
- <template>
- 🟠 task: **<ase-task-id/>**, plan: **<words/>** words, status: plan **saved**
- </template>
+ 2. **Iterate:**
+ Perform the states (1) *querying*, (2) *discovering*, (3) *grilling*,
+ (4) *implementing*, and (5) *verifying* below as one *iteration*.
+ Without `--loop` perform exactly *one* iteration. Under `--loop`
+ *repeat* the iteration until the *querying* state receives a
+ `STOP SKILL` result. Do not output anything in this item.
+
+ 3. **State: querying:**
+
+ 1. <if condition="<query/> is empty">
+
+ 1. In the following, you *MUST* *NOT* use your built-in
+ <user-dialog-tool/> tool! Instead, you *MUST* just show a
+ custom dialog according to the expanded `custom-dialog`
+ definition. You *MUST* closely follow this definition. Its
+ only answer option is the fixed `STOP SKILL`, so the user
+ normally answers with the edit query in *one* free-text
+ reply:
+
+ <expand name="custom-dialog" arg1="--other">
+ Edit Query: What is your edit query?
+ STOP SKILL: stop the entire skill immediately
+ </expand>
+
+ 2. If <result/> is `STOP SKILL` or `CANCEL`, only output the
+ following <template/> and then immediately *STOP* processing
+ the entire current skill:
+
+ <template>
+ ⧉ **ASE**: ✪ skill: **ase-spec-edit**, ▶ status: **editing finished**
+ </template>
+
+ Otherwise, strip any leading `OTHER: ` prefix from
+ <result/> and set <query/> to the remainder.
+
+ </if>
+
+ 2. Convert the <query/> *fresh* into <todo-what/> -- the
+ domain-specific, non-implementation-detail information -- and
+ <todo-how/> -- the remaining information -- discarding all
+ <todo-what/>/<todo-how/> content of any previous iteration.
+ Without `--grill` you *MUST* *NOT* ask any clarifying questions
+ and during later implementation just interpret the query best-effort.
+ Do not output anything.
+
+ 3. Expand the following:
+
+ <expand name="todo-box" arg1="current state (after querying)"></expand>
+
+ 4. Set <query></query> (clear the query, so every further `--loop`
+ iteration asks for a fresh one). Do not output anything.
+
+ 4. **State: discovering:**
+
+ 1. Resolve the `SPEC` artifacts by calling the
+ `ase_artifact_list(kind: [ "spec" ])` tool of the `ase` MCP
+ server *once* and reading the returned `artifacts` array of
+ `{ kind, files }` objects to obtain the project-relative file
+ list. Do not output anything.
+
+ 2. 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. Do not
+ output anything.
+
+ 3. Read all resolved `SPEC` artifacts which are related to
+ <todo-what/> and <todo-how/>, and check the structure of the
+ existing specification -- its artifacts, object kinds, ids,
+ properties, descriptions, and `[[xxx]]` references -- to
+ understand the overall models and their relationships. Do not
+ output anything.
+
+ 5. **State: grilling:**
+
+ Enter this state only if <getopt-option-grill/> is equal `true`;
+ otherwise silently *skip* the entire state. Do not output anything
+ about the skipping.
+
+ 1. Understand what "grilling" is about:
+
+ <expand name="grill-understanding" arg1="the edit query in <todo-what/> and <todo-how/>"></expand>
+
+ 2. Perform <getopt-option-grill-rounds/> grilling *rounds*,
+ numbered <m/> (1-<getopt-option-grill-rounds/>).
+
+ For each round:
+
+ 1. INITIALIZE TODO:
+
+ Explicitly start *from scratch* from *only* the current
+ <todo-what/> and <todo-how/> and *forget* all information
+ gathered in previous rounds. Set <round-id/> to
+ `GRILLING ROUND <m/>/<getopt-option-grill-rounds/>` if
+ <getopt-option-grill-rounds/> is greater than 1, or to
+ `GRILLING` otherwise (a single round needs no round
+ numbering). Do not output anything.
+
+ 2. DETERMINE QUESTIONS:
+
+ Determine the questions, comprised of a round-local id
+ <question-N-id/> of `Q<N/>` -- where <N/> restarts at `1`
+ in *every* round, independent of the numbering of previous
+ rounds --, and a very brief but precise question text
+ <question-N-text/>. Each question is chosen to
+ resolve the open points related to the above understanding
+ of grilling, by focusing on the mentioned *Focus Areas*.
+
+ For <question-N-text/> use the format `Shall...?` for
+ questions of focus area `DOMAIN` and `INTERFACE`, the format
+ `Should...?` for questions of focus area `ARCHITECTURE`,
+ and the format `May...?` for questions of focus area
+ `IMPLEMENTATION`.
+
+ In every <question-N-text/>, encode all *literal aspects*
+ -- file paths, artifact ids, object kinds, object ids,
+ property keys, references, and literal values -- with
+ backticks.
+
+ Keep every <question-N-text/> at most *200 characters* long
+ -- compact the text until it fits --, as a longer question
+ overflows its table cell and silently degrades the entire
+ table into a plain text rendering.
+
+ 3. DETERMINE CONTEXT:
+
+ For each question, determine its focus area
+ <context-N-focus/> from the mentioned *Focus Areas*, a 1-3
+ word hint <context-N-topic/>, describing what the question
+ is about, and a <context-N-severity/>, describing how
+ important this question is.
+
+ Set <context-N-id/> to `DOM` for <context-N-focus/> of
+ `DOMAIN`, `IFC` for <context-N-focus/> of `INTERFACE`, `ARC`
+ for <context-N-focus/> of `ARCHITECTURE`, and `IMP` for
+ <context-N-focus/> of `IMPLEMENTATION`.
+
+ 4. SORT QUESTIONS:
+
+ Finally, *sort* the questions by descending focus area
+ order -- first all `DOMAIN`, then all `INTERFACE`, then all
+ `ARCHITECTURE`, and then all `IMPLEMENTATION` ones -- and
+ renumber <N/> according to this order, starting at `1`.
+ Truncate the list after a maximum of 10 questions and set
+ <n/> to the number of remaining questions. Do not output
+ anything.
+
+ Finally, assemble the <question-N/> out of
+ `**<question-N-id/>** ▶ **<context-N-id/>** ▷
+ **<context-N-topic/>**: <question-N-text/>`.
+
+ 5. DETERMINE ANSWERS:
+
+ For all remaining <question-N/>, check the specification and
+ your world knowledge to find *two to three* grounded answer
+ alternatives <answer-N-K/> with a question-local id
+ <answer-N-K-id/> of `A<K/>` -- where <K/> restarts at `1`
+ for *every* question, independent of the numbering of other
+ questions --, a 1-3 word label <answer-N-K-label/>, and
+ an ultra brief description <answer-N-K-description/> of
+ at most *10 words*. For the answer which reflects the
+ current <todo-what/>/<todo-how/> understanding, append
+ ` ⚑` to its <answer-N-K-label/>.
+
+ Assemble an <answer-N/> out of `**<answer-N-1-id/>**
+ ▶ **<answer-N-1-label/>**: <answer-N-1-description/>,
+ **<answer-N-2-id/>** ▶ **<answer-N-2-label/>**:
+ <answer-N-2-description/>[, ...]`.
+
+ Keep every assembled <answer-N/> at most *240 characters*
+ long -- drop the least relevant alternative and compact the
+ descriptions until it fits -- as a longer answer overflows
+ its table cell and silently degrades the entire table into a
+ plain text rendering.
+
+ 6. INTERACTIVE DIALOG:
+
+ In the following, you *MUST* *NOT* use your built-in
+ <user-dialog-tool/> tool! Instead, you *MUST* just show a
+ custom dialog according to the expanded `custom-dialog`
+ definition. You *MUST* closely follow this definition. The
+ dialog below carries the two fixed answer options
+ `SKIP GRILLING` and `STOP SKILL`, dispatched as follows:
+
+ - If a <result/> is `SKIP GRILLING` or `CANCEL`, ask no
+ further questions, continue with item 7 below (merging
+ the answers gathered so far), and after item 8 skip all
+ remaining rounds and continue with the *implementing*
+ state.
+
+ - If a <result/> is `STOP SKILL`, only output the
+ following <template/> and then immediately *STOP*
+ processing the entire current skill:
+
+ <template>
+ ⧉ **ASE**: ✪ skill: **ase-spec-edit**, ▶ status: **editing stopped**
+ </template>
+
+ 1. Output only the following <template/> -- it lists *all*
+ questions of the round up-front, one table row per
+ aspect, so the subsequent dialog only has to ask for the
+ combined answer. Align all column edges of the table.
+
+ In every table cell you *MUST* escape each literal pipe
+ character outside a code span as `\|` and you *MUST*
+ open *and* close every backtick code span within the
+ *same* cell -- an unescaped pipe or an unbalanced
+ backtick run splits the cell and silently degrades the
+ entire table into a plain text rendering:
+
+ <template>
+ ⧉ **ASE**: <round-id/>: *Relentless Interviewing Until Clarity*
+
+ | QUESTION | ANSWERS |
+ | ------------- | ----------- |
+ | <question-1/> | <answer-1/> |
+ | <question-2/> | <answer-2/> |
+ | [...] | [...] |
+
+ Legend: **DOM**: Domain (MUST), **IFC**: Interface (MUST), **ARC**: Architecture (SHOULD), **IMP**: Implementation (MAY)
+ **Qn**: round-local question id, **An**: question-local answer id, ⚑: current decision state
+ </template>
+
+ 2. Show a custom dialog. Its only answer options are the
+ two fixed ones, so the user normally answers all aspects in
+ *one* free-text reply:
+
+ <expand name="custom-dialog" arg1="--other">
+ <round-id/>: What is your (combined) answer to all (or a subset) of the above questions? (keywords or `Qn:An` references are sufficient)
+ SKIP GRILLING: skip all remaining grilling and continue with the implementation
+ STOP SKILL: stop the entire skill immediately
+ </expand>
+
+ Dispatch `SKIP GRILLING`, `STOP SKILL`, and `CANCEL` as
+ defined above. Otherwise, strip any leading `OTHER: `
+ prefix from <result/> and treat the remainder as the
+ combined free-text answers to all questions of the
+ round.
+
+ 7. MERGE ANSWERS INTO TODO:
+
+ Merge all gathered answers in <result/> of the round -- the
+ combined reply -- *exclusively* back into <todo-what/> and
+ <todo-how/>. Do not output anything.
+
+ 8. SHOW CURRENT TODO:
+
+ Set <round-suffix/> to
+ ` round <m/>/<getopt-option-grill-rounds/>` if
+ <getopt-option-grill-rounds/> is greater than 1, or to
+ empty otherwise, and expand the following -- this
+ intentionally closes *every* round, so the intermediate
+ <todo-what/>/<todo-how/> states stay visible:
+
+ <expand name="todo-box" arg1="current state (after grilling<round-suffix/>)"></expand>
+
+ 6. **State: implementing:**
+
+ 1. You *MUST* first forget all previous internalized tenets and
+ then freshly internalize and strictly honor the **GENERIC
+ TENETS** and the **SPECIFYING TENETS** of the **ASE Tenets** in
+ the following creation and updating of specification content. Do
+ not output anything.
+
+ 2. <if condition="<getopt-option-worktree/> is equal `true` and <worktree-dir/> is empty">
+
+ One *single* worktree serves the whole skill run: it is created
+ *once* before the first change set is applied, and all further
+ `--loop` iterations land in it, too.
+
+ 1. Set <worktree-name/> to a unique name, derived from
+ <todo-what/>, which consists of two lower-case words
+ concatenated with a `-` character. Do not output anything.
+
+ 2. 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. If this tool call fails, only output the following
+ <template/> and then immediately *STOP* processing the
+ entire current skill, leaving the working copy *untouched*:
+
+ <template>
+ ⧉ **ASE**: ✪ skill: **ase-spec-edit**, ▶ ERROR: no Git repository or unsafe worktree directory -- cannot create worktree
+ </template>
+
+ 3. Determine the *existing worktrees* and *existing branches*
+ by running the commands `git worktree list --porcelain` and
+ `git branch --list` (taken exactly as given) and capturing
+ their outputs. If the worktree directory <worktree-dir/> or
+ the branch <worktree-name/> 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*:
+
+ <template>
+ ⧉ **ASE**: ✪ skill: **ase-spec-edit**, ▶ ERROR: worktree or branch **<worktree-name/>** already exists
+ </template>
+
+ 4. Create the worktree by running the command
+ `git worktree add "<worktree-dir/>"` (taken exactly as
+ given), which creates the directory *and* -- named after its
+ last path component -- the branch <worktree-name/> from
+ `HEAD`. If this command fails, only output the following
+ <template/> and then immediately *STOP* processing the
+ entire current skill, leaving the working copy *untouched*:
+
+ <template>
+ ⧉ **ASE**: ✪ skill: **ase-spec-edit**, ▶ ERROR: worktree **<worktree-name/>** failed to create
+ </template>
+
+ 5. Only output the following <template/>:
+
+ <template>
+ ⧉ **ASE**: ✪ skill: **ase-spec-edit**, ◉ worktree: **.ase/worktree/<worktree-name/>**, ▶ status: **worktree created**
+ </template>
+
+ </if>
+
+ 3. Call the `ase_timestamp(format: "yyyy-LL-dd HH:mm")` tool of the
+ `ase` MCP server *once* to find out the current time and store
+ it in <timestamp-modified/>. Do not output anything.
+
+ 4. Apply the edit by modifying the affected `SPEC` *artifacts* with
+ a corresponding, complete *change set*, honoring *only*
+ <todo-what/> and <todo-how/> plus the information gathered in
+ the *discovering* state.
+
+ The change set *MUST* keep every touched artifact conformant to
+ the `SPEC` format contract (`ase-format-spec.md`): the
+ `Created:`/`Modified:` frontmatter block, the heading levels,
+ the Complex/Concise/Grouped format variants, the schema-allowed
+ object kinds, nestings, and property keys, the object ids and
+ `{{<id/>}}` anchors, the `, BECAUSE ` rationale split, and the
+ `[[xxx]]` references.
+
+ *Generate* a `SPEC` artifact which does not yet exist but is
+ warranted by the edit, using <timestamp-modified/> for both its
+ `Created:` and `Modified:` timestamps. Whenever an *existing*
+ artifact is changed and carries a `Modified:
+ <timestamp-modified-old/>` line, replace this with `Modified:
+ <timestamp-modified/>`.
+
+ Also, if a `CHANGELOG.md` file exists, make an appropriate entry
+ there, too.
+
+ <if condition="<worktree-dir/> is not empty">
+ The change set *MUST* land *exclusively inside* the worktree
+ <worktree-dir/>: resolve *every* file path relative to
+ <worktree-dir/> instead of the original working copy. 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>
+
+ 5. Output only the following <template/>. You *MUST* *NOT* output a
+ change summary, a list of modified artifacts, a rationale, or a
+ unified diff of the changes -- *independent* of
+ <ase-project-boxing/>, whose exposure rules are explicitly
+ *overridden* here:
+
+ <template>
+ ⧉ **ASE**: ✪ skill: **ase-spec-edit**, ▶ status: **changes applied**
+ </template>
+
+ 7. **State: verifying:**
+
+ Enter this state only if <getopt-option-verify/> is equal `true`.
+ Otherwise you *MUST* *strictly skip* the entire state and *any*
+ verification: do *NOT* validate the specification at all and do
+ *NOT* run any build, tests, linter, or type-checker.
+
+ 1. Validate the specification and capture its <diagnostics/> array
+ of `{ file, line, column, message }` objects:
+
+ <if condition="<worktree-dir/> is not empty">
+ Run the command `ase spec lint` with <worktree-dir/> as its
+ working directory and parse its
+ `<file/>:<line/>:<column/>: <message/>` output lines into
+ <diagnostics/> -- the `ase_specbook_lint` tool always validates
+ the *project* working copy and hence *MUST* *NOT* be used here.
+ </if>
+ <else>
+ Call the `ase_specbook_lint()` tool of the `ase` MCP server and
+ read its returned `diagnostics` array into <diagnostics/>.
+ </else>
+
+ 2. If <diagnostics/> is not empty, fix the reported problems in the
+ affected `SPEC` artifacts via the `Edit`/`Write` tools and
+ re-validate as in item 7.1 -- for at most *three* rounds in
+ total.
+
+ 3. <if condition="<diagnostics/> is not empty after the last round">
+
+ Only output the following <template/>, listing one bullet line
+ per remaining diagnostic:
+
+ <template>
+ ⧉ **ASE**: ✪ skill: **ase-spec-edit**, ▶ status: **verification failed**
+
+ <ase-tpl-bullet-signal/> **REMAINING DIAGNOSTICS**:
+
+ - `<file/>:<line/>:<column/>`: <message/>
+ [...]
+ </template>
+
+ </if>
+ <else>
+
+ Only output the following <template/>:
+
+ <template>
+ ⧉ **ASE**: ✪ skill: **ase-spec-edit**, ▶ status: **verification passed**
+ </template>
+
+ </else>
+
+ 8. **Loop or Finish:**
+
+ <if condition="<getopt-option-loop/> is equal `true`">
+ Continue with the *next* iteration at the *querying* state
+ (item 3 above). Do not output anything in this item.
+ </if>
+ <else>
+ Finish the skill processing, but first give the closing hints by
+ expanding the following (which, depending on the configured
+ <ase-guidance-level/>, may each expand into nothing and hence emit
+ no output at all):
+
+ <ase-tpl-hint level="normal">
+ Use `/ase-sync-reconcile -s SPEC` to propagate the specification changes into the remaining artifact kinds, and `/ase-sync-export` to re-materialize the derived export files.
+ </ase-tpl-hint>
+
+ <ase-tpl-hint level="verbose">
+ Use `/ase-spec-edit --grill` to stress-test the query first, `--verify` to validate the specification afterwards, and `--loop` to chain several edits.
+ </ase-tpl-hint>
+ </else>