@rse/ase 0.9.12 → 0.9.13

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (38) hide show
  1. package/dst/ase-compat.js +1 -1
  2. package/dst/ase-diagram.js +5 -2
  3. package/dst/ase-getopt.js +2 -1
  4. package/dst/ase-mcp.js +2 -0
  5. package/dst/ase-persona.js +4 -1
  6. package/dst/ase-skills.js +13 -3
  7. package/dst/ase-statusline.js +2 -2
  8. package/dst/ase.js +1 -1
  9. package/package.json +1 -1
  10. package/plugin/.claude-plugin/plugin.json +1 -1
  11. package/plugin/.codex-plugin/plugin.json +1 -1
  12. package/plugin/.github/plugin/plugin.json +1 -1
  13. package/plugin/meta/ase-dialog.md +1 -1
  14. package/plugin/meta/ase-format-arch.md +26 -9
  15. package/plugin/meta/ase-format-meta.md +7 -3
  16. package/plugin/meta/ase-format-spec.md +11 -6
  17. package/plugin/meta/ase-getopt.md +6 -2
  18. package/plugin/meta/ase-skill.md +43 -19
  19. package/plugin/package.json +1 -1
  20. package/plugin/skills/ase-arch-analyze/SKILL.md +17 -10
  21. package/plugin/skills/ase-code-craft/SKILL.md +16 -4
  22. package/plugin/skills/ase-code-explain/SKILL.md +0 -1
  23. package/plugin/skills/ase-code-insight/SKILL.md +1 -1
  24. package/plugin/skills/ase-code-lint/SKILL.md +13 -14
  25. package/plugin/skills/ase-code-refactor/SKILL.md +16 -4
  26. package/plugin/skills/ase-code-resolve/SKILL.md +17 -4
  27. package/plugin/skills/ase-docs-proofread/SKILL.md +11 -12
  28. package/plugin/skills/ase-meta-compat/SKILL.md +2 -12
  29. package/plugin/skills/ase-meta-diff/SKILL.md +3 -3
  30. package/plugin/skills/ase-meta-evaluate/SKILL.md +20 -18
  31. package/plugin/skills/ase-meta-quorum/SKILL.md +3 -3
  32. package/plugin/skills/ase-task-condense/SKILL.md +6 -0
  33. package/plugin/skills/ase-task-edit/SKILL.md +6 -2
  34. package/plugin/skills/ase-task-grill/SKILL.md +9 -6
  35. package/plugin/skills/ase-task-id/SKILL.md +3 -3
  36. package/plugin/skills/ase-task-implement/SKILL.md +6 -2
  37. package/plugin/skills/ase-task-preflight/SKILL.md +5 -1
  38. package/plugin/skills/ase-task-rename/SKILL.md +9 -0
