@rse/ase 0.0.36 → 0.0.38

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-hello.js CHANGED
@@ -3,7 +3,11 @@
3
3
  ** Copyright (c) 2025-2026 Dr. Ralf S. Engelschall <rse@engelschall.com>
4
4
  ** Licensed under GPL 3.0 <https://spdx.org/licenses/GPL-3.0-only>
5
5
  */
6
- import chalk from "chalk";
6
+ import { Chalk } from "chalk";
7
+ /* forced-color chalk instance: stdout is a pipe under Claude Code,
8
+ so chalk auto-detection would yield level 0; force level 1 to keep
9
+ emitting ANSI sequences as the original implementation did */
10
+ const c = new Chalk({ level: 1 });
7
11
  /* command-line handling */
8
12
  export default class HelloCommand {
9
13
  log;
@@ -14,9 +18,10 @@ export default class HelloCommand {
14
18
  register(program) {
15
19
  program
16
20
  .command("hello")
17
- .description("Print \"Hello World\" in red")
18
- .action(async () => {
19
- process.stdout.write(chalk.red("Hello World") + "\n");
21
+ .description("print a colored greeting message")
22
+ .option("-s, --subject <name>", "subject to greet", "Universe")
23
+ .action(async (opts) => {
24
+ process.stdout.write(`${c.red(`${opts.subject} World!`)}\n`);
20
25
  });
21
26
  }
22
27
  }
package/dst/ase-hook.js CHANGED
@@ -106,6 +106,8 @@ export default class HookCommand {
106
106
  cfg.set("agent.task", taskId);
107
107
  cfg.write();
108
108
  });
109
+ /* initialize agent activity status */
110
+ this.writeAgentStatus("ready");
109
111
  /* determine project id */
110
112
  const cwd = input.cwd ?? process.cwd();
111
113
  let projectDir = cwd;
@@ -170,6 +172,32 @@ export default class HookCommand {
170
172
  process.stdout.write(JSON.stringify(payload));
171
173
  return 0;
172
174
  }
175
+ /* publish the agent activity marker to tmux as a per-pane user
176
+ option, so tmux can render the live state via
177
+ #{@ase_agent_status} (refreshed on tmux's own interval,
178
+ independent of Claude Code's statusline repaint cadence).
179
+ Notice: the Claude Code statusline is not usable for this case
180
+ here at all, as it is not repainted during agent processing! */
181
+ writeAgentStatus(status) {
182
+ const icon = status === "busy" ? "▶" : "⏸";
183
+ if (process.env.TMUX !== undefined
184
+ && process.env.TMUX !== ""
185
+ && process.env.TMUX_PANE !== undefined
186
+ && process.env.TMUX_PANE !== "") {
187
+ execaSync("tmux", ["set-option", "-p", "-t", process.env.TMUX_PANE,
188
+ "@ase_agent_status", icon], { stdio: "ignore", reject: false });
189
+ }
190
+ }
191
+ /* handler for "ase hook user-prompt-submit" (both tools) */
192
+ doUserPromptSubmit(_tool) {
193
+ this.writeAgentStatus("busy");
194
+ return 0;
195
+ }
196
+ /* handler for "ase hook stop" (both tools) */
197
+ doStop(_tool) {
198
+ this.writeAgentStatus("ready");
199
+ return 0;
200
+ }
173
201
  /* handler for "ase hook session-end" (both tools) */
174
202
  doSessionEnd(_tool) {
175
203
  /* read session information (Claude Code uses snake_case fields,
@@ -287,5 +315,21 @@ export default class HookCommand {
287
315
  .action((opts) => {
288
316
  process.exit(this.doPreToolUse(this.parseTool(opts.tool)));
289
317
  });
318
+ /* register CLI sub-command "ase hook user-prompt-submit" */
319
+ hookCmd
320
+ .command("user-prompt-submit")
321
+ .description("handle UserPromptSubmit hook event (mark agent as busy)")
322
+ .option("-t, --tool <tool>", "target tool (\"claude\" or \"copilot\")", toolDflt)
323
+ .action((opts) => {
324
+ process.exit(this.doUserPromptSubmit(this.parseTool(opts.tool)));
325
+ });
326
+ /* register CLI sub-command "ase hook stop" */
327
+ hookCmd
328
+ .command("stop")
329
+ .description("handle Stop hook event (mark agent as ready)")
330
+ .option("-t, --tool <tool>", "target tool (\"claude\" or \"copilot\")", toolDflt)
331
+ .action((opts) => {
332
+ process.exit(this.doStop(this.parseTool(opts.tool)));
333
+ });
290
334
  }
291
335
  }
package/dst/ase-setup.js CHANGED
@@ -3,6 +3,7 @@
3
3
  ** Copyright (c) 2025-2026 Dr. Ralf S. Engelschall <rse@engelschall.com>
4
4
  ** Licensed under GPL 3.0 <https://spdx.org/licenses/GPL-3.0-only>
5
5
  */
6
+ import fs from "node:fs/promises";
6
7
  import path from "node:path";
7
8
  import { fileURLToPath } from "node:url";
8
9
  import { execa } from "execa";
@@ -24,6 +25,74 @@ export default class SetupCommand {
24
25
  throw new Error(`mandatory tool "${tool}" not found in $PATH`);
25
26
  });
