@rse/ase 0.0.54 → 0.0.56

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.
package/dst/ase-config.js CHANGED
@@ -391,19 +391,9 @@ export class Config {
391
391
  return this.docs[this.target].doc.contents;
392
392
  const segs = this.resolveKey(key).split(".");
393
393
  for (let i = this.docs.length - 1; i >= 0; i--) {
394
- const v = this.docs[i].doc.getIn(segs);
395
- if (v !== undefined)
396
- return v;
397
- }
398
- return undefined;
399
- }
400
- /* retrieve the effective value together with the scope it came from */
401
- getWithOrigin(key) {
402
- const segs = this.resolveKey(key).split(".");
403
- for (let i = this.docs.length - 1; i >= 0; i--) {
404
- const v = this.docs[i].doc.getIn(segs);
405
- if (v !== undefined)
406
- return { value: v, scope: this.docs[i].scope };
394
+ const node = this.docs[i].doc.getIn(segs);
395
+ if (node !== undefined)
396
+ return node;
407
397
  }
408
398
  return undefined;
409
399
  }
@@ -429,9 +419,9 @@ export class Config {
429
419
  for (const k of keys) {
430
420
  const segs = k.split(".");
431
421
  for (let i = this.docs.length - 1; i >= 0; i--) {
432
- const v = this.docs[i].doc.getIn(segs);
433
- if (v !== undefined) {
434
- result.push({ key: k, value: v, scope: this.docs[i].scope });
422
+ const node = this.docs[i].doc.getIn(segs);
423
+ if (node !== undefined) {
424
+ result.push({ key: k, value: node, scope: this.docs[i].scope });
435
425
  break;
436
426
  }
437
427
  }
@@ -556,8 +546,8 @@ export default class ConfigCommand {
556
546
  style: { head: ["blue"] }
557
547
  });
558
548
  for (const e of cfg.entries()) {
559
- const v = isScalar(e.value) ? e.value.value : e.value;
560
- table.push([e.key, String(v), Config.scopeLabel(e.scope)]);
549
+ const val = isScalar(e.value) ? e.value.value : e.value;
550
+ table.push([e.key, String(val), Config.scopeLabel(e.scope)]);
561
551
  }
562
552
  process.stdout.write(`${table.toString()}\n`);
563
553
  });