package/dst/ase-compat.js CHANGED
@@ -12,7 +12,7 @@ const EXPECTED = {
12
12
  "xml-placeholders/overwrite": "99",
13
13
  "xml-placeholders/indexed": "+1,-1",
14
14
  "xml-placeholders/nested-attr": "20",
15
- "xml-placeholders/entity": "",
15
+ "xml-placeholders/entity": "⦿",
16
16
  /* control-flow */
17
17
  "control-flow/branch": "mid",
18
18
  "control-flow/while-sum": "15",
@@ -117,12 +117,15 @@ export class Diagram {
117
117
  /* detect terminal color capability */
118
118
  static detectColorMode() {
119
119
  let mode = "none";
120
+ let explicit = false;
120
121
  /* attempt 1: query environment variable (explicitly) */
121
122
  if (process.env.ASE_TERM_COLORS !== undefined)
122
- if (/^(?:none|ansi16|ansi256)$/.test(process.env.ASE_TERM_COLORS))
123
+ if (/^(?:none|ansi16|ansi256)$/.test(process.env.ASE_TERM_COLORS)) {
123
124
  mode = process.env.ASE_TERM_COLORS;
125
+ explicit = true;
126
+ }
124
127
  /* attempt 2: query stdout */
125
- if (mode === "none" && process.stdout.isTTY) {
128
+ if (!explicit && process.stdout.isTTY) {
126
129
  const depth = process.stdout.getColorDepth();
127
130
  if (depth >= 8)
128
131
  mode = "ansi256";
package/dst/ase-getopt.js CHANGED
@@ -108,7 +108,8 @@ export class GetoptMCP {
108
108
  if (listOpts.length > 0) {
109
109
  const opts = cmd.opts();
110
110
  for (const { long, choices } of listOpts) {
111
- const v = opts[long];
111
+ const key = long.replace(/-(.)/g, (_, c) => c.toUpperCase());
112
+ const v = opts[key];
112
113
  if (typeof v !== "string")
113
114
  continue;
114
115
  const items = v.split(",").map((s) => s.trim()).filter((s) => s.length > 0);
package/dst/ase-mcp.js CHANGED
@@ -133,6 +133,8 @@ export default class MCPCommand {
133
133
  };
134
134
  /* trigger a reconnect chain (idempotent while one is active) */
135
135
  const triggerReconnect = (reason) => {
136
+ if (reconnecting)
137
+ return;
136
138
  reconnecting = true;
137
139
  this.log.write("warning", `mcp: ${reason} — reconnecting`);
138
140
  reconnect(0).catch(() => { });
@@ -21,7 +21,10 @@ export class Persona {
21
21
  const val = cfg.get("agent.persona");
22
22
  if (val === undefined)
23
23
  return "engineer";
24
- return String(isScalar(val) ? val.value : val);
24
+ const style = String(isScalar(val) ? val.value : val);
25
+ if (!Persona.styles.includes(style))
26
+ return "engineer";
27
+ return style;
25
28
  }
26
29
  /* set the persona style on the strongest scope of an optional session */
27
30
  static set(log, style, session) {
package/dst/ase-skills.js CHANGED
@@ -263,10 +263,20 @@ export class Skills {
263
263
  const halfLife = 365 / 2;
264
264
  /* lifespan requires both timestamps; recentness requires the
265
265
  updated timestamp -- any unavailable date-derived factor is
266
- treated as neutral `1` so the entry can still be ranked by the
267
- remaining metrics, instead of collapsing the product to zero */
266
+ given a neutral default so the entry can still be ranked by the
267
+ remaining metrics, instead of collapsing the product to zero.
268
+ For `lifespan` (an unbounded duration) the multiplicative-neutral
269
+ `1` is also the low floor, so a missing value cannot unfairly
270
+ inflate the rank. For `recentness`, however, the value is an
271
+ exp-decay factor bounded in `(0,1]` where `1` is the *ceiling*
272
+ (a just-now update), not a floor -- defaulting a missing update
273
+ date to `1` would hand packages with absent metadata the highest
274
+ possible recentness and let them outrank genuinely fresh ones.
275
+ We therefore default a missing `recentness` to the decay value at
276
+ one half-life (`0.5`), a conservative midpoint that keeps the
277
+ entry rankable without rewarding the missing date. */
268
278
  const lifespan = (!Number.isNaN(cMs) && !Number.isNaN(uMs)) ? Math.max(0, uMs - cMs) : 1;
269
- const recentness = !Number.isNaN(uMs) ? Math.exp(-Math.max(0, (now - uMs) / msPerDay) / halfLife) : 1;
279
+ const recentness = !Number.isNaN(uMs) ? Math.exp(-Math.max(0, (now - uMs) / msPerDay) / halfLife) : 0.5;
270
280
  return d * s * lifespan * recentness;
271
281
  }
272
282
  /* compute the per-alternative product-sum (rating) row from a
@@ -67,7 +67,7 @@ const formatTokens = (n) => {
67
67
  if (n >= 1_000_000)
68
68
  return `${(n / 1_000_000).toFixed(1)}M`;
69
69
  if (n >= 1_000)
70
- return `${Math.round(n / 1_000)}k`;
70
+ return `${(n / 1_000).toFixed(1)}k`;
71
71
  return `${n}`;
72
72
  };
73
73
  /* format a millisecond duration as a compact human-readable string (e.g. 6d 12hr 7m, 4hr 27m, 12m 30s) */
@@ -362,7 +362,7 @@ export default class StatuslineCommand {
362
362
  emit(`${prefix("◔", "context")}${bar} ${pct}%`);
363
363
  },
364
364
  C: () => {
365
- const pct = Math.floor(data.context_window?.used_percentage ?? 0);
365
+ const pct = data.context_window?.used_percentage ?? 0;
366
366
  const tokensCur = (data.context_window?.total_input_tokens ?? 0) +
367
367
  (data.context_window?.total_output_tokens ?? 0);
368
368
  const tokensLim = pct > 0 && tokensCur > 0 ? Math.round(tokensCur * 100 / pct) : 0;
package/dst/ase.js CHANGED
@@ -18,7 +18,7 @@ import ArtifactCommand from "./ase-artifact.js";
18
18
  import CompatCommand from "./ase-compat.js";
19
19
  import pkg from "../package.json" with { type: "json" };
20
20
  /* globally initialize logger */
21
- const log = new Log("ase", "warning", "-");
21
+ const log = new Log("ase", "info", "-");
22
22
  /* main entry point (wrapped in a regular async function to avoid
23
23
  top-level await, which would be reported as "unsettled" by Node in
24
24
  the long-running daemon process spawned by "ase service start") */
package/package.json CHANGED
@@ -6,7 +6,7 @@
6
6
  "homepage": "http://github.com/rse/ase",
7
7
  "repository": { "url": "git+https://github.com/rse/ase.git", "type": "git" },
8
8
  "bugs": { "url": "http://github.com/rse/ase/issues" },
9
- "version": "0.9.12",
9
+ "version": "0.9.13",
10
10
  "license": "GPL-3.0-only",
11
11
  "author": {
12
12
  "name": "Dr. Ralf S. Engelschall",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ase",
3
- "version": "0.9.12",
3
+ "version": "0.9.13",
4
4
  "description": "Agentic Software Engineering (ASE)",
5
5
  "keywords": [ "agentic", "software", "engineering" ],
6
6
  "homepage": "https://ase.tools",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ase",
3
- "version": "0.9.12",
3
+ "version": "0.9.13",
4
4
  "description": "Agentic Software Engineering (ASE)",
5
5
  "keywords": [ "agentic", "software", "engineering" ],
6
6
  "homepage": "https://ase.tools",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ase",
3
- "version": "0.9.12",
3
+ "version": "0.9.13",
4
4
  "description": "Agentic Software Engineering (ASE)",
5
5
  "keywords": [ "agentic", "software", "engineering" ],
6
6
  "homepage": "https://ase.tools",
@@ -185,7 +185,7 @@ following procedure:
185
185
 
186
186
  Do not output anything in this step!
187
187
 
188
- 2. Dispatch according to the agent tool:
188
+ 2. Render the custom dialog, collect the user input, and dispatch on the result:
189
189
 
190
190
  1. You *MUST* not output anything in this step.
191
191
 
@@ -243,7 +243,7 @@ at runtime.
243
243
  for the component's existence and boundary.
244
244
 
245
245
  - In case a component has no dependencies at all, the
246
- entire `- Depends On:` bullet point is omitted.
246
+ entire `- Depends On:` bullet point is omitted.
247
247
 
248
248
  - In case the rationale is not present, the
249
249
  entire `, **BECAUSE** [...]` clause is omitted.
@@ -666,8 +666,16 @@ How the Non-Functional Requirements (NR) are addressed.
666
666
  perspective addresses, one of `Performance`, `Scalability`,
667
667
  `Reliability`, `Availability`, `Security`, `Privacy`,
668
668
  `Usability`, `Accessibility`, `Maintainability`, `Portability`,
669
- `Compatibility`, or `Compliance` (aligned with the Non-Functional
670
- Requirements categories).
669
+ `Compatibility`, or `Compliance`. This enumeration is a
670
+ solution-oriented refinement of the Non-Functional Requirements
671
+ (NR) categories and intentionally differs from them: the NR
672
+ categories follow the ISO/IEC 25010:2023 top-level characteristics
673
+ (and include `Safety` and `Flexibility`), whereas the perspective
674
+ qualities decompose some of these into the finer-grained,
675
+ architecturally actionable attributes `Scalability`,
676
+ `Availability`, `Privacy`, `Accessibility`, and `Portability`. A
677
+ perspective's quality therefore need not match the category of the
678
+ `SPEC-NR-<spec-nr-requirement-id/>` it addresses.
671
679
 
672
680
  - <arch-qp-perspective-requirement/> is a
673
681
  `SPEC-NR-<spec-nr-requirement-id/>` reference to the corresponding
@@ -722,10 +730,11 @@ forces at play, the chosen response, and the reasoning that justifies it.
722
730
 
723
731
  ## DECISION: <arch-dr-decision-name/> <a id="ARCH-DR-<arch-dr-decision-id/>"></a>
724
732
 
725
- - Status: <arch-dr-decision-status/>
726
- - Affects: <arch-dr-decision-element/>, [...]
727
- - Created: <arch-dr-decision-created/>
728
- - Modified: <arch-dr-decision-modified/>
733
+ - Status: <arch-dr-decision-status/>
734
+ - Affects: <arch-dr-decision-element/>, [...]
735
+ - Superseded-By: <arch-dr-decision-superseded-by/>
736
+ - Created: <arch-dr-decision-created/>
737
+ - Modified: <arch-dr-decision-modified/>
729
738
 
730
739
  - WHEN (Context):
731
740
  <arch-dr-decision-context/>
@@ -752,12 +761,17 @@ forces at play, the chosen response, and the reasoning that justifies it.
752
761
  <arch-dr-decision-decision/>, not longer than 80 characters.
753
762
 
754
763
  - <arch-dr-decision-status/> is one of `proposed`, `accepted`,
755
- `deprecated`, or `superseded by ARCH-DR-<arch-dr-decision-id/>`.
764
+ `deprecated`, or `superseded`.
756
765
 
757
766
  - <arch-dr-decision-element/> is an `ARCH-FV-<arch-fv-component-id/>`
758
767
  or `ARCH-DP-<arch-dp-node-id/>` reference to the functional
759
768
  element or deployment node the decision affects.
760
769
 
770
+ - <arch-dr-decision-superseded-by/> is an
771
+ `ARCH-DR-<arch-dr-decision-id/>` reference to the decision that
772
+ supersedes this decision. It is present if and only if the
773
+ <arch-dr-decision-status/> is `superseded`.
774
+
761
775
  - <arch-dr-decision-created/> is the timestamp when this decision was
762
776
  created, and <arch-dr-decision-modified/> is the timestamp when
763
777
  this decision was last modified, both in the same ISO-style format
@@ -832,7 +846,10 @@ forces at play, the chosen response, and the reasoning that justifies it.
832
846
  job.
833
847
 
834
848
  - In case the element reference is not present, the
835
- entire `- Affects:` bullet point is omitted.
849
+ entire `- Affects:` bullet point is omitted.
850
+
851
+ - In case the <arch-dr-decision-status/> is not `superseded`, the
852
+ entire `- Superseded-By:` bullet point is omitted.
836
853
 
837
854
  - In case the `NOTES (Background)` content is not present, the
838
855
  entire `NOTES (Background)` chunk is omitted.
@@ -29,9 +29,13 @@ Artifact Meta Information
29
29
  - **Artifact**:
30
30
 
31
31
  At level 2, each **Artifact Set** is composed of many **Artifact**s.
32
- Each **Artifact** has a unique identifier <artifact-id/>, which is
33
- an upper-case, two-letter identifier (e.g. `CJ` for `Customer
34
- Journey`) derived from the **Artifact** name.
32
+ Each **Artifact** has an identifier <artifact-id/>, which is an
33
+ upper-case, two-letter identifier (e.g. `CJ` for `Customer Journey`)
34
+ derived from the **Artifact** name. The <artifact-id/> is unique
35
+ only *within* its **Artifact Set**; the globally-unique handle of an
36
+ **Artifact** is the qualified form <artifact-set-id/>-<artifact-id/>
37
+ (e.g. `SPEC-DP` and `ARCH-DP` are distinct artifacts). All
38
+ references to an **Artifact** *MUST* use this qualified form.
35
39
 
36
40
  Each **Artifact** also has a sequence number <artifact-no/>, which
37
41
  is the zero-padded, two-digit position of the **Artifact** (starting
@@ -871,8 +871,8 @@ for main, alternative, and exceptional paths.
871
871
 
872
872
  - <spec-uc-usecase-description/>: a concise paragraph (1-3
873
873
  sentences) of prose describing the use case at a glance, without
874
- prescribing the step-by-step flow (which belongs to the **Use
875
- Case Scenarios** **Artifact**).
874
+ prescribing the step-by-step flow (which belongs to the
875
+ **SCENARIO** blocks of this use case).
876
876
 
877
877
  - In case the use case realizes no specific functional requirement,
878
878
  the entire `- Requirements:` bullet point is omitted.
@@ -884,7 +884,7 @@ for main, alternative, and exceptional paths.
884
884
 
885
885
  <format>
886
886
 
887
- ### SCENARIO: <spec-uc-usecase-scenario-name/> (<spec-uc-usecase-scenario-type/>)
887
+ ### SCENARIO: <spec-uc-usecase-scenario-name/> (<spec-uc-usecase-scenario-type/>) <a id="SPEC-UC-<spec-uc-usecase-id/>-<spec-uc-usecase-scenario-id/>"></a>
888
888
 
889
889
  1. <spec-uc-usecase-scenario-step/>
890
890
  2. <spec-uc-usecase-scenario-step/>
@@ -894,6 +894,11 @@ for main, alternative, and exceptional paths.
894
894
 
895
895
  - <spec-uc-usecase-scenario/> details:
896
896
 
897
+ - <spec-uc-usecase-scenario-id/>: per-use-case unique "slug" of
898
+ always 1-3 lower-cased words (concatenated with "-" characters
899
+ and in total not longer than 30 characters), derived from
900
+ <spec-uc-usecase-scenario-name/>.
901
+
897
902
  - <spec-uc-usecase-scenario-name/>: a short (3-8 word) summary of the
898
903
  scenario.
899
904
 
@@ -1213,9 +1218,9 @@ turn.
1213
1218
  visualizes (optional).
1214
1219
 
1215
1220
  - <spec-ds-storyboard-scenario/> is a
1216
- Use Case scenario type `<spec-uc-usecase-scenario-type/>` of
1217
- the corresponding **Aspect** of the Use Case **Artifact** the
1218
- storyboard visualizes (optional).
1221
+ `SPEC-UC-<spec-uc-usecase-id/>-<spec-uc-usecase-scenario-id/>`
1222
+ reference to the corresponding scenario **Aspect** of the Use
1223
+ Case **Artifact** the storyboard visualizes (optional).
1219
1224
 
1220
1225
  - <spec-ds-frame-name/>: a short (2-5 word) label for the screen,
1221
1226
  turn, or state depicted by the storyboard frame. Frames are
@@ -27,8 +27,8 @@ set placeholders into the context as a side-effect.
27
27
  `--<long/>[|-<short/>][=<default/>|=(<c1/>|<c2/>|...)[...]]`, set
28
28
  <getopt-option-<long/>/> to <default/> (for `=<default/>`
29
29
  form), or to the *single token* <c1/> (the first choice, both
30
- for the choice form `=(<c1/>|<c2>/|...)` and for the list form
31
- `=(<c1/>|<c2>/|...)...` -- an *unsupplied* list-option always
30
+ for the choice form `=(<c1/>|<c2/>|...)` and for the list form
31
+ `=(<c1/>|<c2/>|...)...` -- an *unsupplied* list-option always
32
32
  defaults to the single token <c1/>, *not* to a whole list),
33
33
  or to `false` (for value-less options). Then set
34
34
  <getopt-arguments><getopt-args/></getopt-arguments>.
@@ -63,6 +63,10 @@ set placeholders into the context as a side-effect.
63
63
  validate each remaining token themselves as they consume it).
64
64
 
65
65
  4. **Short-Circuit for Error**:
66
+ This step is the *sole* and *authoritative* handler for an
67
+ `ERROR:`-prefixed `ase_getopt` response; the generic MCP-Tool-Calls
68
+ error rule (see `ase-skill.md`) explicitly does *NOT* apply here, so
69
+ only the <template/> below is emitted (never both).
66
70
  If <text/> starts with `ERROR:`:
67
71
  Remove all `ERROR:` or `error:` prefixes from <text/>.
68
72
  Then only output the following <template/> and
@@ -119,15 +119,25 @@ Skill Sequential Processing
119
119
  For speed, emit *all* `TaskCreate` calls together in a *single* turn
120
120
  (issued in parallel), *not* one-per-turn sequentially. Do *not*
121
121
  rely on the call order to establish the step order, as the parallel
122
- results carry no guaranteed ordering. Instead, in the *immediately
123
- following* turn, establish the strict order explicitly by chaining
124
- the created tasks with `TaskUpdate`: for each <step/> after the
125
- first one, call `TaskUpdate({ taskId: "<this/>", addBlockedBy:
126
- [ "<prev/>" ] })` so that every step (with `taskId` <this/>) is
127
- blocked by its predecessor step (with `taskId` <prev/>).
122
+ results carry no guaranteed ordering.
123
+
124
+ Instead, in the *immediately single following* turn, first
125
+ reconstruct the step-id-to-taskId mapping: because each task's
126
+ `subject` equals the originating <step/> `id` (and <step/> ids are
127
+ unique), match every created task back to its <step/> by comparing
128
+ the task's `subject` to the step `id` -- read the ids straight from
129
+ the `TaskCreate` results, or call `TaskList` if the results are
130
+ no longer at hand.
131
+
132
+ Then establish the strict order explicitly by chaining the created
133
+ tasks with `TaskUpdate`: for each <step/> after the first one,
134
+ resolve <this/> and <prev/> to the mapped `taskId` values and
135
+ call `TaskUpdate({ taskId: "<this/>", addBlockedBy: [ "<prev/>" ]
136
+ })` so that every step (with `taskId` <this/>) is blocked by its
137
+ predecessor step (with `taskId` <prev/>).
128
138
 
129
139
  - *IMPORTANT*: For each <step/> you *MUST* use the `TaskUpdate` tool
130
- for updating its status during processing.
140
+ for updating its status *during* processing, once a <step/> finished.
131
141
 
132
142
  - *IMPORTANT*: You *MUST* sequentially execute every <step/> in
133
143
  a <flow/> *EXACTLY* as the instructions specify.
@@ -172,6 +182,12 @@ MCP Tool Calls
172
182
  ⧉ **ASE**: **ERROR:** MCP tool failed: <info/>
173
183
  </template>
174
184
 
185
+ *EXCEPTION*: this rule does *NOT* apply to the `ase_getopt` tool,
186
+ whose `ERROR:`-prefixed output is *expected* option-parsing
187
+ feedback handled exclusively by step 4 of the `getopt` procedure
188
+ (see `ase-getopt.md`); never emit this generic template for an
189
+ `ase_getopt` response.
190
+
175
191
  - Only on a clean response: proceed as the skill instructs.
176
192
 
177
193
  Skill Identification
@@ -232,9 +248,11 @@ Template Patterns
232
248
  </template>
233
249
 
234
250
  - When `<ase-tpl-head title="<title/>"/>` should be expanded, use
235
- (where <title-len/> is the number of characters in the string
236
- `⧉ ASE: <title/>`, and <bar/> is the `─` character repeated exactly
237
- (67 - <title-len/>) times):
251
+ (where <raw-title/> is the visible un-styled text `⧉ ASE: <title/>`,
252
+ <raw-title-len/> is the number of characters in <raw-title/>, and
253
+ <bar/> is the `─` character repeated exactly (67 - <raw-title-len/>)
254
+ times -- the very same bar-width rule as `<ase-tpl-foot/>` and
255
+ `<ase-tpl-boxed/>`, so equal visible text yields equal total width):
238
256
 
239
257
  <template>
240
258
 
@@ -251,9 +269,11 @@ Template Patterns
251
269
  </template>
252
270
 
253
271
  - When `<ase-tpl-foot title="<title/>"/>` should be expanded, use
254
- (where <title-len/> is the number of characters in the string
255
- `⧉ ASE: <title/>`, and <bar/> is the `─` character repeated exactly
256
- (67 - <title-len/>) times):
272
+ (where <raw-title/> is the visible un-styled text `⧉ ASE: <title/>`,
273
+ <raw-title-len/> is the number of characters in <raw-title/>, and
274
+ <bar/> is the `─` character repeated exactly (67 - <raw-title-len/>)
275
+ times -- the very same bar-width rule as `<ase-tpl-head/>` and
276
+ `<ase-tpl-boxed/>`, so equal visible text yields equal total width):
257
277
 
258
278
  <template>
259
279
 
@@ -275,19 +295,23 @@ Template Patterns
275
295
  </else>
276
296
 
277
297
  - When `<ase-tpl-boxed title="<title/>"[ subtitle="<subtitle/>"]><content/></ase-tpl-boxed>`
278
- should be expanded use the following helper placeholder and then the <template/>:
298
+ should be expanded use the following helper placeholders and then
299
+ the following <template/>:
279
300
 
280
301
  - <if condition="<subtitle/> is not empty">
281
- Set <raw-title>⧉ ASE: <title/>: <subtitle/><raw-title>.
302
+ Set <raw-title>⧉ ASE: <title/>: <subtitle/></raw-title>.
282
303
  Set <render-title>⧉ ASE: **`<title/>`**: `<subtitle/>`</render-title>.
283
304
  </if>
284
305
  <else>
285
- Set <raw-title>⧉ ASE: <title/><raw-title>.
306
+ Set <raw-title>⧉ ASE: <title/></raw-title>.
286
307
  Set <render-title>⧉ ASE: **`<title/>`**</render-title>.
287
308
  </else>
288
- - Set <raw-title-len/> to the number of characters in <raw-title/>.
289
- - Set <bar/> to the `─` character repeated exactly (67 - <raw-title-len/>) times.
290
- - Set <body> to <content/> with all line-starts prefixed with `│ `.
309
+ - Set <raw-title-len/> to the number of characters in the visible
310
+ un-styled text <raw-title/>.
311
+ - Set <bar/> to the `─` character repeated exactly (67 - <raw-title-len/>)
312
+ times -- the very same bar-width rule as `<ase-tpl-head/>` and
313
+ `<ase-tpl-foot/>`, so equal visible text yields equal total width.
314
+ - Set <body/> to <content/> with all line-starts prefixed with `│ `.
291
315
 
292
316
  <template>
293
317
 
@@ -6,7 +6,7 @@
6
6
  "homepage": "http://github.com/rse/ase",
7
7
  "repository": { "url": "git+https://github.com/rse/ase.git", "type": "git" },
8
8
  "bugs": { "url": "http://github.com/rse/ase/issues" },
9
- "version": "0.9.12",
9
+ "version": "0.9.13",
10
10
  "license": "GPL-3.0-only",
11
11
  "author": {
12
12
  "name": "Dr. Ralf S. Engelschall",
@@ -375,13 +375,19 @@ interface quality, quality attributes, and architecture governance.
375
375
  - *Focal aspect*: <focal-aspect/> - <focal-state/>
376
376
  - *In tension with*: <partner-list/>
377
377
 
378
- **RECOMMENDED**: lean toward *<focal|partners/>*
378
+ **RECOMMENDED**: lean toward *<lean-toward/>*
379
379
  *Reason*: <rationale/>
380
380
  *Implies*:
381
- - <partner-aspect-1/>: <partner-implication-1/>
382
- - <partner-aspect-2/>: <partner-implication-2/>
381
+ - <partner-aspect/>: <partner-implication/>
382
+ - ...
383
383
  </template>
384
384
 
385
+ For each partner in <partner-list/>, repeat the `*Implies*` line,
386
+ set <partner-aspect/> to the partner aspect, and set
387
+ <partner-implication/> to its brief implication. Set <lean-toward/>
388
+ to the aspect direction the recommendation favors (the *focal
389
+ aspect* or the *partners*).
390
+
385
391
  Hints:
386
392
 
387
393
  - For the final results, do *not* output anything else,
@@ -429,13 +435,14 @@ interface quality, quality attributes, and architecture governance.
429
435
  for the same aspect, and never emit both halves of a
430
436
  tension pair as separate PROBLEMs.
431
437
 
432
- - *Additionally*, first call the `ase_kv_clear()` tool of the `ase`
433
- MCP server to clear the in-memory key/value store, and then,
434
- for *every* reported PROBLEM and TRADEOFF, persist its finding
435
- result via the `ase_kv_set` tool of the `ase` MCP server, using
436
- `key` set to `ase-issue-P<n/>` (for PROBLEMs) or
437
- `ase-issue-T<n/>` (for TRADEOFFs) and `val` set to
438
- `<title/>: <description/>`.
438
+ - *Additionally*, persist all reported findings in a *single*
439
+ `ase_kv_batch` call to the `ase` MCP server with `transactional`
440
+ set to `true`. The `commands` parameter array of this call
441
+ starts with one `{ command: "clear" }` entry, followed by one
442
+ `{ command: "set", key: "ase-issue-P<n/>", val: "<title/>:
443
+ <description/>" }` entry per reported PROBLEM and one
444
+ `{ command: "set", key: "ase-issue-T<n/>", val: "<title/>:
445
+ <description/>" }` entry per reported TRADEOFF.
439
446
  </step>
440
447
 
441
448
  4. <step id="STEP 4: Give Final Hint">
@@ -319,7 +319,19 @@ permitted way to persist artifacts is via `ase_task_save(...)`.
319
319
  as <head/> (or `none` if the list is `none`/empty).
320
320
  Set <args>--int-reuse-task</args>.
321
321
 
322
- 1. <if condition="<head/> is equal `IMPLEMENT`">
322
+ 1. <if condition="<head/> is equal `DONE`">
323
+ Consume the head: set <getopt-option-next/> to the remaining
324
+ tokens (joined back with `,`, or `none` if empty). `DONE`
325
+ means the freshly composed plan is finalized as-is, so do
326
+ *not* hand off to `ase-task-edit`. Only output the following
327
+ <template/> and then *STOP*. Do *not* implement the plan.
328
+
329
+ <template>
330
+ ⧉ **ASE**: ◉ task: **<ase-task-id/>**, ✪ plan: **<words/>** words, ▶ status: **plan finalized -- done**
331
+ </template>
332
+ </if>
333
+
334
+ 2. <elseif condition="<head/> is equal `IMPLEMENT`">
323
335
  Consume the head: set <getopt-option-next/> to the remaining
324
336
  tokens (joined back with `,`, or `none` if empty).
325
337
  <if condition="<getopt-option-next/> is not equal `none`">
@@ -327,9 +339,9 @@ permitted way to persist artifacts is via `ase_task_save(...)`.
327
339
  </if>
328
340
  Call the tool `Skill(skill: "ase:ase-task-implement", args: "<args/>")`
329
341
  to *implement* the freshly composed plan, bypassing `ase-task-edit`.
330
- </if>
342
+ </elseif>
331
343
 
332
- 2. <elseif condition="<head/> is equal `PREFLIGHT`">
344
+ 3. <elseif condition="<head/> is equal `PREFLIGHT`">
333
345
  Consume the head: set <getopt-option-next/> to the remaining
334
346
  tokens (joined back with `,`, or `none` if empty).
335
347
  <if condition="<getopt-option-next/> is not equal `none`">
@@ -339,7 +351,7 @@ permitted way to persist artifacts is via `ase_task_save(...)`.
339
351
  to *preflight* the freshly composed plan, bypassing `ase-task-edit`.
340
352
  </elseif>
341
353
 
342
- 3. <else>
354
+ 4. <else>
343
355
  Hand off to `ase-task-edit`.
344
356
  <if condition="<head/> is equal `EDIT`">
345
357
  Consume the head: set <getopt-option-next/> to the remaining
@@ -8,7 +8,6 @@ user-invocable: true
8
8
  disable-model-invocation: false
9
9
  effort: high
10
10
  allowed-tools:
11
- - "Skill"
12
11
  - "Agent"
13
12
  ---
14
13
 
@@ -12,7 +12,7 @@ allowed-tools:
12
12
  - "Bash(sort *)"
13
13
  - "Bash(uniq *)"
14
14
  - "Bash(head *)"
15
- - "Skill"
15
+ - "Bash(git log * | grep * | sort * | uniq * | sort * | head *)"
16
16
  - "Agent"
17
17
  ---
18
18
 
@@ -143,13 +143,24 @@ related to a set of code quality aspects.
143
143
  Set <new-text/> to the `new_text` field of <item/>.
144
144
  Set <context-after/> to the `context_after` field of <item/>.
145
145
 
146
- 2. If <context/> is not empty, set
146
+ 2. Set <old-start/> to the line of the first hunk line, i.e.,
147
+ the line of <context-before/> (one before <line/>).
148
+ Set <new-start/> to the same as <old-start/> (the unchanged
149
+ <context-before/> line shares the same start in both files).
150
+ Set <old-count/> to the total number of old-side hunk lines, i.e.,
151
+ the number of lines in <context-before/>, <old-text/>, and
152
+ <context-after/> combined.
153
+ Set <new-count/> to the total number of new-side hunk lines, i.e.,
154
+ the number of lines in <context-before/>, <new-text/>, and
155
+ <context-after/> combined.
156
+
157
+ 3. If <context/> is not empty, set
147
158
  <context><context/>,</context> (append a comma).
148
159
  Then append the following <template/> to <context/>:
149
160
 
150
161
  <template>`<file/>`:<line/></template>
151
162
 
152
- 3. Append the following <template/> to <diff-file/>:
163
+ 4. Append the following <template/> to <diff-file/>:
153
164
 
154
165
  <template>
155
166
  @@ -<old-start/>,<old-count/> +<new-start/>,<new-count/> @@
@@ -159,18 +170,6 @@ related to a set of code quality aspects.
159
170
  <context-after/>
160
171
  </template>
161
172
 
162
- Hints:
163
- - The <old-start/> is the line of the first hunk line, i.e.,
164
- the line of <context-before/> (one before <line/>).
165
- - The <new-start/> is the same as <old-start/> (the unchanged
166
- <context-before/> line shares the same start in both files).
167
- - The <old-count/> is the total number of old-side hunk lines, i.e.,
168
- the number of lines in <context-before/>, <old-text/>, and
169
- <context-after/> combined.
170
- - The <new-count/> is the total number of new-side hunk lines, i.e.,
171
- the number of lines in <context-before/>, <new-text/>, and
172
- <context-after/> combined.
173
-
174
173
  </for>
175
174
 
176
175
  3. Append <diff-file/> to <diff/>.
@@ -308,7 +308,19 @@ permitted way to persist artifacts is via `ase_task_save(...)`.
308
308
  as <head/> (or `none` if the list is `none`/empty).
309
309
  Set <args>--int-reuse-task</args>.
310
310
 
311
- 1. <if condition="<head/> is equal `IMPLEMENT`">
311
+ 1. <if condition="<head/> is equal `DONE`">
312
+ Consume the head: set <getopt-option-next/> to the remaining
313
+ tokens (joined back with `,`, or `none` if empty). `DONE`
314
+ means the freshly composed plan is finalized as-is, so do
315
+ *not* hand off to `ase-task-edit`. Only output the following
316
+ <template/> and then *STOP*. Do *not* implement the plan.
317
+
318
+ <template>
319
+ ⧉ **ASE**: ◉ task: **<ase-task-id/>**, ✪ plan: **<words/>** words, ▶ status: **plan finalized -- done**
320
+ </template>
321
+ </if>
322
+
323
+ 2. <elseif condition="<head/> is equal `IMPLEMENT`">
312
324
  Consume the head: set <getopt-option-next/> to the remaining
313
325
  tokens (joined back with `,`, or `none` if empty).
314
326
  <if condition="<getopt-option-next/> is not equal `none`">
@@ -316,9 +328,9 @@ permitted way to persist artifacts is via `ase_task_save(...)`.
316
328
  </if>
317
329
  Call the tool `Skill(skill: "ase:ase-task-implement", args: "<args/>")`
318
330
  to *implement* the freshly composed plan, bypassing `ase-task-edit`.
319
- </if>
331
+ </elseif>
320
332
 
321
- 2. <elseif condition="<head/> is equal `PREFLIGHT`">
333
+ 3. <elseif condition="<head/> is equal `PREFLIGHT`">
322
334
  Consume the head: set <getopt-option-next/> to the remaining
323
335
  tokens (joined back with `,`, or `none` if empty).
324
336
  <if condition="<getopt-option-next/> is not equal `none`">
@@ -328,7 +340,7 @@ permitted way to persist artifacts is via `ase_task_save(...)`.
328
340
  to *preflight* the freshly composed plan, bypassing `ase-task-edit`.
329
341
  </elseif>
330
342
 
331
- 3. <else>
343
+ 4. <else>
332
344
  Hand off to `ase-task-edit`.
333
345
  <if condition="<head/> is equal `EDIT`">
334
346
  Consume the head: set <getopt-option-next/> to the remaining
@@ -71,6 +71,7 @@ permitted way to persist artifacts is via `ase_task_save(...)`.
71
71
  <problem-id/> and stop processing.
72
72
 
73
73
  2. <if condition="
74
+ <problem-id/> is not set AND
74
75
  <problem/> matches the regexp `^[a-zA-Z][a-zA-Z0-9_-]*$`
75
76
  ">
76
77
  Set <ase-task-id><problem/></ase-task-id> (set task id to problem)
@@ -366,7 +367,19 @@ permitted way to persist artifacts is via `ase_task_save(...)`.
366
367
  as <head/> (or `none` if the list is `none`/empty).
367
368
  Set <args>--int-reuse-task</args>.
368
369
 
369
- 1. <if condition="<head/> is equal `IMPLEMENT`">
370
+ 1. <if condition="<head/> is equal `DONE`">
371
+ Consume the head: set <getopt-option-next/> to the remaining
372
+ tokens (joined back with `,`, or `none` if empty). `DONE`
373
+ means the freshly composed plan is finalized as-is, so do
374
+ *not* hand off to `ase-task-edit`. Only output the following
375
+ <template/> and then *STOP*. Do *not* implement the plan.
376
+
377
+ <template>
378
+ ⧉ **ASE**: ◉ task: **<ase-task-id/>**, ✪ plan: **<words/>** words, ▶ status: **plan finalized -- done**
379
+ </template>
380
+ </if>
381
+
382
+ 2. <elseif condition="<head/> is equal `IMPLEMENT`">
370
383
  Consume the head: set <getopt-option-next/> to the remaining
371
384
  tokens (joined back with `,`, or `none` if empty).
372
385
  <if condition="<getopt-option-next/> is not equal `none`">
@@ -374,9 +387,9 @@ permitted way to persist artifacts is via `ase_task_save(...)`.
374
387
  </if>
375
388
  Call the tool `Skill(skill: "ase:ase-task-implement", args: "<args/>")`
376
389
  to *implement* the freshly composed plan, bypassing `ase-task-edit`.
377
- </if>
390
+ </elseif>
378
391
 
379
- 2. <elseif condition="<head/> is equal `PREFLIGHT`">
392
+ 3. <elseif condition="<head/> is equal `PREFLIGHT`">
380
393
  Consume the head: set <getopt-option-next/> to the remaining
381
394
  tokens (joined back with `,`, or `none` if empty).
382
395
  <if condition="<getopt-option-next/> is not equal `none`">
@@ -386,7 +399,7 @@ permitted way to persist artifacts is via `ase_task_save(...)`.
386
399
  to *preflight* the freshly composed plan, bypassing `ase-task-edit`.
387
400
  </elseif>
388
401
 
389
- 3. <else>
402
+ 4. <else>
390
403
  Hand off to `ase-task-edit`.
391
404
  <if condition="<head/> is equal `EDIT`">
392
405
  Consume the head: set <getopt-option-next/> to the remaining
@@ -119,6 +119,17 @@ Analyze documents for spelling, punctuation, or grammar errors
119
119
 
120
120
  3. <if condition="<getopt-option-auto/> is not 'true'">
121
121
 
122
+ Set <old-start/> to the line of the first hunk line, i.e.,
123
+ the line of <context-before/> (one before <line/>).
124
+ Set <new-start/> to the same as <old-start/> (the unchanged
125
+ <context-before/> line shares the same start in both files).
126
+ Set <old-count/> to the total number of old-side hunk lines, i.e.,
127
+ the number of lines in <context-before/>, <old-text/>, and
128
+ <context-after/> combined.
129
+ Set <new-count/> to the total number of new-side hunk lines, i.e.,
130
+ the number of lines in <context-before/>, <new-text/>, and
131
+ <context-after/> combined.
132
+
122
133
  Render the proposed correction as a *unified diff* with *up to
123
134
  two* lines of context in a fenced block based on the following <template/>:
124
135
 
@@ -138,18 +149,6 @@ Analyze documents for spelling, punctuation, or grammar errors
138
149
 
139
150
  </template>
140
151
 
141
- Hints:
142
- - The <old-start/> is the line of the first hunk line, i.e.,
143
- the line of <context-before/> (one before <line/>).
144
- - The <new-start/> is the same as <old-start/> (the unchanged
145
- <context-before/> line shares the same start in both files).
146
- - The <old-count/> is the total number of old-side hunk lines, i.e.,
147
- the number of lines in <context-before/>, <old-text/>, and
148
- <context-after/> combined.
149
- - The <new-count/> is the total number of new-side hunk lines, i.e.,
150
- the number of lines in <context-before/>, <new-text/>, and
151
- <context-after/> combined.
152
-
153
152
  </if>
154
153
 
155
154
  4. <if condition="<getopt-option-auto/> is not 'true'">
@@ -71,7 +71,7 @@ Procedure
71
71
  `width="<w/>"` and read the attribute `width` back.
72
72
  Record actual result for `xml-placeholders/nested-attr`.
73
73
 
74
- 6. *entity*: Evaluate the XML entity `&#x25CB;` and get the rendered
74
+ 6. *entity*: Evaluate the XML entity `&#x29BF;` and get the rendered
75
75
  Unicode character.
76
76
  Record actual result for `xml-placeholders/entity`.
77
77
 
@@ -152,8 +152,6 @@ Procedure
152
152
 
153
153
  Set <re-total/> to the number of regex probes above.
154
154
 
155
- </step>
156
-
157
155
  5. STEP 5: Probe Arithmetic
158
156
 
159
157
  Execute *all* of the following arithmetic probes (in the given
@@ -181,8 +179,6 @@ Procedure
181
179
 
182
180
  Set <arith-total/> to the number of arithmetic probes above.
183
181
 
184
- </step>
185
-
186
182
  6. STEP 6: Fetch Expected Values and Score
187
183
 
188
184
  Call the `ase_compat()` tool of the `ase` MCP server with an
@@ -209,8 +205,6 @@ Procedure
209
205
  - Set <re-pass/> to the number of `regex/*` probes that passed.
210
206
  - Set <arith-pass/> to the number of `arithmetic/*` probes that passed.
211
207
 
212
- </step>
213
-
214
208
  7. STEP 7: Compute and Report Compatibility
215
209
 
216
210
  Compute each category's *pass-rate* (a value in 0.0…1.0) by dividing
@@ -269,9 +263,7 @@ Procedure
269
263
  4. If <failures/> is not empty:
270
264
  Append to <verdict/> the suffix ` (failed: <failures/>)`.
271
265
 
272
- Output the final compatibility report with the following <template/>:
273
-
274
- <template>
266
+ Finally, output the compatibility report:
275
267
 
276
268
  **RESULTS**:
277
269
 
@@ -284,5 +276,3 @@ Procedure
284
276
  | **OVERALL** | | | **<overall-pct/>%** |
285
277
 
286
278
  **VERDICT**: <verdict/>
287
-
288
- </template>
@@ -274,9 +274,9 @@ explicitly requested by this procedure via outputs based on a <template/>!
274
274
 
275
275
  <ase-tpl-bullet-signal/> **CHANGE RISK REPORT**: Overall: **<band/>** (<aggregate/>/5)
276
276
 
277
- | Axis | Score | Findings |
278
- | ----------- | ---------- | ----------------------------------------------------------- |
279
- | **<axis/>** | <score/>/5 | ● **EVIDENCE**: <evidence/> ● **MITIGATION**: <mitigation/> |
277
+ | Axis | Score | Findings |
278
+ | ----------- | ---------- | ----------------------------------------------------------------------------------------------------- |
279
+ | **<axis/>** | <score/>/5 | ● **EVIDENCE**: <evidence/><if condition="axis score is `>= 4`"> ● **MITIGATION**: <mitigation/></if> |
280
280
  </template>
281
281
  </step>
282
282
 
@@ -81,15 +81,17 @@ multi-*criteria* decision matrix.
81
81
  - For each alternative <alternative-K/> (K=1-N), decide whether
82
82
  it is a genuine member of <class-of-alternatives/>. If any
83
83
  <alternative-K/> is *not* a member (i.e. the alternatives are not
84
- mutually comparable within a single class), let <alternative-J/>
85
- (J=1-P, P<=N) be the subset of non-member alternatives, output the
86
- following <template/> and *stop the entire flow* immediately without
87
- executing any further steps:
84
+ mutually comparable within a single class), collect the subset
85
+ of non-member alternatives into the space-separated list
86
+ <non-members/> (the <alternative-K/> for which the membership
87
+ decision was negative), output the following <template/> and
88
+ *stop the entire flow* immediately without executing any further
89
+ steps:
88
90
 
89
91
  <template>
90
92
  <ase-tpl-bullet-signal/> **ERROR: INCOMPARABLE ALTERNATIVES**: *<class-of-alternatives/>*
91
93
 
92
- <for items="<alternative-J/> [...]">
94
+ <for items="<non-members/>">
93
95
  ⚑ **<item/>** (*member of a different class*)
94
96
  </for>
95
97
  </template>
@@ -217,29 +219,29 @@ multi-*criteria* decision matrix.
217
219
  appear large; the all-negative regime is surfaced as a dedicated
218
220
  warning branch below. Do not output anything.
219
221
 
220
- - If <percentage/> is less than 0.01 (i.e. <distance/> is
221
- effectively zero relative to abs(<rating-K/>)), stop the flow after
222
- you output just the following <template/> and do not output anything
223
- else:
224
-
225
- <template>
226
- <ase-tpl-bullet-signal/> **ERROR**: ✘ *MULTIPLE BEST ALTERNATIVES FOUND*,
227
- ⚠ *Please give some hints on the criteria to ensure a single best alternative!*
228
- </template>
229
-
230
- - Otherwise, if <rating-K/> is less than zero (i.e. all alternatives
222
+ - If <rating-K/> is less than zero (i.e. all alternatives
231
223
  rate negatively and the "best" is merely the least-bad), stop the
232
224
  flow after you output just the following <template/> and do not
233
225
  output anything else. This all-negative check is evaluated *before*
234
- the small-distance check below, so that an all-negative alternative
226
+ the small-distance checks below, so that an all-negative alternative
235
227
  set with a small winning gap surfaces the all-negative warning rather
236
- than being masked by the small-distance branch:
228
+ than being masked by the multiple-best or small-distance branches:
237
229
 
238
230
  <template>
239
231
  <ase-tpl-bullet-signal/> **BEST ALTERNATIVE**: ⚑ **<alternative-K/>**
240
232
  ⚠ *ATTENTION: all alternatives rate negatively; this is the least-bad choice, not a strong winner!*
241
233
  </template>
242
234
 
235
+ - Otherwise, if <percentage/> is less than 0.01 (i.e. <distance/> is
236
+ effectively zero relative to abs(<rating-K/>)), stop the flow after
237
+ you output just the following <template/> and do not output anything
238
+ else:
239
+
240
+ <template>
241
+ <ase-tpl-bullet-signal/> **ERROR**: ✘ *MULTIPLE BEST ALTERNATIVES FOUND*,
242
+ ⚠ *Please give some hints on the criteria to ensure a single best alternative!*
243
+ </template>
244
+
243
245
  - Otherwise, if <percentage/> is less than 0.10, stop the flow after
244
246
  you output just the following <template/> and do not output anything
245
247
  else:
@@ -142,9 +142,9 @@ by querying *multiple* AIs for an *optimal consensus*.
142
142
  set <disagreement/> to `(no quorum: no foreign AIs were available)`,
143
143
  then skip the rest of this step.
144
144
 
145
- Otherwise, determine, on a Likert scale of 0..<n/>, the amount of the
146
- overall consensus <c/> of all the responses. The <n/> is the *total
147
- number of responders* (yourself plus all available foreign AIs above).
145
+ Otherwise, let <n/> be the *total number of responders* (yourself plus
146
+ all available foreign AIs above). Then determine, on a Likert scale of
147
+ 0..<n/>, the amount of the overall consensus <c/> of all the responses.
148
148
  If all responses disagree, the consensus <c/> is zero.
149
149
  If all responses agree, <c/> is <n/>.
150
150
 
@@ -93,6 +93,12 @@ explicitly requested by this procedure via outputs based on a <template/>!
93
93
  Set <words-before><words/></words-before> (remember the loaded
94
94
  word count for the strictly-smaller check in step 3).
95
95
 
96
+ <if condition="<content/> contains 'Created: <text/>'">
97
+ Set <timestamp-created><text/></timestamp-created> (extract the
98
+ original creation timestamp so it can be re-inserted unchanged
99
+ into the condensed <content/> in step 3).
100
+ </if>
101
+
96
102
  Only output the following <template/>:
97
103
 
98
104
  <template>
@@ -171,7 +171,11 @@ Set <content-dirty>true</content-dirty>.
171
171
 
172
172
  1. Determine any existing plan content:
173
173
 
174
- <if condition="<getopt-option-int-reuse-task/> is equal `true`">
174
+ <if condition="
175
+ <getopt-option-int-reuse-task/> is equal `true`
176
+ *and* a `ase_task_save(id: '<ase-task-id/>', ...)` tool call
177
+ exists earlier in the current session
178
+ ">
175
179
  Set <text/> to the `text` argument of the most recent
176
180
  `ase_task_save(id: '<ase-task-id/>', ...)` tool call,
177
181
  *without* calling `ase_task_load` again. Set <status>plan
@@ -286,7 +290,7 @@ Set <content-dirty>true</content-dirty>.
286
290
  </template>
287
291
  </if>
288
292
 
289
- 4. <if condition="<content/> does not contain '# TASK' AND <instruction/> is empty">
293
+ 4. <if condition="no line of <content/> matches the case-insensitive regex `^\s*#+\s*TASK\b` AND <instruction/> is empty">
290
294
  Set <instruction><content/></instruction> (set instruction to content).
291
295
  Set <content></content> (set content to empty).
292
296
  Set <content-dirty>true</content-dirty>.
@@ -80,7 +80,11 @@ explicitly requested by this procedure via outputs based on a <template/>!
80
80
 
81
81
  1. Determine the current task plan content:
82
82
 
83
- <if condition="<getopt-option-int-reuse-task/> is equal `true`">
83
+ <if condition="
84
+ <getopt-option-int-reuse-task/> is equal `true`
85
+ *and* a `ase_task_save(id: '<ase-task-id/>', ...)` tool call
86
+ exists earlier in the current session
87
+ ">
84
88
  Set <text/> to the `text` argument of the most recent
85
89
  `ase_task_save(id: '<ase-task-id/>', ...)` tool call,
86
90
  *without* calling `ase_task_load` again. Set <status>plan
@@ -105,12 +109,11 @@ explicitly requested by this procedure via outputs based on a <template/>!
105
109
  - If <text/> starts NOT with `ERROR:` and NOT with `WARNING:`:
106
110
  Set <plan><text/></plan> (set plan to text).
107
111
  Calculate the number of words <words/> of <plan/>.
112
+ Then output the following <template/>:
108
113
 
109
- Output the following <template/>:
110
-
111
- <template>
112
- ⧉ **ASE**: ◉ task: **<ase-task-id/>**, ✪ plan: **<words/>** words, ▶ status: **<status/>**
113
- </template>
114
+ <template>
115
+ ⧉ **ASE**: ◉ task: **<ase-task-id/>**, ✪ plan: **<words/>** words, ▶ status: **<status/>**
116
+ </template>
114
117
 
115
118
  2. <if condition="<plan/> is empty">
116
119
  Complain and tell the user to use the `ase-code-resolve`,
@@ -52,9 +52,9 @@ Configure Task Id
52
52
  </if>
53
53
 
54
54
  4. <if condition="<request/> is NOT empty">
55
- - Set <ase-task-id><request/></ase-task-id> and
56
- call the `ase_task_id(id: "<ase-task-id/>", session: "<ase-session-id/>")`
57
- tool from the `ase` MCP server.
55
+ - Call the `ase_task_id(id: "<request/>", session: "<ase-session-id/>")`
56
+ tool from the `ase` MCP server. Check the response as mandated
57
+ above; only on a clean response set <ase-task-id><request/></ase-task-id>.
58
58
 
59
59
  - Output:
60
60
  <template>
@@ -97,7 +97,11 @@ explicitly requested by this procedure via outputs based on a <template/>!
97
97
 
98
98
  1. Determine the current task plan content:
99
99
 
100
- <if condition="<getopt-option-int-reuse-task/> is equal `true`">
100
+ <if condition="
101
+ <getopt-option-int-reuse-task/> is equal `true`
102
+ *and* a `ase_task_save(id: '<ase-task-id/>', ...)` tool call
103
+ exists earlier in the current session
104
+ ">
101
105
  Set <text/> to the `text` argument of the most recent
102
106
  `ase_task_save(id: '<ase-task-id/>', ...)` tool call,
103
107
  *without* calling `ase_task_load` again. Set <status>plan
@@ -210,7 +214,7 @@ explicitly requested by this procedure via outputs based on a <template/>!
210
214
  skill accepts only an optional `[<id>]` argument and no
211
215
  `--next` option; remaining tokens are intentionally discarded.
212
216
  Only output the following <template/> and then call the
213
- tool `Skill(skill: "ase:ase-task-delete", args: <args/>)`
217
+ tool `Skill(skill: "ase:ase-task-delete", args: "<args/>")`
214
218
  to invoke the `ase:ase-task-delete` skill in order to
215
219
  *delete* the updated plan. Immediately stop processing the
216
220
  current skill once the `Skill` tool was used.
@@ -97,7 +97,11 @@ explicitly requested by this procedure via outputs based on a <template/>!
97
97
 
98
98
  1. Determine the current task plan content:
99
99
 
100
- <if condition="<getopt-option-int-reuse-task/> is equal `true`">
100
+ <if condition="
101
+ <getopt-option-int-reuse-task/> is equal `true`
102
+ *and* a `ase_task_save(id: '<ase-task-id/>', ...)` tool call
103
+ exists earlier in the current session
104
+ ">
101
105
  Set <text/> to the `text` argument of the most recent
102
106
  `ase_task_save(id: '<ase-task-id/>', ...)` tool call,
103
107
  *without* calling `ase_task_load` again. Set <status>plan
@@ -71,6 +71,15 @@ explicitly requested by this procedure via outputs based on a <template/>!
71
71
  </template>
72
72
  </if>
73
73
 
74
+ 6. <if condition="<old/> is equal <new/>">
75
+ Only output the following <template/> and then immediately
76
+ *STOP* processing the entire current skill:
77
+
78
+ <template>
79
+ ⧉ **ASE**: ◉ task: **<old/>**, ▶ status: **task unchanged (old and new task id are equal)**
80
+ </template>
81
+ </if>
82
+
74
83
  2. **Perform Operation**:
75
84
 
76
85
  1. Call the `ase_task_rename(old: "<old/>", new: "<new/>")` tool of the