26
27
  }
28
+ /* determine whether a global "npm" operation requires "sudo" by
29
+ checking whether the npm global install root is writable by the
30
+ current user; on Windows or when already running as root, no
31
+ elevation is needed */
32
+ async npmGlobalNeedsSudo() {
33
+ /* Windows has no "sudo" concept here */
34
+ if (process.platform === "win32")
35
+ return false;
36
+ /* already running as root */
37
+ const getuid = process.getuid;
38
+ if (typeof getuid === "function" && getuid.call(process) === 0)
39
+ return false;
40
+ /* determine the npm global prefix and probe writability of the
41
+ directories that "npm -g" actually mutates */
42
+ let prefix = "";
43
+ try {
44
+ const result = await execa("npm", ["prefix", "-g"], { stdio: "pipe" });
45
+ prefix = result.stdout.trim();
46
+ }
47
+ catch {
48
+ /* if we cannot determine the prefix, fall back to "no sudo" */
49
+ return false;
50
+ }
51
+ if (prefix === "")
52
+ return false;
53
+ const candidates = [
54
+ prefix,
55
+ path.join(prefix, "bin"),
56
+ path.join(prefix, "lib", "node_modules")
57
+ ];
58
+ for (const dir of candidates) {
59
+ try {
60
+ await fs.access(dir, fs.constants.W_OK);
61
+ }
62
+ catch {
63
+ /* directory exists but not writable, or does not exist
64
+ inside a non-writable parent: require sudo */
65
+ try {
66
+ await fs.access(dir, fs.constants.F_OK);
67
+ return true;
68
+ }
69
+ catch {
70
+ /* directory does not exist: check parent writability */
71
+ try {
72
+ await fs.access(path.dirname(dir), fs.constants.W_OK);
73
+ }
74
+ catch {
75
+ return true;
76
+ }
77
+ }
78
+ }
79
+ }
80
+ return false;
81
+ }
82
+ /* build the (cmd, args) pair for an "npm" invocation, prefixing
83
+ with "sudo" when necessary for global operations */
84
+ async npmCmd(args, global) {
85
+ if (global && await this.npmGlobalNeedsSudo()) {
86
+ const sudo = await which("sudo").catch(() => "");
87
+ if (sudo !== "") {
88
+ this.log.write("info", "setup: npm global install root not writable: using \"sudo\"");
89
+ return { cmd: "sudo", args: ["npm", ...args] };
90
+ }
91
+ this.log.write("warning", "setup: npm global install root is not writable by current user " +
92
+ "and \"sudo\" not found in $PATH: attempting without elevation");
93
+ }
94
+ return { cmd: "npm", args };
95
+ }
27
96
  /* run a sub-process, suppressing output on success and emitting it on failure */
28
97
  async run(cmd, args, opts = {}) {
29
98
  const { cwd, quiet = false, retries = 1, ignoreError } = opts;
@@ -118,7 +187,8 @@ export default class SetupCommand {
118
187
  }
119
188
  /* update ASE CLI tool */
120
189
  this.log.write("info", `setup: update: updating ASE CLI tool: ${current} -> ${latest}`);
121
- await this.run("npm", ["update", "-g", "@rse/ase"]);
190
+ const updateCmd = await this.npmCmd(["update", "-g", "@rse/ase"], true);
191
+ await this.run(updateCmd.cmd, updateCmd.args);
122
192
  /* update ASE plugin */
123
193
  this.log.write("info", `setup: update: updating ASE ${spec.label} plugin`);
124
194
  await this.run(spec.cli, ["plugin", "marketplace", "update", "ase"]);
@@ -165,7 +235,8 @@ export default class SetupCommand {
165
235
  /* uninstall ASE CLI tool (non-development only) */
166
236
  if (!dev) {
167
237
  this.log.write("info", "setup: uninstall: uninstalling ASE CLI tool (origin: remote)");
168
- await this.run("npm", ["uninstall", "-g", "@rse/ase"]);
238
+ const uninstallCmd = await this.npmCmd(["uninstall", "-g", "@rse/ase"], true);
239
+ await this.run(uninstallCmd.cmd, uninstallCmd.args);
169
240
  }
170
241
  return 0;
171
242
  }
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.36",
9
+ "version": "0.0.38",
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.36",
3
+ "version": "0.0.38",
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.36",
3
+ "version": "0.0.38",
4
4
  "description": "Agentic Software Engineering (ASE)",
5
5
  "keywords": [ "agentic", "software", "engineering" ],
6
6
  "homepage": "https://ase.tools",
@@ -3,20 +3,37 @@
3
3
  "hooks": {
4
4
  "sessionStart": [
5
5
  {
6
- "type": "command",
7
- "bash": "ase hook session-start --tool copilot"
6
+ "type": "command",
7
+ "bash": "ase hook session-start --tool copilot",
8
+ "powershell": "ase hook session-start --tool copilot"
8
9
  }
9
10
  ],
10
11
  "sessionEnd": [
11
12
  {
12
- "type": "command",
13
- "bash": "ase hook session-end --tool copilot"
13
+ "type": "command",
14
+ "bash": "ase hook session-end --tool copilot",
15
+ "powershell": "ase hook session-end --tool copilot"
14
16
  }
15
17
  ],
16
18
  "preToolUse": [
17
19
  {
18
- "type": "command",
19
- "bash": "ase hook pre-tool-use --tool copilot"
20
+ "type": "command",
21
+ "bash": "ase hook pre-tool-use --tool copilot",
22
+ "powershell": "ase hook pre-tool-use --tool copilot"
23
+ }
24
+ ],
25
+ "userPromptSubmitted": [
26
+ {
27
+ "type": "command",
28
+ "bash": "ase hook user-prompt-submit --tool copilot",
29
+ "powershell": "ase hook user-prompt-submit --tool copilot"
30
+ }
31
+ ],
32
+ "agentStop": [
33
+ {
34
+ "type": "command",
35
+ "bash": "ase hook stop --tool copilot",
36
+ "powershell": "ase hook stop --tool copilot"
20
37
  }
21
38
  ]
22
39
  }
@@ -2,7 +2,6 @@
2
2
  "hooks": {
3
3
  "SessionStart": [
4
4
  {
5
- "matcher": "startup|resume|clear|compact",
6
5
  "hooks": [
7
6
  {
8
7
  "type": "command",
@@ -14,7 +13,6 @@
14
13
  ],
15
14
  "SessionEnd": [
16
15
  {
17
- "matcher": "",
18
16
  "hooks": [
19
17
  {
20
18
  "type": "command",
@@ -26,7 +24,6 @@
26
24
  ],
27
25
  "PreToolUse": [
28
26
  {
29
- "matcher": "",
30
27
  "hooks": [
31
28
  {
32
29
  "type": "command",
@@ -35,6 +32,26 @@
35
32
  }
36
33
  ]
37
34
  }
35
+ ],
36
+ "UserPromptSubmit": [
37
+ {
38
+ "hooks": [
39
+ {
40
+ "type": "command",
41
+ "command": "ase hook user-prompt-submit"
42
+ }
43
+ ]
44
+ }
45
+ ],
46
+ "Stop": [
47
+ {
48
+ "hooks": [
49
+ {
50
+ "type": "command",
51
+ "command": "ase hook stop"
52
+ }
53
+ ]
54
+ }
38
55
  ]
39
56
  }
40
57
  }
@@ -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.36",
9
+ "version": "0.0.38",
10
10
  "license": "GPL-3.0-only",
11
11
  "author": {
12
12
  "name": "Dr. Ralf S. Engelschall",
@@ -84,19 +84,30 @@ permitted way to persist artifacts is via `task_save(...)`.
84
84
 
85
85
  Then set <feature/> to the response of the user.
86
86
 
87
- 4. Report the task and feature with the following <template/>:
87
+ 4. <if condition="
88
+ <ase-task-id/> is equal `default` and
89
+ <feature/> is not empty
90
+ ">
91
+ Set <ase-task-id/> to a unique task id, derived from <feature/>,
92
+ which consists of two lower-case words concatenated with a
93
+ `-` character. Then call the `task_id(id: <ase-task-id/>,
94
+ session: <ase-session-id/>)` tool from the `ase` MCP service to
95
+ implicitly switch the task.
96
+ </if>
97
+
98
+ 5. Report the task and feature with the following <template/>:
88
99
 
89
100
  <template>
90
101
  ⧉ **ASE**: ◉ task: **<ase-task-id/>**
91
102
  ⧉ **ASE**: ⇌ feature: **<feature/>**
92
103
  </template>
93
104
 
94
- 5. Figure out what the requested <feature/> to be crafted is about.
105
+ 6. Figure out what the requested <feature/> to be crafted is about.
95
106
 
96
- 6. Ask the user for clarification if the goal of this crafting is too
107
+ 7. Ask the user for clarification if the goal of this crafting is too
97
108
  unclear.
98
109
 
99
- 7. Do not output anything in this step, except you asked the user.
110
+ 8. Do not output anything in this step, except you asked the user.
100
111
 
101
112
  2. **Investigate Code Base**:
102
113
 
@@ -168,8 +179,9 @@ permitted way to persist artifacts is via `task_save(...)`.
168
179
  4. **Choose Feature Crafting Approach**:
169
180
 
170
181
  1. If <getopt-option-auto/> is equal `false`:
171
- Let the *user interactively choose* the preferred feature approach A<n/>
172
- with the help of the <user-dialog-tool/> tool. Use *single-selection* only
182
+ Let the *user interactively choose* the preferred feature
183
+ approach A<n/> with the help of the <user-dialog-tool/> tool.
184
+ Use the header `Select Approach` and *single-selection* only
173
185
  and provide small *code change previews*. Mark your recommended
174
186
  feature approach with ` ⚝ **RECOMMENDATION** ⚝` here again.
175
187
 
@@ -84,19 +84,30 @@ permitted way to persist artifacts is via `task_save(...)`.
84
84
 
85
85
  Then set <request/> to the response of the user.
86
86
 
87
- 4. Report the task and request with the following <template/>:
87
+ 4. <if condition="
88
+ <ase-task-id/> is equal `default` and
89
+ <request/> is not empty
90
+ ">
91
+ Set <ase-task-id/> to a unique task id, derived from <request/>,
92
+ which consists of two lower-case words concatenated with a
93
+ `-` character. Then call the `task_id(id: <ase-task-id/>,
94
+ session: <ase-session-id/>)` tool from the `ase` MCP service to
95
+ implicitly switch the task.
96
+ </if>
97
+
98
+ 5. Report the task and request with the following <template/>:
88
99
 
89
100
  <template>
90
101
  ⧉ **ASE**: ◉ task: **<ase-task-id/>**
91
102
  ⧉ **ASE**: ⇌ request: **<request/>**
92
103
  </template>
93
104
 
94
- 5. Figure out what the artifact refactoring <request/> is about.
105
+ 6. Figure out what the artifact refactoring <request/> is about.
95
106
 
96
- 6. Ask the user for clarification if the goal of this refactoring is
107
+ 7. Ask the user for clarification if the goal of this refactoring is
97
108
  too unclear.
98
109
 
99
- 7. Do not output anything in this step, except you asked the user.
110
+ 8. Do not output anything in this step, except you asked the user.
100
111
 
101
112
  2. **Investigate Code Base**:
102
113
 
@@ -172,11 +183,13 @@ permitted way to persist artifacts is via `task_save(...)`.
172
183
  4. **Choose Refactoring Approach**:
173
184
 
174
185
  1. If <getopt-option-auto/> is equal `false`:
175
- Let the *user interactively choose* the preferred refactoring approach A<n/>
176
- with the help of the <user-dialog-tool/> tool. Use *single-selection* only
186
+ Let the *user interactively choose* the preferred refactoring
187
+ approach A<n/> with the help of the <user-dialog-tool/> tool.
188
+ Use the header `Select Approach` and *single-selection* only
177
189
  and provide small *code change previews*. Mark your recommended
178
190
  refactoring approach with ` ⚝ **RECOMMENDATION** ⚝` here again.
179
- Except for the interactive selection, do not output anything in this step.
191
+ Except for the interactive selection, do not output anything in
192
+ this step.
180
193
 
181
194
  2. If <getopt-option-auto/> is equal `true`:
182
195
  Set <n/> to the number of the refactoring approach A<n/> you recommend.
@@ -56,12 +56,13 @@ permitted way to persist artifacts is via `task_save(...)`.
56
56
  1. **Reason About Problem**:
57
57
 
58
58
  1. If <problem/> matches the regexp `^[PT]\d+$` (i.e. a bare issue
59
- identifier like `P1`, `P2`, `T1`, `T2`, ...), set
60
- <problem-id><problem/></problem-id>, call the `task_id(id:
61
- <ase-task-id/>, session: <ase-session-id/>)` tool from the `ase`
62
- MCP service to implicitly switch the task, and then call the
63
- `kv_get(key: "ase-issue-<problem-id/>")` tool
64
- of the `ase` MCP service to retrieve the previously persisted
59
+ identifier like `P1`, `P2`, `T1`, `T2`, ...),
60
+ set <problem-id><problem/></problem-id> and
61
+ <ase-task-id><problem/></ase-task-id>, call the `task_id(id:
62
+ <ase-task-id/>, session: <ase-session-id/>)` tool from the
63
+ `ase` MCP service to implicitly switch the task, and then
64
+ call the `kv_get(key: "ase-issue-<problem-id/>")` tool of
65
+ the `ase` MCP service to retrieve the previously persisted
65
66
  problem description. If the returned `text` is non-empty, set
66
67
  <problem><text/></problem>, otherwise complain to the user that
67
68
  no analyzer result exists for <problem-id/> and stop processing.
@@ -95,21 +96,32 @@ permitted way to persist artifacts is via `task_save(...)`.
95
96
 
96
97
  Then set <problem/> to the response of the user.
97
98
 
98
- 5. Report the task and problem with the following <template/>:
99
+ 5. <if condition="
100
+ <ase-task-id/> is equal `default` and
101
+ <problem/> is not empty
102
+ ">
103
+ Set <ase-task-id/> to a unique task id, derived from <problem/>,
104
+ which consists of two lower-case words concatenated with a
105
+ `-` character. Then call the `task_id(id: <ase-task-id/>,
106
+ session: <ase-session-id/>)` tool from the `ase` MCP service to
107
+ implicitly switch the task.
108
+ </if>
109
+
110
+ 6. Report the task and problem with the following <template/>:
99
111
 
100
112
  <template>
101
113
  ⧉ **ASE**: ◉ task: **<ase-task-id/>**
102
114
  ⧉ **ASE**: ⇌ problem: **<problem/>**
103
115
  </template>
104
116
 
105
- 6. Figure out what the requested <problem/> is about.
117
+ 7. Figure out what the requested <problem/> is about.
106
118
 
107
- 7. Ask the user for clarification if the goal of this resolution is
119
+ 8. Ask the user for clarification if the goal of this resolution is
108
120
  too unclear.
109
121
 
110
- 8. Do not output anything in this step, except you asked the user.
122
+ 9. Do not output anything in this step, except you asked the user.
111
123
 
112
- 9. Investigate and *figure out details* related to this problem.
124
+ 10. Investigate and *figure out details* related to this problem.
113
125
  Report those details with the following <template/>:
114
126
 
115
127
  <template>
@@ -224,8 +236,9 @@ permitted way to persist artifacts is via `task_save(...)`.
224
236
  4. **Choose Problem Resolution Approach**:
225
237
 
226
238
  1. If <getopt-option-auto/> is equal `false`:
227
- Let the *user interactively choose* the preferred resolution approach A<n/>
228
- with the help of the <user-dialog-tool/> tool. Use *single-selection* only
239
+ Let the *user interactively choose* the preferred resolution
240
+ approach A<n/> with the help of the <user-dialog-tool/> tool.
241
+ Use the header `Select Approach` and *single-selection* only
229
242
  and provide small *code change previews*. Mark your recommended
230
243
  resolution approach with ` ⚝ **RECOMMENDATION** ⚝` here again.
231
244
 
@@ -21,8 +21,10 @@ Evaluate Alternatives
21
21
  Evaluate Alternatives
22
22
  </skill>
23
23
 
24
+ <role>
24
25
  Your role is an experienced, *expert-level assistant*,
25
26
  specialized in *evaluating alternatives*.
27
+ </role>
26
28
 
27
29
  <objective>
28
30
  *Evaluate* *alternatives* through a weighted
@@ -73,10 +75,11 @@ multi-*criteria* decision matrix.
73
75
  over) is its single most distinguishing perspective, and remember
74
76
  this as an <info-K/> (K=1-N) formatted like `<type/>: <hint/>` where
75
77
  <type/> is one of `USP`, `Crux`, or `Gotcha` and <hint/> is a 1-6
76
- word hint.
78
+ word hint. Do not output anything.
77
79
 
78
80
  - For the set of alternatives, decide what the 1-6 word long
79
81
  name of the *class of alternatives* <class-of-alternatives/> is.
82
+ Do not output anything.
80
83
 
81
84
  - For each alternative <alternative-K/> (K=1-N), decide whether
82
85
  it is a genuine member of <class-of-alternatives/>. If any
@@ -178,16 +181,16 @@ multi-*criteria* decision matrix.
178
181
  - The best alternative <alternative-K/> (K=1-N) is the alternative
179
182
  whose *raw, unrounded* <rating-K/> (i.e. the product-sum from STEP
180
183
  4, *before* the display-only rounding) is the maximum rating value
181
- across all alternatives.
184
+ across all alternatives. Do not output anything.
182
185
 
183
186
  - The second best alternative <alternative-X/> (X=1-N, X != K) is
184
187
  the alternative whose *raw, unrounded* <rating-X/> is the second
185
- largest rating value across all alternatives.
188
+ largest rating value across all alternatives. Do not output anything.
186
189
 
187
190
  - If multiple alternatives share the second-largest raw rating, pick
188
191
  any one of them as <alternative-X/>; the resulting <distance/> and
189
192
  <percentage/> are unaffected by the choice, so the downstream output
190
- is deterministic.
193
+ is deterministic. Do not output anything.
191
194
 
192
195
  - Determine rating distance <distance/> between <alternative-K/> and
193
196
  <alternative-X/> from their *raw, unrounded* ratings by calculating:
@@ -203,6 +206,7 @@ multi-*criteria* decision matrix.
203
206
  (so a true zero tie with <distance/> = 0 falls into the
204
207
  *MULTIPLE BEST* branch below, and a non-zero gap with zero
205
208
  best falls into the *small distance* branch below).
209
+ Do not output anything.
206
210
 
207
211
  - By construction, <rating-K/> is the maximum rating across
208
212
  all alternatives, so <distance/> >= 0 always holds; using
@@ -210,7 +214,7 @@ multi-*criteria* decision matrix.
210
214
  regimes. Note that when <rating-K/> itself is negative, the
211
215
  denominator anchors to a poor best rating and small gaps can
212
216
  appear large; the all-negative regime is surfaced as a dedicated
213
- warning branch below.
217
+ warning branch below. Do not output anything.
214
218
 
215
219
  - If <percentage/> is less than 0.01 (i.e. <distance/> is
216
220
  effectively zero relative to abs(<rating-K/>)), stop the flow after
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: ase-task-list
3
- argument-hint: ""
3
+ argument-hint: "[-v|--verbose]"
4
4
  description: >
5
5
  List all available task ids.
6
6
  Use when user wants to see all tasks.
@@ -11,6 +11,7 @@ effort: low
11
11
 
12
12
  @${CLAUDE_SKILL_DIR}/../../meta/ase-persona.md
13
13
  @${CLAUDE_SKILL_DIR}/../../meta/ase-skill.md
14
+ @${CLAUDE_SKILL_DIR}/../../meta/ase-getopt.md
14
15
 
15
16
  Task List
16
17
  =========
@@ -19,10 +20,17 @@ Task List
19
20
  List Task Plans
20
21
  </skill>
21
22
 
22
- 1. Call the `task_list(verbose: true)` tool from the `ase` MCP service.
23
- The result is a structured object with a `tasks` array where each
24
- entry has an `id` field and an `mtime` field (formatted as
25
- `YYYY-MM-DD HH:MM`).
23
+ <expand name="getopt"
24
+ arg1="ase-task-list"
25
+ arg2="--verbose|-v">
26
+ $ARGUMENTS
27
+ </expand>
28
+
29
+ 1. Call the `task_list(verbose: <getopt-option-verbose/>)` tool from
30
+ the `ase` MCP service. The result is a structured object with a
31
+ `tasks` array where each entry has an `id` field, and -- if
32
+ <getopt-option-verbose/> is `true` -- additionally an `mtime` field
33
+ (formatted as `YYYY-MM-DD HH:MM`).
26
34
 
27
35
  2. If the `tasks` array is empty, output the following <template/>:
28
36
 
@@ -30,16 +38,33 @@ List Task Plans
30
38
  ⧉ **ASE**: ◉ tasks: *(none)*
31
39
  </template>
32
40
 
33
- Else, output the list of tasks with the following <template/>, where
34
- each <id/> and <mtime/> correspond to an entry in the task list:
41
+ Else, dispatch on <getopt-option-verbose/>:
35
42
 
36
- <template>
37
- **ASE**: tasks:
43
+ - If <getopt-option-verbose/> is `true`, output the list of tasks
44
+ with the following <template/>, where each <id/> and <mtime/>
45
+ correspond to an entry in the task list:
38
46
 
39
- | *Task Id* | *Last Modified* |
40
- |-----------|--------------------|
41
- | **<id/>** | `<mtime/>` |
42
- | [...] | [...] |
47
+ <template>
48
+ ⧉ **ASE**: ◉ tasks:
43
49
 
44
- </template>
50
+ | *Task Id* | *Last Modified* |
51
+ |-----------|--------------------|
52
+ | **<id/>** | `<mtime/>` |
53
+ | [...] | [...] |
54
+
55
+ </template>
56
+
57
+ - If <getopt-option-verbose/> is `false`, output the list of tasks
58
+ with the following <template/>, where each <id/> corresponds to
59
+ an entry in the task list:
60
+
61
+ <template>
62
+ ⧉ **ASE**: ◉ tasks:
63
+
64
+ | *Task Id* |
65
+ |-----------|
66
+ | **<id/>** |
67
+ | [...] |
68
+
69
+ </template>
45
70