@@ -126,7 +126,7 @@ export class Diagram {
126
126
  let mode = "none";
127
127
  /* attempt 1: query environment variable (explicitly) */
128
128
  if (process.env.ASE_TERM_COLORS !== undefined)
129
- if (process.env.ASE_TERM_COLORS.match(/^(?:none|ansi16|ansi256)$/) !== null)
129
+ if (/^(?:none|ansi16|ansi256)$/.test(process.env.ASE_TERM_COLORS))
130
130
  mode = process.env.ASE_TERM_COLORS;
131
131
  /* attempt 2: query stdout */
132
132
  if (mode === "none" && process.stdout.isTTY) {
package/dst/ase-hook.js CHANGED
@@ -140,9 +140,6 @@ export default class HookCommand {
140
140
  /* establish config context (session-scoped only if a valid sessionId is present) */
141
141
  const hasSession = this.isValidSessionId(sessionId);
142
142
  const cfg = new Config("config", configSchema, this.log, hasSession ? parseScope(`session:${sessionId}`) : parseScope(undefined));
143
- cfg.lock(() => {
144
- cfg.read();
145
- });
146
143
  /* determine task id (only persist when scoped to a real session) */
147
144
  const taskId = process.env.ASE_TASK_ID ?? "default";
148
145
  if (hasSession)
@@ -151,6 +148,10 @@ export default class HookCommand {
151
148
  cfg.set("agent.task", taskId);
152
149
  cfg.write();
153
150
  });
151
+ else
152
+ cfg.lock(() => {
153
+ cfg.read();
154
+ });
154
155
  /* initialize agent activity status */
155
156
  this.writeAgentStatus("ready");
156
157
  /* determine project id */
package/dst/ase-setup.js CHANGED
@@ -397,30 +397,23 @@ export default class SetupCommand {
397
397
  server: "chat-openai-chatgpt",
398
398
  skills: ["ase-meta-chat", "ase-meta-quorum"],
399
399
  handler: async (spec, tool, action, envKey, envVal) => {
400
- if (action === "activate") {
401
- if (envKey === "OPENROUTER")
402
- await this.mcpAdd(tool, spec.server, { OPENAI_KEY: envVal }, {
403
- type: "stdio", command: [
404
- "npx", "-y", "mcp-to-openai",
405
- "--service", spec.name,
406
- "--mcp-tool", "query",
400
+ if (action === "activate")
401
+ await this.mcpAdd(tool, spec.server, { OPENAI_KEY: envVal }, {
402
+ type: "stdio", command: [
403
+ "npx", "-y", "mcp-to-openai",
404
+ "--service", spec.name,
405
+ "--mcp-tool", "query",
406
+ ...(envKey === "OPENROUTER" ? [
407
407
  "--openai-url", "https://openrouter.ai/api/v1",
408
408
  "--openai-api", "completion",
409
409
  "--openai-model", "openai/gpt-5.5"
410
- ]
411
- });
412
- else
413
- await this.mcpAdd(tool, spec.server, { OPENAI_KEY: envVal }, {
414
- type: "stdio", command: [
415
- "npx", "-y", "mcp-to-openai",
416
- "--service", spec.name,
417
- "--mcp-tool", "query",
410
+ ] : [
418
411
  "--openai-url", "https://api.openai.com/v1",
419
412
  "--openai-api", "responses",
420
413
  "--openai-model", "gpt-5.5"
421
- ]
422
- });
423
- }
414
+ ])
415
+ ]
416
+ });
424
417
  else
425
418
  await this.mcpRemove(tool, spec.server);
426
419
  }
@@ -433,30 +426,23 @@ export default class SetupCommand {
433
426
  server: "chat-google-gemini",
434
427
  skills: ["ase-meta-chat", "ase-meta-quorum"],
435
428
  handler: async (spec, tool, action, envKey, envVal) => {
436
- if (action === "activate") {
437
- if (envKey === "OPENROUTER")
438
- await this.mcpAdd(tool, spec.server, { OPENAI_KEY: envVal }, {
439
- type: "stdio", command: [
440
- "npx", "-y", "mcp-to-openai",
441
- "--service", spec.name,
442
- "--mcp-tool", "query",
429
+ if (action === "activate")
430
+ await this.mcpAdd(tool, spec.server, { OPENAI_KEY: envVal }, {
431
+ type: "stdio", command: [
432
+ "npx", "-y", "mcp-to-openai",
433
+ "--service", spec.name,
434
+ "--mcp-tool", "query",
435
+ ...(envKey === "OPENROUTER" ? [
443
436
  "--openai-url", "https://openrouter.ai/api/v1",
444
437
  "--openai-api", "completion",
445
438
  "--openai-model", "google/gemini-3.5-flash"
446
- ]
447
- });
448
- else
449
- await this.mcpAdd(tool, spec.server, { OPENAI_KEY: envVal }, {
450
- type: "stdio", command: [
451
- "npx", "-y", "mcp-to-openai",
452
- "--service", spec.name,
453
- "--mcp-tool", "query",
439
+ ] : [
454
440
  "--openai-url", "https://generativelanguage.googleapis.com/v1beta/openai/",
455
441
  "--openai-api", "completion",
456
442
  "--openai-model", "gemini-3.5-flash"
457
- ]
458
- });
459
- }
443
+ ])
444
+ ]
445
+ });
460
446
  else
461
447
  await this.mcpRemove(tool, spec.server);
462
448
  }
@@ -469,31 +455,23 @@ export default class SetupCommand {
469
455
  server: "chat-deepseek",
470
456
  skills: ["ase-meta-chat", "ase-meta-quorum"],
471
457
  handler: async (spec, tool, action, envKey, envVal) => {
472
- if (action === "activate") {
473
- if (envKey === "OPENROUTER")
474
- await this.mcpAdd(tool, spec.server, { OPENAI_KEY: envVal }, {
475
- type: "stdio",
476
- command: [
477
- "npx", "-y", "mcp-to-openai",
478
- "--service", spec.name,
479
- "--mcp-tool", "query",
458
+ if (action === "activate")
459
+ await this.mcpAdd(tool, spec.server, { OPENAI_KEY: envVal }, {
460
+ type: "stdio", command: [
461
+ "npx", "-y", "mcp-to-openai",
462
+ "--service", spec.name,
463
+ "--mcp-tool", "query",
464
+ ...(envKey === "OPENROUTER" ? [
480
465
  "--openai-url", "https://openrouter.ai/api/v1",
481
466
  "--openai-api", "completion",
482
467
  "--openai-model", "deepseek/deepseek-v4-flash"
483
- ]
484
- });
485
- else
486
- await this.mcpAdd(tool, spec.server, { OPENAI_KEY: envVal }, {
487
- type: "stdio", command: [
488
- "npx", "-y", "mcp-to-openai",
489
- "--service", spec.name,
490
- "--mcp-tool", "query",
468
+ ] : [
491
469
  "--openai-url", "https://api.deepseek.com/v1",
492
470
  "--openai-api", "completion",
493
471
  "--openai-model", "deepseek-v4-flash"
494
- ]
495
- });
496
- }
472
+ ])
473
+ ]
474
+ });
497
475
  else
498
476
  await this.mcpRemove(tool, spec.server);
499
477
  }
@@ -506,30 +484,23 @@ export default class SetupCommand {
506
484
  server: "chat-xai-grok",
507
485
  skills: ["ase-meta-chat", "ase-meta-quorum"],
508
486
  handler: async (spec, tool, action, envKey, envVal) => {
509
- if (action === "activate") {
510
- if (envKey === "OPENROUTER")
511
- await this.mcpAdd(tool, spec.server, { OPENAI_KEY: envVal }, {
512
- type: "stdio", command: [
513
- "npx", "-y", "mcp-to-openai",
514
- "--service", spec.name,
515
- "--mcp-tool", "query",
487
+ if (action === "activate")
488
+ await this.mcpAdd(tool, spec.server, { OPENAI_KEY: envVal }, {
489
+ type: "stdio", command: [
490
+ "npx", "-y", "mcp-to-openai",
491
+ "--service", spec.name,
492
+ "--mcp-tool", "query",
493
+ ...(envKey === "OPENROUTER" ? [
516
494
  "--openai-url", "https://openrouter.ai/api/v1",
517
495
  "--openai-api", "completion",
518
496
  "--openai-model", "x-ai/grok-4.3"
519
- ]
520
- });
521
- else
522
- await this.mcpAdd(tool, spec.server, { OPENAI_KEY: envVal }, {
523
- type: "stdio", command: [
524
- "npx", "-y", "mcp-to-openai",
525
- "--service", spec.name,
526
- "--mcp-tool", "query",
497
+ ] : [
527
498
  "--openai-url", "https://api.x.ai/v1",
528
499
  "--openai-api", "completion",
529
500
  "--openai-model", "grok-4.3"
530
- ]
531
- });
532
- }
501
+ ])
502
+ ]
503
+ });
533
504
  else
534
505
  await this.mcpRemove(tool, spec.server);
535
506
  }
@@ -542,30 +513,23 @@ export default class SetupCommand {
542
513
  server: "chat-alibaba-qwen",
543
514
  skills: ["ase-meta-chat", "ase-meta-quorum"],
544
515
  handler: async (spec, tool, action, envKey, envVal) => {
545
- if (action === "activate") {
546
- if (envKey === "OPENROUTER")
547
- await this.mcpAdd(tool, spec.server, { OPENAI_KEY: envVal }, {
548
- type: "stdio", command: [
549
- "npx", "-y", "mcp-to-openai",
550
- "--service", spec.name,
551
- "--mcp-tool", "query",
516
+ if (action === "activate")
517
+ await this.mcpAdd(tool, spec.server, { OPENAI_KEY: envVal }, {
518
+ type: "stdio", command: [
519
+ "npx", "-y", "mcp-to-openai",
520
+ "--service", spec.name,
521
+ "--mcp-tool", "query",
522
+ ...(envKey === "OPENROUTER" ? [
552
523
  "--openai-url", "https://openrouter.ai/api/v1",
553
524
  "--openai-api", "completion",
554
525
  "--openai-model", "qwen/qwen3.7-max"
555
- ]
556
- });
557
- else
558
- await this.mcpAdd(tool, spec.server, { OPENAI_KEY: envVal }, {
559
- type: "stdio", command: [
560
- "npx", "-y", "mcp-to-openai",
561
- "--service", spec.name,
562
- "--mcp-tool", "query",
526
+ ] : [
563
527
  "--openai-url", "https://dashscope.aliyuncs.com/compatible-mode/v1",
564
528
  "--openai-api", "completion",
565
529
  "--openai-model", "qwen3.7-max"
566
- ]
567
- });
568
- }
530
+ ])
531
+ ]
532
+ });
569
533
  else
570
534
  await this.mcpRemove(tool, spec.server);
571
535
  }
@@ -578,30 +542,23 @@ export default class SetupCommand {
578
542
  server: "chat-zai-glm",
579
543
  skills: ["ase-meta-chat", "ase-meta-quorum"],
580
544
  handler: async (spec, tool, action, envKey, envVal) => {
581
- if (action === "activate") {
582
- if (envKey === "OPENROUTER")
583
- await this.mcpAdd(tool, spec.server, { OPENAI_KEY: envVal }, {
584
- type: "stdio", command: [
585
- "npx", "-y", "mcp-to-openai",
586
- "--service", spec.name,
587
- "--mcp-tool", "query",
545
+ if (action === "activate")
546
+ await this.mcpAdd(tool, spec.server, { OPENAI_KEY: envVal }, {
547
+ type: "stdio", command: [
548
+ "npx", "-y", "mcp-to-openai",
549
+ "--service", spec.name,
550
+ "--mcp-tool", "query",
551
+ ...(envKey === "OPENROUTER" ? [
588
552
  "--openai-url", "https://openrouter.ai/api/v1",
589
553
  "--openai-api", "completion",
590
554
  "--openai-model", "z-ai/glm-5.1"
591
- ]
592
- });
593
- else
594
- await this.mcpAdd(tool, spec.server, { OPENAI_KEY: envVal }, {
595
- type: "stdio", command: [
596
- "npx", "-y", "mcp-to-openai",
597
- "--service", spec.name,
598
- "--mcp-tool", "query",
555
+ ] : [
599
556
  "--openai-url", "https://api.z.ai/api/paas/v4/",
600
557
  "--openai-api", "completion",
601
558
  "--openai-model", "glm-5.1"
602
- ]
603
- });
604
- }
559
+ ])
560
+ ]
561
+ });
605
562
  else
606
563
  await this.mcpRemove(tool, spec.server);
607
564
  }
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.0.54",
9
+ "version": "0.0.56",
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.0.54",
3
+ "version": "0.0.56",
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.0.54",
3
+ "version": "0.0.56",
4
4
  "description": "Agentic Software Engineering (ASE)",
5
5
  "keywords": [ "agentic", "software", "engineering" ],
6
6
  "homepage": "https://ase.tools",
@@ -4,8 +4,8 @@ description: Query the Web
4
4
  model: sonnet
5
5
  effort: low
6
6
  tools:
7
- - "mcp__perplexity__perplexity_search"
8
- - "mcp__brave__brave_web_search"
7
+ - "mcp__search-perplexity__perplexity_search"
8
+ - "mcp__search-brave__brave_web_search"
9
9
  - "mcp__search-exa__web_search_exa"
10
10
  - "WebSearch"
11
11
  ---
@@ -16,12 +16,12 @@ Control Flow Constructs
16
16
  - *IMPORTANT*: You *MUST* honor the following control flow construct:
17
17
  <expand name="<define-name/>" [arg1="<expand-arg1/>" [arg2="<expand-arg2/>" [...]]]><expand-content/></expand>:
18
18
 
19
- This specifies the *expansion* of previous <define/>.
20
- This construct is expanded into the <define-body/> of <define/>
21
- with `<args/>` substituted with `<expand-arg1/> <expand-arg2/>
22
- [...]`, `<arg1/>` substituted with <expand-arg1/>, and `<content/>`
23
- substituted with <expand-content/>.
24
- Do not output anything else.
19
+ This specifies the *expansion* of previous <define/>. This
20
+ construct is expanded to the <define-body/> of <define/> with
21
+ `<args/>` substituted with `<expand-arg1/> <expand-arg2/> [...]`,
22
+ `<arg1/>` substituted with <expand-arg1/>, `<arg2/>` substituted
23
+ with <expand-arg2/>, etc, and `<content/>` substituted with
24
+ <expand-content/>. Do not output anything else.
25
25
 
26
26
  - *IMPORTANT*: You *MUST* honor the following control flow construct:
27
27
  <flow><flow-body/></flow>:
@@ -38,7 +38,7 @@ Let the *user interactively choose* an answer.
38
38
 
39
39
  Start with <n>0</n> (set entry count to zero).
40
40
  <for items="2 3 4 5">
41
- Take from <config/> the line number <item/>.
41
+ Take from <spec/> the line number <item/>.
42
42
  If this line does not exist, <break/>.
43
43
  If this line exists, parse it according to the format `<label/>: <description/>`.
44
44
  If <config/> is not empty, set <config><config/>, </config> (append comma).
@@ -93,7 +93,7 @@ Let the *user interactively choose* an answer.
93
93
 
94
94
  Start with <n>0</n> (set entry count to zero).
95
95
  <for items="2 3 4 5">
96
- Take from <config/> the line number <item/>.
96
+ Take from <spec/> the line number <item/>.
97
97
  If this line does not exist, <break/>.
98
98
  If this line exists, parse it according to the format `<label/>: <description/>`.
99
99
  If <config/> is not empty, set <config><config/>, </config> (append comma).
@@ -20,13 +20,14 @@ set placeholders into the context as a side-effect.
20
20
  then just silently *SKIP* the following steps 3-7!
21
21
 
22
22
  3. **MCP Call**:
23
- Call the `ase_getopt(name: <getopt-skill/>, spec: <getopt-spec/>, args:
24
- <getopt-args/>)` tool of the `ase` MCP server and set <text/> to the
25
- `text` output field of this tool call. The `spec` syntax for each
26
- option token is `--<long>[|-<short>][=<default>|=(<c1>|<c2>|...)]`,
27
- where `=<default>` declares a value-taking option with a default,
28
- and `=(<c1>|<c2>|...)` declares a value-taking option restricted to
29
- the listed fixed choices (the first choice acts as the default).
23
+ Call the `ase_getopt(name: "<getopt-skill/>", spec:
24
+ "<getopt-spec/>", args: "<getopt-args/>")` tool of the `ase`
25
+ MCP server and set <text/> to the `text` output field of
26
+ this tool call. The `spec` syntax for each option token is
27
+ `--<long>[|-<short>][=<default>|=(<c1>|<c2>|...)]`, where
28
+ `=<default>` declares a value-taking option with a default, and
29
+ `=(<c1>|<c2>|...)` declares a value-taking option restricted to the
30
+ listed fixed choices (the first choice acts as the default).
30
31
 
31
32
  4. **Short-Circuit for Error**:
32
33
  If <text/> starts with `ERROR:`:
@@ -47,14 +48,15 @@ set placeholders into the context as a side-effect.
47
48
  {
48
49
  "opts": { "<long1/>": <value1/>, "<long2/>": <value2/>, ... },
49
50
  "argv": [ "<arg1/>", "<arg2/>", ... ],
50
- "args": "..."
51
+ "args": "...",
52
+ "info": "..."
51
53
  }
52
54
  ```
53
55
 
54
56
  6. **Materializing into Context**:
55
- For each *key* `<long/>` in <getopt-result/>`.opts`:
56
- Set <getopt-option-<long/>/> to the corresponding value from
57
- `<getopt-result/>.opts[<long/>]`.
57
+ For each *key* `<longN/>` in <getopt-result/>`.opts`:
58
+ Set <getopt-option-<longN/>/> to the corresponding value
59
+ `<getopt-result/>.opts[<longN/>]`.
58
60
  Set <getopt-arguments/> to the value of `<getopt-result/>.args`.
59
61
  Set <getopt-info/> to `<getopt-result/>.info`.
60
62
 
@@ -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.0.54",
9
+ "version": "0.0.56",
10
10
  "license": "GPL-3.0-only",
11
11
  "author": {
12
12
  "name": "Dr. Ralf S. Engelschall",
@@ -131,12 +131,13 @@ for the technology stack to *provide* the *needed functionality*
131
131
  into the already existing result set, but deduplicate
132
132
  entries by Maven coordinate.
133
133
 
134
- - Call the `ase_component_info(stack: <stack/>, components:
135
- [ <package-1/>, ..., <package-N/> ])` tool of the `ase` MCP
134
+ - Call the `ase_component_info(stack: "<stack/>", components:
135
+ [ "<package-1/>", ..., "<package-N/>" ])` tool of the `ase` MCP
136
136
  server *once* for the entire set of discovered packages.
137
137
  The tool dispatches internally on <stack/> and fetches all
138
138
  metadata in maximum parallel and returns an array of objects `{
139
- name, version, time, repository, stars, downloads }`. For each
139
+ name, version, created, updated, repository, stars, downloads,
140
+ rank }`. For each
140
141
  component <component-K/> (K=1-N) read from its corresponding
141
142
  entry: <version-K/> from `version`, <updated-K/> from `updated`,
142
143
  <created-K/> from `created`, <repository-K/> from `repository`,
@@ -61,7 +61,7 @@ permitted way to persist artifacts is via `ase_task_save(...)`.
61
61
  ">
62
62
  Set <ase-task-id><feature/></ase-task-id> (set task id to feature)
63
63
  and <feature></feature> (set feature empty), call the
64
- `ase_task_id(id: <ase-task-id/>, session: <ase-session-id/>)` tool
64
+ `ase_task_id(id: "<ase-task-id/>", session: "<ase-session-id/>")` tool
65
65
  from the `ase` MCP server to switch the task, and then only
66
66
  output the following <template/>:
67
67
 
@@ -71,10 +71,10 @@ permitted way to persist artifacts is via `ase_task_save(...)`.
71
71
  </if>
72
72
 
73
73
  2. If <feature/> has the format `<id/>: <text/>` where <id/> matches
74
- the regexp `^[a-zA-Z][a-zA-Z0-9_-]+$`, then set
74
+ the regexp `^[a-zA-Z][a-zA-Z0-9_-]*$`, then set
75
75
  <feature><text/></feature> and <ase-task-id><id/></ase-task-id>
76
- and call the `ase_task_id(id: <ase-task-id/>, session:
77
- <ase-session-id/>)` tool from the `ase` MCP server to
76
+ and call the `ase_task_id(id: "<ase-task-id/>", session:
77
+ "<ase-session-id/>")` tool from the `ase` MCP server to
78
78
  implicitly switch the task. Do not output anything.
79
79
 
80
80
  3. If <feature/> is empty,
@@ -91,8 +91,8 @@ permitted way to persist artifacts is via `ase_task_save(...)`.
91
91
  ">
92
92
  Set <ase-task-id/> to a unique task id, derived from <feature/>,
93
93
  which consists of two lower-case words concatenated with a
94
- `-` character. Then call the `ase_task_id(id: <ase-task-id/>,
95
- session: <ase-session-id/>)` tool from the `ase` MCP server to
94
+ `-` character. Then call the `ase_task_id(id: "<ase-task-id/>",
95
+ session: "<ase-session-id/>")` tool from the `ase` MCP server to
96
96
  implicitly switch the task. Do not output anything.
97
97
  </if>
98
98
 
@@ -279,7 +279,7 @@ permitted way to persist artifacts is via `ase_task_save(...)`.
279
279
  words <words/> of <content/>.
280
280
 
281
281
  3. You *MUST* *save* the resulting plan content with the
282
- `ase_task_save(id: <ase-task-id/>, text: <content/>)`.
282
+ `ase_task_save(id: "<ase-task-id/>", text: "<content/>")`.
283
283
 
284
284
  4. Output a hint with the following <template/>:
285
285
 
@@ -61,7 +61,7 @@ permitted way to persist artifacts is via `ase_task_save(...)`.
61
61
  ">
62
62
  Set <ase-task-id><request/></ase-task-id> (set task id to request)
63
63
  and <request></request> (set request empty), call the
64
- `ase_task_id(id: <ase-task-id/>, session: <ase-session-id/>)` tool
64
+ `ase_task_id(id: "<ase-task-id/>", session: "<ase-session-id/>")` tool
65
65
  from the `ase` MCP server to switch the task, and then only
66
66
  output the following <template/>:
67
67
 
@@ -73,8 +73,8 @@ permitted way to persist artifacts is via `ase_task_save(...)`.
73
73
  2. If <request/> has the format `<id/>: <text/>` where <id/> matches
74
74
  the regexp `^[a-zA-Z][a-zA-Z0-9_-]*$`, then set
75
75
  <request><text/></request> and <ase-task-id><id/></ase-task-id>
76
- and call the `ase_task_id(id: <ase-task-id/>, session:
77
- <ase-session-id/>)` tool from the `ase` MCP server to
76
+ and call the `ase_task_id(id: "<ase-task-id/>", session:
77
+ "<ase-session-id/>")` tool from the `ase` MCP server to
78
78
  implicitly switch the task. Do not output anything.
79
79
 
80
80
  3. If <request/> is empty,
@@ -91,8 +91,8 @@ permitted way to persist artifacts is via `ase_task_save(...)`.
91
91
  ">
92
92
  Set <ase-task-id/> to a unique task id, derived from <request/>,
93
93
  which consists of two lower-case words concatenated with a
94
- `-` character. Then call the `ase_task_id(id: <ase-task-id/>,
95
- session: <ase-session-id/>)` tool from the `ase` MCP server to
94
+ `-` character. Then call the `ase_task_id(id: "<ase-task-id/>",
95
+ session: "<ase-session-id/>")` tool from the `ase` MCP server to
96
96
  implicitly switch the task. Do not output anything.
97
97
  </if>
98
98
 
@@ -270,7 +270,7 @@ permitted way to persist artifacts is via `ase_task_save(...)`.
270
270
  words <words/> of <content/>.
271
271
 
272
272
  3. You then *MUST* *save* the resulting plan content with the
273
- `ase_task_save(id: <ase-task-id/>, text: <content/>)`.
273
+ `ase_task_save(id: "<ase-task-id/>", text: "<content/>")`.
274
274
 
275
275
  4. Output a hint with the following <template/>:
276
276
 
@@ -60,7 +60,7 @@ permitted way to persist artifacts is via `ase_task_save(...)`.
60
60
  identifier like `P1`, `P2`, `T1`, `T2`, ...),
61
61
  set <problem-id><problem/></problem-id> and
62
62
  <ase-task-id><problem/></ase-task-id>, call the `ase_task_id(id:
63
- <ase-task-id/>, session: <ase-session-id/>)` tool from the
63
+ "<ase-task-id/>", session: "<ase-session-id/>")` tool from the
64
64
  `ase` MCP server to implicitly switch the task, and then
65
65
  call the `ase_kv_get(key: "ase-issue-<problem-id/>")` tool of
66
66
  the `ase` MCP server to retrieve the previously persisted
@@ -73,7 +73,7 @@ permitted way to persist artifacts is via `ase_task_save(...)`.
73
73
  ">
74
74
  Set <ase-task-id><problem/></ase-task-id> (set task id to problem)
75
75
  and <problem></problem> (set problem empty), call the
76
- `ase_task_id(id: <ase-task-id/>, session: <ase-session-id/>)` tool
76
+ `ase_task_id(id: "<ase-task-id/>", session: "<ase-session-id/>")` tool
77
77
  from the `ase` MCP server to switch the task, and then only
78
78
  output the following <template/>:
79
79
 
@@ -83,10 +83,10 @@ permitted way to persist artifacts is via `ase_task_save(...)`.
83
83
  </if>
84
84
 
85
85
  3. If <problem/> has the format `<id/>: <text/>` where <id/> matches
86
- the regexp `^[a-zA-Z][a-zA-Z0-9_-]+$`, then set
86
+ the regexp `^[a-zA-Z][a-zA-Z0-9_-]*$`, then set
87
87
  <problem><text/></problem> and <ase-task-id><id/></ase-task-id>
88
- and call the `ase_task_id(id: <ase-task-id/>, session:
89
- <ase-session-id/>)` tool from the `ase` MCP server to
88
+ and call the `ase_task_id(id: "<ase-task-id/>", session:
89
+ "<ase-session-id/>")` tool from the `ase` MCP server to
90
90
  implicitly switch the task. Do not output anything.
91
91
 
92
92
  4. If <problem/> is empty,
@@ -103,8 +103,8 @@ permitted way to persist artifacts is via `ase_task_save(...)`.
103
103
  ">
104
104
  Set <ase-task-id/> to a unique task id, derived from <problem/>,
105
105
  which consists of two lower-case words concatenated with a
106
- `-` character. Then call the `ase_task_id(id: <ase-task-id/>,
107
- session: <ase-session-id/>)` tool from the `ase` MCP server to
106
+ `-` character. Then call the `ase_task_id(id: "<ase-task-id/>",
107
+ session: "<ase-session-id/>")` tool from the `ase` MCP server to
108
108
  implicitly switch the task. Do not output anything.
109
109
  </if>
110
110
 
@@ -318,7 +318,7 @@ permitted way to persist artifacts is via `ase_task_save(...)`.
318
318
  words <words/> of <content/>.
319
319
 
320
320
  3. You then *MUST* *save* the resulting plan content with the
321
- `ase_task_save(id: <ase-task-id/>, text: <content/>)`.
321
+ `ase_task_save(id: "<ase-task-id/>", text: "<content/>")`.
322
322
 
323
323
  4. If <problem-id/> is set (i.e. the <problem/> was retrieved from
324
324
  `ase_kv_get` in STEP 1.3 via key `ase-issue-<problem-id/>`),
@@ -86,8 +86,8 @@ Processing
86
86
  </template>
87
87
 
88
88
  To update to entries of the most recent *ChangeLog* section, consult
89
- the Git *commits* plus the currenly already staged changes in the Git
90
- *index*, but *ignore* the Git *stash* and and still unstaged changes.
89
+ the Git *commits* plus the currently already staged changes in the Git
90
+ *index*, but *ignore* the Git *stash* and still unstaged changes.
91
91
 
92
92
  For finding the corresponding Git *commits*, use the `N.M.K` from the
93
93
  *second* level-2 header in the *ChangeLog* file as the corresponding
@@ -154,8 +154,8 @@ multi-*criteria* decision matrix.
154
154
 
155
155
  - Then, calculate the ratings <rating-K/> (K=1-N) for all
156
156
  alternatives in a single call by invoking the `ase_decision_matrix(matrix:
157
- [ [ <weight-1/>, <eval-1-1/>, ..., <eval-1-N/> ], ..., [ <weight-M/>,
158
- <eval-M-1/>, ..., <eval-M-N/> ] ])` tool of the `ase` MCP server.
157
+ [ [ <weight-1/>, <eval-1-1/>, ..., <eval-N-1/> ], ..., [ <weight-M/>,
158
+ <eval-1-M/>, ..., <eval-N-M/> ] ])` tool of the `ase` MCP server.
159
159
  The tool returns an array of N numerical values, where the K-th
160
160
  entry is the product-sum of all weights <weight-L/> (L=1-M) and
161
161
  the evaluation <eval-K-L/> (L=1-M) for alternative <alternative-K/>.
@@ -173,9 +173,9 @@ multi-*criteria* decision matrix.
173
173
 
174
174
  | ⦿ *Criteria* | ⚖ *Weight* | ⚑ **<alternative-1/>** | [...alternatives 2-(N-1)...] | ⚑ **<alternative-N/>** |
175
175
  | :------------ | ----------: | ---------------------: | ---------------------------: | ---------------------: |
176
- | <criteria-1/> | <weight-1/> | <eval-1-1/> | [...evals 1-2..1-(N-1)...] | <eval-1-N/> |
176
+ | <criteria-1/> | <weight-1/> | <eval-1-1/> | [...evals 2-1..(N-1)-1...] | <eval-N-1/> |
177
177
  [...criteria L=2-(M-1) for M>2...]
178
- | <criteria-M/> | <weight-M/> | <eval-M-1/> | [...evals M-2..M-(N-1)...] | <eval-M-N/> |
178
+ | <criteria-M/> | <weight-M/> | <eval-1-M/> | [...evals 2-M..(N-1)-M...] | <eval-N-M/> |
179
179
  | **RATING** | | **<rating-1/>** | [...ratings 2-(N-1)...] | **<rating-N/>** |
180
180
  </template>
181
181
  </step>
@@ -24,7 +24,7 @@ Persona Configuration
24
24
  Do not output anything.
25
25
 
26
26
  2. <if condition="<request/> is empty">
27
- 1. Call the `ase_persona(session: <ase-session-id/>)`
27
+ 1. Call the `ase_persona(session: "<ase-session-id/>")`
28
28
  tool from the `ase` MCP server and set
29
29
  <ase-persona-style/> to its `text` output.
30
30
  Do not output anything.
@@ -46,8 +46,8 @@ Persona Configuration
46
46
  </template>
47
47
 
48
48
  2. Set <ase-persona-style><request/></ase-persona-style> and
49
- call the `ase_persona(style: <ase-persona-style/>, session:
50
- <ase-session-id/>)` tool from the `ase` MCP server. Do not
49
+ call the `ase_persona(style: "<ase-persona-style/>", session:
50
+ "<ase-session-id/>")` tool from the `ase` MCP server. Do not
51
51
  output anything.
52
52
 
53
53
  3. Output the following <template/>:
@@ -150,6 +150,14 @@ by querying *multiple* AIs for an *optimal consensus*.
150
150
  &#x25CB; **xAI Grok**:
151
151
  - [...]
152
152
  - [...]
153
+
154
+ &#x25CB; **Z.AI GLM**:
155
+ - [...]
156
+ - [...]
157
+
158
+ &#x25CB; **Alibaba Qwen**:
159
+ - [...]
160
+ - [...]
153
161
  </template>
154
162
 
155
163
  In this output, remove the sections of those AIs which were not available.
@@ -36,7 +36,8 @@ explicitly requested by this procedure via outputs based on a <template/>!
36
36
 
37
37
  1. **Determine Task:**
38
38
 
39
- 1. Set <id>$ARGUMENTS</id> initially.
39
+ 1. Set <id>$ARGUMENTS</id> initially, with any leading and trailing
40
+ whitespace stripped.
40
41
  Inherit the always existing <ase-task-id/> from the current context.
41
42
  Do not output anything.
42
43
 
@@ -45,9 +46,18 @@ explicitly requested by this procedure via outputs based on a <template/>!
45
46
  Do not output anything.
46
47
  </if>
47
48
 
49
+ 3. <if condition="<id/> does NOT match the regexp `^[a-zA-Z][a-zA-Z0-9_-]*$`">
50
+ Only output the following <template/> and then immediately
51
+ *STOP* processing the entire current skill:
52
+
53
+ <template>
54
+ ⧉ **ASE**: ☻ skill: **ase-task-delete**, ▶ ERROR: expected single `[<id>]` argument
55
+ </template>
56
+ </if>
57
+
48
58
  2. **Perform Operation**:
49
59
 
50
- 1. Call the `ase_task_delete(id: <id/>)` tool of the `ase` MCP
60
+ 1. Call the `ase_task_delete(id: "<id/>")` tool of the `ase` MCP
51
61
  server to delete the task plan content and set <text/> to the
52
62
  `text` output field of this `ase_task_delete` tool call. Do not
53
63
  output anything related to this MCP tool call.
@@ -59,7 +69,7 @@ explicitly requested by this procedure via outputs based on a <template/>!
59
69
  ⧉ **ASE**: ◉ task: **<id/>**, ▶ status: **<text/>**
60
70
  </template>
61
71
 
62
- - If <text/> starts NOT with `ERROR:`:
72
+ - If <text/> starts NOT with `ERROR:` and NOT with `WARNING:`:
63
73
  Only output the following <template/>:
64
74
 
65
75
  <template>
@@ -68,7 +78,7 @@ explicitly requested by this procedure via outputs based on a <template/>!
68
78
 
69
79
  2. <if condition="<id/> is equal <ase-task-id/> AND <ase-task-id/> is not equal 'default'">
70
80
  Set <ase-task-id>default</ase-task-id>. Call the `ase_task_id(id:
71
- <ase-task-id/>, session: <ase-session-id/>)` tool from the `ase`
81
+ "<ase-task-id/>", session: "<ase-session-id/>")` tool from the `ase`
72
82
  MCP server to switch the task to the default task. Only output
73
83
  the following <template/>:
74
84
 
@@ -56,6 +56,7 @@ explicitly requested by this procedure via outputs based on a <template/>!
56
56
 
57
57
  1. Set <instruction><getopt-arguments/></instruction> initially.
58
58
  Inherit the always existing <ase-task-id/> from the current context.
59
+ Inherit the always existing <ase-session-id/> from the current context.
59
60
  Do not output anything.
60
61
 
61
62
  2. React on task and/or instruction:
@@ -65,8 +66,8 @@ explicitly requested by this procedure via outputs based on a <template/>!
65
66
  ">
66
67
  Set <ase-task-id><instruction/></ase-task-id> (set task
67
68
  id to instruction) and <instruction></instruction> (set
68
- instruction empty), call the `ase_task_id(id: <ase-task-id/>,
69
- session: <ase-session-id/>)` tool from the `ase` MCP
69
+ instruction empty), call the `ase_task_id(id: "<ase-task-id/>",
70
+ session: "<ase-session-id/>")` tool from the `ase` MCP
70
71
  server to switch the task, and then only output the
71
72
  following <template/>:
72
73
 
@@ -82,8 +83,8 @@ explicitly requested by this procedure via outputs based on a <template/>!
82
83
  ">
83
84
  Set <instruction></instruction> (set instruction to empty)
84
85
  and <ase-task-id><id/></ase-task-id> (set task id to
85
- id) and call the `ase_task_id(id: <ase-task-id/>, session:
86
- <ase-session-id/>)` tool from the `ase` MCP server to
86
+ id) and call the `ase_task_id(id: "<ase-task-id/>", session:
87
+ "<ase-session-id/>")` tool from the `ase` MCP server to
87
88
  switch the task, and then only output the following
88
89
  <template/>:
89
90
 
@@ -99,8 +100,8 @@ explicitly requested by this procedure via outputs based on a <template/>!
99
100
  ">
100
101
  Set <instruction><text/></instruction> (set instruction to
101
102
  text) and <ase-task-id><id/></ase-task-id> (set task id
102
- to id) and call the `ase_task_id(id: <ase-task-id/>, session:
103
- <ase-session-id/>)` tool from the `ase` MCP server to
103
+ to id) and call the `ase_task_id(id: "<ase-task-id/>", session:
104
+ "<ase-session-id/>")` tool from the `ase` MCP server to
104
105
  switch the task, and then only output the following
105
106
  <template/>:
106
107
 
@@ -133,7 +134,7 @@ explicitly requested by this procedure via outputs based on a <template/>!
133
134
 
134
135
  2. **Determine Plan:**
135
136
 
136
- 1. Call the `ase_task_load(id: <ase-task-id/>)` tool of the `ase` MCP
137
+ 1. Call the `ase_task_load(id: "<ase-task-id/>")` tool of the `ase` MCP
137
138
  server to load any existing plan content and set <text/> to
138
139
  the `text` output field of this `ase_task_load` tool call.
139
140
  Do not output anything related to this MCP tool call.
@@ -235,6 +236,28 @@ explicitly requested by this procedure via outputs based on a <template/>!
235
236
 
236
237
  Only output the following <template/> and continue processing:
237
238
 
239
+ <template>
240
+ ⧉ **ASE**: ◉ task: **<ase-task-id/>**, ✪ plan: **<words/>** words, ▶ status: **plan refined**
241
+ ⧉ **ASE**: ◉ task: **<ase-task-id/>**, ⇌ instruction: **<instruction/>**, ▶ status: **instruction given**
242
+ </template>
243
+
244
+ - If <result/> matches `OTHER: <text/>`:
245
+
246
+ Set <instruction><instruction/> <text/></instruction> (append
247
+ the user's free-text hint to the existing instruction).
248
+
249
+ Treat the <instruction/> as a *refinement instruction* for
250
+ the plan, and update <content/> in-place by *applying* the
251
+ requested <instruction/> to the *plan*. When refining the
252
+ plan this way, preserve the overall structure of the plan
253
+ and only modify what the user actually requested. Do *not*
254
+ rewrite unrelated sections of the plan.
255
+
256
+ Calculate the number of words <words/> of <content/>.
257
+ Set <content-dirty>true</content-dirty>.
258
+
259
+ Only output the following <template/> and continue processing:
260
+
238
261
  <template>
239
262
  ⧉ **ASE**: ◉ task: **<ase-task-id/>**, ✪ plan: **<words/>** words, ▶ status: **plan refined**
240
263
  ⧉ **ASE**: ◉ task: **<ase-task-id/>**, ⇌ instruction: **<instruction/>**, ▶ status: **instruction given**
@@ -273,9 +296,9 @@ explicitly requested by this procedure via outputs based on a <template/>!
273
296
 
274
297
  3. **Iterative Plan Refinement Loop:**
275
298
 
276
- *REPEAT* the following steps 3.1 to 3.4 in a *LOOP* until
277
- the user selects `DONE`, `IMPLEMENT`, or `PREFLIGHT`, or
278
- declines/cancels in the dialog of step 3.4:
299
+ *REPEAT* the following steps from 3.1 up to and including 3.4 in a
300
+ *LOOP* until the user selects `DONE`, `IMPLEMENT`, or `PREFLIGHT`,
301
+ or declines/cancels in the dialog of step 3.4:
279
302
 
280
303
  1. *Update timestamp*:
281
304
  <if condition="<content/> contains '✎ modified:' AND <content-dirty/> is 'true'">
@@ -289,7 +312,7 @@ explicitly requested by this procedure via outputs based on a <template/>!
289
312
 
290
313
  2. *Persist plan*:
291
314
  <if condition="<content-dirty/> is 'true'">
292
- Call the `ase_task_save(id: <ase-task-id/>, text: <content/>)` tool
315
+ Call the `ase_task_save(id: "<ase-task-id/>", text: "<content/>")` tool
293
316
  of the `ase` MCP server to persist the current plan, and then
294
317
  set <content-dirty>false</content-dirty> again. Calculate the
295
318
  number of words <words/> of <content/>. Do not output anything
@@ -301,11 +324,12 @@ explicitly requested by this procedure via outputs based on a <template/>!
301
324
  </if>
302
325
 
303
326
  3. *Render plan*: Only output the following <template/>, so the user
304
- can read the plan and react to it. If <content/> is longer than
305
- 90 lines and a `※ IMPLEMENTATION DRAFT` section exists, replace
306
- the entire content of the `※ IMPLEMENTATION DRAFT` section with
307
- `[...]`. Else, do *not* truncate, summarize, or partially show
308
- the plan. Use the following <template/>:
327
+ can read the plan and react to it. If <content/> is longer
328
+ than 90 lines and a `※ IMPLEMENTATION DRAFT` section (from the
329
+ companion skill `ase-task-preflight`) exists, replace the entire
330
+ content of the `※ IMPLEMENTATION DRAFT` section with `[...]`.
331
+ Else, do *not* truncate, summarize, or partially show the plan.
332
+ Use the following <template/>:
309
333
 
310
334
  <template>
311
335
  ⧉ **ASE**: ┈┈┈┈┈┈┈┈────────━━━━━━━━**(** `TASK-PLAN-BEGIN` **)**━━━━━━━━────────┈┈┈┈┈┈┈┈
@@ -318,8 +342,17 @@ explicitly requested by this procedure via outputs based on a <template/>!
318
342
  - If <getopt-option-next/> matches the regex `^(DONE|IMPLEMENT|PREFLIGHT|REFINE)$`:
319
343
  Honor the pre-selection what to do as the next step.
320
344
  Set <result><getopt-option-next/></result>.
321
- Then *clear* <getopt-option-next/> by setting <getopt-option-next>none</getopt-option-next>
322
- so that subsequent loop iterations fall back to the interactive dialog.
345
+
346
+ Then *clear* <getopt-option-next/> by setting
347
+ <getopt-option-next>none</getopt-option-next> so that
348
+ subsequent loop iterations fall back to the interactive
349
+ dialog.
350
+
351
+ Set <instruction></instruction> (clear the instruction, as
352
+ any instruction carried in via the arguments was already
353
+ applied to the plan in step 2 before this loop), so that a
354
+ pre-selected `REFINE` correctly asks the user for a *fresh*
355
+ refinement instruction below.
323
356
 
324
357
  - If <getopt-option-next/> is equal to `none`:
325
358
  Let the *user interactively choose* what to do as the next step.
@@ -367,9 +400,9 @@ explicitly requested by this procedure via outputs based on a <template/>!
367
400
 
368
401
  - If <result/> is `REFINE`:
369
402
 
370
- Ask the user interactively, without a special tool, for
371
- the refinement instruction with a single question `**What
372
- is your instruction for refining the plan?**`. Then set
403
+ Ask the user interactively, without a special tool, for the
404
+ refinement instruction with a single question `**What is
405
+ your instruction for further refining the plan?**`. Then set
373
406
  <instruction/> to the response of the user.
374
407
 
375
408
  Treat the <instruction/> as a *refinement instruction* for
@@ -389,7 +422,7 @@ explicitly requested by this procedure via outputs based on a <template/>!
389
422
 
390
423
  - If <result/> matches `OTHER: <text/>`:
391
424
 
392
- Set <instruction><text/></instruction>.
425
+ Set <instruction><text/></instruction> (replace existing instruction).
393
426
 
394
427
  Treat the <instruction/> as a *refinement instruction* for
395
428
  the plan, and update <content/> in-place by *applying* the
@@ -24,7 +24,7 @@ Configure Task Id
24
24
  <request>$ARGUMENTS</request>
25
25
 
26
26
  2. <if condition="<request/> is empty">
27
- - Call the `ase_task_id(session: <ase-session-id/>)`
27
+ - Call the `ase_task_id(session: "<ase-session-id/>")`
28
28
  tool from the `ase` MCP server and set
29
29
  <ase-task-id/> to its `text` output.
30
30
 
@@ -36,7 +36,7 @@ Configure Task Id
36
36
 
37
37
  3. <if condition="<request/> is NOT empty">
38
38
  - Set <ase-task-id><request/></ase-task-id> and
39
- call the `ase_task_id(id: <ase-task-id/>, session: <ase-session-id/>)`
39
+ call the `ase_task_id(id: "<ase-task-id/>", session: "<ase-session-id/>")`
40
40
  tool from the `ase` MCP server.
41
41
 
42
42
  - Output:
@@ -59,8 +59,8 @@ explicitly requested by this procedure via outputs based on a <template/>!
59
59
  ">
60
60
  Set <ase-task-id><instruction/></ase-task-id> (set task
61
61
  id to instruction) and <instruction></instruction> (set
62
- instruction empty), call the `ase_task_id(id: <ase-task-id/>,
63
- session: <ase-session-id/>)` tool from the `ase` MCP
62
+ instruction empty), call the `ase_task_id(id: "<ase-task-id/>",
63
+ session: "<ase-session-id/>")` tool from the `ase` MCP
64
64
  server to switch the task, and then only output the
65
65
  following <template/>:
66
66
 
@@ -76,8 +76,8 @@ explicitly requested by this procedure via outputs based on a <template/>!
76
76
  ">
77
77
  Set <instruction></instruction> (set instruction to empty)
78
78
  and <ase-task-id><id/></ase-task-id> (set task id to
79
- id) and call the `ase_task_id(id: <ase-task-id/>, session:
80
- <ase-session-id/>)` tool from the `ase` MCP server to
79
+ id) and call the `ase_task_id(id: "<ase-task-id/>", session:
80
+ "<ase-session-id/>")` tool from the `ase` MCP server to
81
81
  switch the task, and then only output the following
82
82
  <template/>:
83
83
 
@@ -86,13 +86,30 @@ explicitly requested by this procedure via outputs based on a <template/>!
86
86
  </template>
87
87
  </if>
88
88
 
89
+ 3. else <if condition="<instruction/> is NOT empty">
90
+ The argument is neither empty nor a valid task id. As this
91
+ skill only accepts an optional `[<id>]` argument and *never*
92
+ a free-text instruction, only output the following <template/>
93
+ and then immediately *STOP* processing the entire current skill:
94
+
95
+ <template>
96
+ ⧉ **ASE**: ☻ skill: **ase-task-implement**, ▶ ERROR: expected single `[<id>]` argument
97
+ </template>
98
+ </if>
99
+
89
100
  2. **Determine Operation**:
90
101
 
91
- 1. Call the `ase_task_load(id: <ase-task-id/>)` tool of the `ase` MCP
92
- server to load the current task plan content and set <content/> to
102
+ 1. Call the `ase_task_load(id: "<ase-task-id/>")` tool of the `ase` MCP
103
+ server to load the current task plan content and set <text/> to
93
104
  the `text` output field of the `ase_task_load` tool call.
94
105
 
95
- Calculate the number of words <words/> of <content/>.
106
+ - If <text/> starts with `ERROR:` or `WARNING:`:
107
+ Set <content></content> (set content to empty).
108
+ Set <words/> to "0".
109
+
110
+ - If <text/> starts NOT with `ERROR:` and NOT with `WARNING:`:
111
+ Set <content><text/></content> (set content to text).
112
+ Calculate the number of words <words/> of <content/>.
96
113
 
97
114
  Only output the following <template/>:
98
115
 
@@ -26,7 +26,7 @@ List Task Plans
26
26
  $ARGUMENTS
27
27
  </expand>
28
28
 
29
- 1. Call the `ase_task_list(verbose: <getopt-option-verbose/>)` tool from
29
+ 1. Call the `ase_task_list(verbose: "<getopt-option-verbose/>")` tool from
30
30
  the `ase` MCP server. The result is a structured object with a
31
31
  `tasks` array where each entry has an `id` field, and -- if
32
32
  <getopt-option-verbose/> is `true` -- additionally an `mtime` field
@@ -59,8 +59,8 @@ explicitly requested by this procedure via outputs based on a <template/>!
59
59
  ">
60
60
  Set <ase-task-id><instruction/></ase-task-id> (set task
61
61
  id to instruction) and <instruction></instruction> (set
62
- instruction empty), call the `ase_task_id(id: <ase-task-id/>,
63
- session: <ase-session-id/>)` tool from the `ase` MCP
62
+ instruction empty), call the `ase_task_id(id: "<ase-task-id/>",
63
+ session: "<ase-session-id/>")` tool from the `ase` MCP
64
64
  server to switch the task, and then only output the
65
65
  following <template/>:
66
66
 
@@ -76,8 +76,8 @@ explicitly requested by this procedure via outputs based on a <template/>!
76
76
  ">
77
77
  Set <instruction></instruction> (set instruction to empty)
78
78
  and <ase-task-id><id/></ase-task-id> (set task id to
79
- id) and call the `ase_task_id(id: <ase-task-id/>, session:
80
- <ase-session-id/>)` tool from the `ase` MCP server to
79
+ id) and call the `ase_task_id(id: "<ase-task-id/>", session:
80
+ "<ase-session-id/>")` tool from the `ase` MCP server to
81
81
  switch the task, and then only output the following
82
82
  <template/>:
83
83
 
@@ -86,13 +86,30 @@ explicitly requested by this procedure via outputs based on a <template/>!
86
86
  </template>
87
87
  </if>
88
88
 
89
+ 3. else <if condition="<instruction/> is NOT empty">
90
+ The argument is neither empty nor a valid task id. As this
91
+ skill only accepts an optional `[<id>]` argument and *never*
92
+ a free-text instruction, only output the following <template/>
93
+ and then immediately *STOP* processing the entire current skill:
94
+
95
+ <template>
96
+ ⧉ **ASE**: ☻ skill: **ase-task-preflight**, ▶ ERROR: expected single `[<id>]` argument
97
+ </template>
98
+ </if>
99
+
89
100
  2. **Determine Operation:**
90
101
 
91
- 1. Call the `ase_task_load(id: <ase-task-id/>)` tool of the `ase` MCP
92
- server to load the current task plan content and set <content/> to
102
+ 1. Call the `ase_task_load(id: "<ase-task-id/>")` tool of the `ase` MCP
103
+ server to load the current task plan content and set <text/> to
93
104
  the `text` output field of the `ase_task_load` tool call.
94
105
 
95
- Calculate the number of words <words/> of <content/>.
106
+ - If <text/> starts with `ERROR:` or `WARNING:`:
107
+ Set <content></content> (set content to empty).
108
+ Set <words/> to "0".
109
+
110
+ - If <text/> starts NOT with `ERROR:` and NOT with `WARNING:`:
111
+ Set <content><text/></content> (set content to text).
112
+ Calculate the number of words <words/> of <content/>.
96
113
 
97
114
  Only output the following <template/>:
98
115
 
@@ -136,8 +153,8 @@ explicitly requested by this procedure via outputs based on a <template/>!
136
153
  Do not output anything.
137
154
  </if>
138
155
 
139
- 4. Finally, call the `ase_task_save(id: <ase-task-id/>,
140
- text: <content/>)` of the `ase` MCP server to save the updated
156
+ 4. Finally, call the `ase_task_save(id: "<ase-task-id/>",
157
+ text: "<content/>")` of the `ase` MCP server to save the updated
141
158
  task plan content. Calculate the number of words <words/> of
142
159
  <content/>. Do not output anything related to this MCP tool call
143
160
  except the following <template/>:
@@ -56,28 +56,45 @@ explicitly requested by this procedure via outputs based on a <template/>!
56
56
 
57
57
  2. React on task id:
58
58
 
59
- <if condition="
60
- <instruction/> matches the regexp `^[a-zA-Z][a-zA-Z0-9_-]*$`
61
- ">
62
- Set <ase-task-id><instruction/></ase-task-id> (set task
63
- id to instruction) and <instruction></instruction> (set
64
- instruction empty), call the `ase_task_id(id: <ase-task-id/>,
65
- session: <ase-session-id/>)` tool from the `ase` MCP
66
- server to switch the task, and then only output the
67
- following <template/>:
59
+ 1. <if condition="
60
+ <instruction/> matches the regexp `^[a-zA-Z][a-zA-Z0-9_-]*$`
61
+ ">
62
+ Set <ase-task-id><instruction/></ase-task-id> (set task
63
+ id to instruction) and <instruction></instruction> (set
64
+ instruction empty), call the `ase_task_id(id: "<ase-task-id/>",
65
+ session: "<ase-session-id/>")` tool from the `ase` MCP
66
+ server to switch the task, and then only output the
67
+ following <template/>:
68
68
 
69
- <template>
70
- ⧉ **ASE**: ◉ task: **<ase-task-id/>**, ▶ status: **task given**
71
- </template>
72
- </if>
69
+ <template>
70
+ ⧉ **ASE**: ◉ task: **<ase-task-id/>**, ▶ status: **task given**
71
+ </template>
72
+ </if>
73
+
74
+ 2. else <if condition="<instruction/> is NOT empty">
75
+ The argument is neither empty nor a valid task id. As this
76
+ skill only accepts an optional `[<id>]` argument and *never*
77
+ a free-text instruction, only output the following <template/>
78
+ and then immediately *STOP* processing the entire current skill:
79
+
80
+ <template>
81
+ ⧉ **ASE**: ☻ skill: **ase-task-reboot**, ▶ ERROR: expected single `[<id>]` argument
82
+ </template>
83
+ </if>
73
84
 
74
85
  2. **Determine Operation:**
75
86
 
76
- 1. Call the `ase_task_load(id: <ase-task-id/>)` tool of the `ase` MCP
77
- server to load the current task plan content and set <content/> to
87
+ 1. Call the `ase_task_load(id: "<ase-task-id/>")` tool of the `ase` MCP
88
+ server to load the current task plan content and set <text/> to
78
89
  the `text` output field of the `ase_task_load` tool call.
79
90
 
80
- Calculate the number of words <words/> of <content/>.
91
+ - If <text/> starts with `ERROR:` or `WARNING:`:
92
+ Set <content></content> (set content to empty).
93
+ Set <words/> to "0".
94
+
95
+ - If <text/> starts NOT with `ERROR:` and NOT with `WARNING:`:
96
+ Set <content><text/></content> (set content to text).
97
+ Calculate the number of words <words/> of <content/>.
81
98
 
82
99
  Only output the following <template/>:
83
100
 
@@ -104,35 +121,39 @@ explicitly requested by this procedure via outputs based on a <template/>!
104
121
  Set <instruction><text/></instruction> (set instruction to extracted text).
105
122
  </if>
106
123
 
107
- 4. <if condition="<content/> contains '- **WHY**: <text/>'">
124
+ 4. <if condition="<content/> contains '- **WHY**: <text/>' and <instruction/> is empty">
125
+ Set <instruction><text/></instruction> (set instruction to extracted text).
126
+ </if>
127
+
128
+ 5. else <if condition="<content/> contains '- **WHY**: <text/>' and <instruction/> is NOT empty">
108
129
  Set <instruction><instruction/>, BECAUSE <text/></instruction>
109
130
  (append extracted text to instruction).
110
131
  </if>
111
132
 
112
- 5. <if condition="<content/> contains 'created: **<text/>**'">
133
+ 6. <if condition="<content/> contains 'created: **<text/>**'">
113
134
  Set <timestamp-created><text/></timestamp-created> (set
114
135
  timestamp-created to extracted text)
115
136
  </if>
116
137
 
117
- 6. Create a new plan from scratch and store the result as
138
+ 7. Create a new plan from scratch and store the result as
118
139
  <content/> by closely following the defined plan format
119
140
  <format/> and injecting into it all the information from
120
141
  the <instruction/> and all decisions you derived from the
121
142
  <instruction/>.
122
143
 
123
- 7. Call the `ase_timestamp(format: "yyyy-LL-dd HH:mm")` tool of the
144
+ 8. Call the `ase_timestamp(format: "yyyy-LL-dd HH:mm")` tool of the
124
145
  `ase` MCP server and use the `text` field of its response for
125
146
  <timestamp-modified/> information. Then insert the current
126
147
  <ase-task-id/>, previous <timestamp-created/>, and refreshed
127
148
  <timestamp-modified/> information and calculate the number of
128
149
  words <words/> of <content/>.
129
150
 
130
- 8. Call the `ase_task_save(id: <ase-task-id/>,
131
- text: <content/>)` of the `ase` MCP server to save the updated
151
+ 9. Call the `ase_task_save(id: "<ase-task-id/>",
152
+ text: "<content/>")` of the `ase` MCP server to save the updated
132
153
  task plan content. Do not output anything related to this MCP
133
154
  call.
134
155
 
135
- 9. Only output the following <template/> and continue processing:
156
+ 10. Only output the following <template/> and continue processing:
136
157
 
137
158
  <template>
138
159
  ⧉ **ASE**: ◉ task: **<ase-task-id/>**, ✪ plan: **<words/>** words, ▶ status: **plan rebooted**
@@ -64,7 +64,7 @@ explicitly requested by this procedure via outputs based on a <template/>!
64
64
 
65
65
  2. **Perform Operation**:
66
66
 
67
- 1. Call the `ase_task_rename(old: <old/>, new: <new/>)` tool of the
67
+ 1. Call the `ase_task_rename(old: "<old/>", new: "<new/>")` tool of the
68
68
  `ase` MCP server to rename the task plan and set <text/> to the
69
69
  `text` output field of this `ase_task_rename` tool call. Do not
70
70
  output anything related to this MCP tool call.
@@ -85,7 +85,7 @@ explicitly requested by this procedure via outputs based on a <template/>!
85
85
 
86
86
  2. <if condition="<old/> is equal <ase-task-id/>">
87
87
  Set <ase-task-id><new/></ase-task-id>. Call the `ase_task_id(id:
88
- <ase-task-id/>, session: <ase-session-id/>)` tool from the `ase`
88
+ "<ase-task-id/>", session: "<ase-session-id/>")` tool from the `ase`
89
89
  MCP server to switch the task to the renamed task. Only output
90
90
  the following <template/>:
91
91
 
@@ -36,7 +36,8 @@ explicitly requested by this procedure via outputs based on a <template/>!
36
36
 
37
37
  1. **Determine Task:**
38
38
 
39
- 1. Set <id>$ARGUMENTS</id> initially.
39
+ 1. Set <id>$ARGUMENTS</id> initially, with any leading and trailing
40
+ whitespace stripped.
40
41
  Inherit the always existing <ase-task-id/> from the current context.
41
42
  Do not output anything.
42
43
 
@@ -45,9 +46,18 @@ explicitly requested by this procedure via outputs based on a <template/>!
45
46
  Do not output anything.
46
47
  </if>
47
48
 
49
+ 3. <if condition="<id/> does NOT match the regexp `^[a-zA-Z][a-zA-Z0-9_-]*$`">
50
+ Only output the following <template/> and then immediately
51
+ *STOP* processing the entire current skill:
52
+
53
+ <template>
54
+ ⧉ **ASE**: ☻ skill: **ase-task-view**, ▶ ERROR: expected single `[<id>]` argument
55
+ </template>
56
+ </if>
57
+
48
58
  2. **Perform Operation**:
49
59
 
50
- 1. Call the `ase_task_load(id: <id/>)` tool of the `ase` MCP
60
+ 1. Call the `ase_task_load(id: "<id/>")` tool of the `ase` MCP
51
61
  server to load the task plan content and set <text/> to the
52
62
  `text` output field of this `ase_task_load` tool call. Do not
53
63
  output anything related to this MCP tool call.
@@ -60,7 +70,7 @@ explicitly requested by this procedure via outputs based on a <template/>!
60
70
  ⧉ **ASE**: ◉ task: **<id/>**, ▶ status: **<text/>**
61
71
  </template>
62
72
 
63
- - If <text/> starts NOT with `ERROR:`:
73
+ - If <text/> starts NOT with `ERROR:` and NOT with `WARNING:`:
64
74
  Set <content><text/></content> (set content to text).
65
75
  Calculate the number of words <words/> of <content/>.
66
76
  Only output the following <template/>: