@rse/ase 0.9.59 → 0.9.61
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-hook.js +45 -5
- package/dst/ase-markdown.js +1 -1
- package/dst/ase-meta.js +1 -1
- package/dst/ase-setup.js +1 -1
- package/dst/ase-statusline.js +1 -1
- package/package.json +12 -13
- package/plugin/.claude-plugin/plugin.json +1 -1
- package/plugin/.codex-plugin/plugin.json +1 -1
- package/plugin/.github/plugin/plugin.json +1 -1
- package/plugin/meta/ase-common-code.md +1 -1
- package/plugin/meta/ase-common-task.md +8 -8
- package/plugin/meta/ase-dialog.md +4 -2
- package/plugin/package.json +4 -4
- package/plugin/skills/ase-code-craft/SKILL.md +43 -9
- package/plugin/skills/ase-code-craft/help.md +13 -0
- package/plugin/skills/ase-code-edit/SKILL.md +492 -0
- package/plugin/skills/ase-code-edit/help.md +127 -0
- package/plugin/skills/ase-code-refactor/SKILL.md +7 -6
- package/plugin/skills/ase-code-resolve/SKILL.md +7 -6
- package/plugin/skills/ase-help-skill/catalog.md +1 -0
- package/plugin/skills/ase-sync-import/SKILL.md +2 -1
- package/plugin/skills/ase-sync-reconcile/SKILL.md +3 -1
- package/plugin/skills/ase-task-condense/SKILL.md +13 -13
- package/plugin/skills/ase-task-dissect/SKILL.md +6 -5
- package/plugin/skills/ase-task-edit/SKILL.md +42 -20
- package/plugin/skills/ase-task-edit/help.md +7 -0
- package/plugin/skills/ase-task-grill/SKILL.md +4 -4
- package/plugin/skills/ase-task-implement/SKILL.md +21 -10
- package/plugin/skills/ase-task-implement/help.md +4 -2
- package/plugin/skills/ase-task-preflight/SKILL.md +18 -4
- package/plugin/skills/ase-task-preflight/help.md +5 -1
- package/plugin/skills/ase-task-reboot/SKILL.md +1 -1
- package/plugin/skills/ase-task-view/SKILL.md +1 -2
- package/plugin/package-lock.json +0 -2890
package/dst/ase-hook.js
CHANGED
|
@@ -75,6 +75,10 @@ const toolInputSchema = v.object({
|
|
|
75
75
|
skill: v.optional(v.string()),
|
|
76
76
|
file_path: v.optional(v.string())
|
|
77
77
|
});
|
|
78
|
+
/* maximum tolerated age of an idle session directory: the session-end hook
|
|
79
|
+
removes it regularly, but a crashed or SIGKILLed agent leaves it behind
|
|
80
|
+
forever, so orphans are garbage-collected once they exceed this age */
|
|
81
|
+
const SESSION_MAX_AGE_MS = 7 * 24 * 60 * 60 * 1000;
|
|
78
82
|
/* CLI command "ase hook" */
|
|
79
83
|
export default class HookCommand {
|
|
80
84
|
log;
|
|
@@ -85,6 +89,40 @@ export default class HookCommand {
|
|
|
85
89
|
isValidSessionId(id) {
|
|
86
90
|
return /^[A-Za-z0-9._-]+$/.test(id);
|
|
87
91
|
}
|
|
92
|
+
/* resolve the base directory holding all per-session state */
|
|
93
|
+
sessionBaseDir() {
|
|
94
|
+
return path.join(os.homedir(), ".ase", "session");
|
|
95
|
+
}
|
|
96
|
+
/* garbage-collect orphaned session directories left behind by agents
|
|
97
|
+
which died before their session-end hook could run; a live session
|
|
98
|
+
keeps its directory's mtime current, as every tool call acquires a
|
|
99
|
+
lock file inside it, so plain age is a reliable liveness signal */
|
|
100
|
+
pruneStaleSessions(currentSessionId) {
|
|
101
|
+
const base = this.sessionBaseDir();
|
|
102
|
+
let entries;
|
|
103
|
+
try {
|
|
104
|
+
entries = fs.readdirSync(base, { withFileTypes: true });
|
|
105
|
+
}
|
|
106
|
+
catch (_e) {
|
|
107
|
+
/* best-effort: no base directory yet, or unreadable */
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
const deadline = Date.now() - SESSION_MAX_AGE_MS;
|
|
111
|
+
for (const entry of entries) {
|
|
112
|
+
if (!entry.isDirectory() || entry.name === currentSessionId)
|
|
113
|
+
continue;
|
|
114
|
+
const dir = path.join(base, entry.name);
|
|
115
|
+
try {
|
|
116
|
+
if (fs.statSync(dir).mtimeMs >= deadline)
|
|
117
|
+
continue;
|
|
118
|
+
fs.rmSync(dir, { recursive: true, force: true });
|
|
119
|
+
this.log.write("debug", `hook: pruned stale session directory: ${dir}`);
|
|
120
|
+
}
|
|
121
|
+
catch (_e) {
|
|
122
|
+
/* best-effort: ignore vanished or undeletable directories */
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
}
|
|
88
126
|
/* drain and discard the stdin event payload */
|
|
89
127
|
async drainStdin() {
|
|
90
128
|
await readStdin().catch(() => "");
|
|
@@ -176,14 +214,14 @@ export default class HookCommand {
|
|
|
176
214
|
try {
|
|
177
215
|
pkg = fs.readFileSync(filePkg, "utf8");
|
|
178
216
|
}
|
|
179
|
-
catch (
|
|
180
|
-
throw new Error(`failed to read plugin manifest: ${filePkg}
|
|
217
|
+
catch (err) {
|
|
218
|
+
throw new Error(`failed to read plugin manifest: ${filePkg}`, { cause: err });
|
|
181
219
|
}
|
|
182
220
|
try {
|
|
183
221
|
md = fs.readFileSync(fileMd, "utf8");
|
|
184
222
|
}
|
|
185
|
-
catch (
|
|
186
|
-
throw new Error(`failed to read constitution file: ${fileMd}
|
|
223
|
+
catch (err) {
|
|
224
|
+
throw new Error(`failed to read constitution file: ${fileMd}`, { cause: err });
|
|
187
225
|
}
|
|
188
226
|
/* determine own version */
|
|
189
227
|
const pkgObj = this.parseJSON(pkg, v.object({ version: v.optional(v.string()) }));
|
|
@@ -210,6 +248,8 @@ export default class HookCommand {
|
|
|
210
248
|
}));
|
|
211
249
|
/* determine session id */
|
|
212
250
|
const sessionId = this.pickSessionId(input);
|
|
251
|
+
/* garbage-collect orphaned session directories of previous agent runs */
|
|
252
|
+
this.pruneStaleSessions(sessionId);
|
|
213
253
|
/* establish config context (session-scoped only if a valid sessionId is present) */
|
|
214
254
|
const hasSession = this.isValidSessionId(sessionId);
|
|
215
255
|
const cfg = new Config("config", configSchema, this.log, hasSession ? parseScope(`session:${sessionId}`) : parseScope(undefined));
|
|
@@ -363,7 +403,7 @@ export default class HookCommand {
|
|
|
363
403
|
const sessionId = await this.readSessionIdFromStdin();
|
|
364
404
|
/* remove the session directory ~/.ase/session/<id> (only for a valid sessionId) */
|
|
365
405
|
if (this.isValidSessionId(sessionId)) {
|
|
366
|
-
const dir = path.join(
|
|
406
|
+
const dir = path.join(this.sessionBaseDir(), sessionId);
|
|
367
407
|
try {
|
|
368
408
|
fs.rmSync(dir, { recursive: true, force: true });
|
|
369
409
|
}
|
package/dst/ase-markdown.js
CHANGED
|
@@ -215,7 +215,7 @@ export class Markdown {
|
|
|
215
215
|
}
|
|
216
216
|
if (fence > 0 && (ch === "\r" || ch === "\n")) {
|
|
217
217
|
/* consume optional CR followed by mandatory LF */
|
|
218
|
-
let nl
|
|
218
|
+
let nl;
|
|
219
219
|
if (ch === "\r" && i + 1 < text.length && text[i + 1] === "\n") {
|
|
220
220
|
nl = "\r\n";
|
|
221
221
|
i += 2;
|
package/dst/ase-meta.js
CHANGED
|
@@ -41,7 +41,7 @@ export class Meta {
|
|
|
41
41
|
}
|
|
42
42
|
catch (err) {
|
|
43
43
|
const message = err instanceof Error ? err.message : String(err);
|
|
44
|
-
throw new Error(`meta: failed to read file: ${abs} (${message})
|
|
44
|
+
throw new Error(`meta: failed to read file: ${abs} (${message})`, { cause: err });
|
|
45
45
|
}
|
|
46
46
|
}
|
|
47
47
|
}
|
package/dst/ase-setup.js
CHANGED
|
@@ -47,7 +47,7 @@ export default class SetupCommand {
|
|
|
47
47
|
return false;
|
|
48
48
|
/* determine the npm global prefix and probe writability of the
|
|
49
49
|
directories that "npm -g" actually mutates */
|
|
50
|
-
let prefix
|
|
50
|
+
let prefix;
|
|
51
51
|
try {
|
|
52
52
|
const result = await execa("npm", ["prefix", "-g"], { stdio: "pipe" });
|
|
53
53
|
prefix = result.stdout.trim();
|
package/dst/ase-statusline.js
CHANGED
|
@@ -229,7 +229,7 @@ export default class StatuslineCommand {
|
|
|
229
229
|
}
|
|
230
230
|
catch (err) {
|
|
231
231
|
const message = err instanceof Error ? err.message : String(err);
|
|
232
|
-
throw new Error(`statusline: invalid JSON on stdin: ${message}
|
|
232
|
+
throw new Error(`statusline: invalid JSON on stdin: ${message}`, { cause: err });
|
|
233
233
|
}
|
|
234
234
|
/* normalize Copilot CLI's top-level "cwd" into the
|
|
235
235
|
"workspace.current_dir" structure shared with Anthropic Claude Code CLI */
|
package/package.json
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
"homepage": "https://ase.tools",
|
|
7
7
|
"repository": { "url": "git+https://github.com/rse/ase.git", "type": "git" },
|
|
8
8
|
"bugs": { "url": "https://github.com/rse/ase/issues" },
|
|
9
|
-
"version": "0.9.
|
|
9
|
+
"version": "0.9.61",
|
|
10
10
|
"license": "Apache-2.0",
|
|
11
11
|
"author": {
|
|
12
12
|
"name": "Dr. Ralf S. Engelschall",
|
|
@@ -16,22 +16,22 @@
|
|
|
16
16
|
"type": "module",
|
|
17
17
|
"bin": { "ase": "bin/ase" },
|
|
18
18
|
"devDependencies": {
|
|
19
|
-
"eslint": "9.
|
|
20
|
-
"@eslint/js": "
|
|
21
|
-
"@typescript-eslint/parser": "8.
|
|
22
|
-
"@typescript-eslint/eslint-plugin": "8.
|
|
19
|
+
"eslint": "10.9.0",
|
|
20
|
+
"@eslint/js": "10.0.1",
|
|
21
|
+
"@typescript-eslint/parser": "8.67.0",
|
|
22
|
+
"@typescript-eslint/eslint-plugin": "8.67.0",
|
|
23
|
+
"typescript-eslint": "8.67.0",
|
|
23
24
|
"eslint-plugin-promise": "7.3.0",
|
|
24
|
-
"
|
|
25
|
-
"
|
|
26
|
-
"globals": "17.9.0",
|
|
25
|
+
"neostandard": "0.14.0-next.1",
|
|
26
|
+
"globals": "17.11.0",
|
|
27
27
|
"typescript": "6.0.3",
|
|
28
28
|
|
|
29
29
|
"@rse/stx": "1.1.6",
|
|
30
30
|
"nodemon": "3.1.14",
|
|
31
31
|
"shx": "0.4.0",
|
|
32
32
|
|
|
33
|
-
"@types/node": "26.
|
|
34
|
-
"@types/luxon": "3.7.
|
|
33
|
+
"@types/node": "26.2.0",
|
|
34
|
+
"@types/luxon": "3.7.5",
|
|
35
35
|
"@types/which": "3.0.4",
|
|
36
36
|
"@types/update-notifier": "6.0.8",
|
|
37
37
|
"@types/shell-quote": "1.7.5",
|
|
@@ -42,7 +42,7 @@
|
|
|
42
42
|
},
|
|
43
43
|
"dependencies": {
|
|
44
44
|
"commander": "15.0.0",
|
|
45
|
-
"@dotenvx/dotenvx": "2.
|
|
45
|
+
"@dotenvx/dotenvx": "2.21.0",
|
|
46
46
|
"yaml": "2.9.0",
|
|
47
47
|
"valibot": "1.4.2",
|
|
48
48
|
"execa": "10.0.1",
|
|
@@ -72,9 +72,8 @@
|
|
|
72
72
|
},
|
|
73
73
|
"engines": {
|
|
74
74
|
"npm": ">=10.0.0",
|
|
75
|
-
"node": ">=22.
|
|
75
|
+
"node": ">=22.13.0"
|
|
76
76
|
},
|
|
77
|
-
"upd": [ "!eslint", "!@eslint/js" ],
|
|
78
77
|
"files": [
|
|
79
78
|
"dst/**/*",
|
|
80
79
|
"bin/**/*",
|
|
@@ -138,7 +138,7 @@ Set <args>--int-reuse-task</args>.
|
|
|
138
138
|
<template/> and then *STOP*. Do *not* implement the plan.
|
|
139
139
|
|
|
140
140
|
<template>
|
|
141
|
-
⧉ **ASE**: ◉ task: **<ase-task-id/>**,
|
|
141
|
+
⧉ **ASE**: ◉ task: **<ase-task-id/>**, ▶ status: **plan finalized -- done**
|
|
142
142
|
</template>
|
|
143
143
|
</if>
|
|
144
144
|
|
|
@@ -83,16 +83,14 @@ Task Skill Common Steps
|
|
|
83
83
|
|
|
84
84
|
- If <text/> starts with `ERROR:` or `WARNING:`:
|
|
85
85
|
Set <task-content></task-content> (set task content to empty).
|
|
86
|
-
Set <words/> to "0".
|
|
87
86
|
|
|
88
87
|
- If <text/> does NOT start with `ERROR:` and NOT with `WARNING:`:
|
|
89
88
|
Set <task-content><text/></task-content> (set task content to text).
|
|
90
|
-
Calculate the number of words <words/> of <task-content/>.
|
|
91
89
|
|
|
92
90
|
Only output the following <template/>:
|
|
93
91
|
|
|
94
92
|
<template>
|
|
95
|
-
⧉ **ASE**: ◉ task: **<ase-task-id/>**,
|
|
93
|
+
⧉ **ASE**: ◉ task: **<ase-task-id/>**, ▶ status: **<status/>**
|
|
96
94
|
</template>
|
|
97
95
|
|
|
98
96
|
</define>
|
|
@@ -109,16 +107,18 @@ had no `Created:` frontmatter key), set
|
|
|
109
107
|
(fall back to the modified timestamp). Re-insert the current
|
|
110
108
|
<ase-task-id/>, the original <timestamp-created/>, and the
|
|
111
109
|
refreshed <timestamp-modified/> into the frontmatter keys `Id:`,
|
|
112
|
-
`Created:`, and `Modified:` of <task-content
|
|
113
|
-
the number of words <words/> of <task-content/>.
|
|
110
|
+
`Created:`, and `Modified:` of <task-content/>.
|
|
114
111
|
|
|
115
112
|
Call the `ase_task_save(id: "<ase-task-id/>", text:
|
|
116
113
|
"<task-content/>")` tool of the `ase` MCP server to save the task
|
|
117
|
-
plan content in its *authoring form*.
|
|
114
|
+
plan content in its *authoring form*. This `ase_task_save` MCP
|
|
115
|
+
tool call is the *only* permitted way to persist the task plan --
|
|
116
|
+
you *MUST* *NEVER* write the plan file via `Write`/`Edit` or by
|
|
117
|
+
executing a shell command. Do not output anything
|
|
118
118
|
related to this MCP call except the following <template/>:
|
|
119
119
|
|
|
120
120
|
<template>
|
|
121
|
-
⧉ **ASE**: ◉ task: **<ase-task-id/>**,
|
|
121
|
+
⧉ **ASE**: ◉ task: **<ase-task-id/>**, ▶ status: **<arg1/>**
|
|
122
122
|
</template>
|
|
123
123
|
|
|
124
124
|
</define>
|
|
@@ -169,7 +169,7 @@ Only output the following <template/> and then call the tool
|
|
|
169
169
|
stop processing the current skill once the `Skill` tool was used.
|
|
170
170
|
|
|
171
171
|
<template>
|
|
172
|
-
⧉ **ASE**: ◉ task: **<ase-task-id/>**,
|
|
172
|
+
⧉ **ASE**: ◉ task: **<ase-task-id/>**, ▶ status: **<arg2/>**
|
|
173
173
|
</template>
|
|
174
174
|
|
|
175
175
|
</define>
|
|
@@ -102,8 +102,10 @@ following procedure:
|
|
|
102
102
|
</ase-tpl-boxed>
|
|
103
103
|
</text>
|
|
104
104
|
|
|
105
|
-
If <n/> is less than 2
|
|
106
|
-
|
|
105
|
+
If <n/> is less than 2 -- or less than 1 when <opts/> contains
|
|
106
|
+
`--other` and does *not* contain `--no-other`, as the free-text
|
|
107
|
+
path then complements a single answer option:
|
|
108
|
+
Set <result>ERROR: custom-dialog requires 2-9 (with free-text: 1-9) answer lines, got <n/></result>
|
|
107
109
|
and *SKIP* the following step 2.2 and continue with step 2.3 dispatch.
|
|
108
110
|
|
|
109
111
|
2. Output the following <template/>, end the current turn, wait for the
|
package/plugin/package.json
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
"homepage": "https://ase.tools",
|
|
7
7
|
"repository": { "url": "git+https://github.com/rse/ase.git", "type": "git" },
|
|
8
8
|
"bugs": { "url": "https://github.com/rse/ase/issues" },
|
|
9
|
-
"version": "0.9.
|
|
9
|
+
"version": "0.9.61",
|
|
10
10
|
"license": "Apache-2.0",
|
|
11
11
|
"author": {
|
|
12
12
|
"name": "Dr. Ralf S. Engelschall",
|
|
@@ -17,13 +17,13 @@
|
|
|
17
17
|
"@rse/stx": "1.1.6",
|
|
18
18
|
"markdownlint": "0.41.1",
|
|
19
19
|
"markdownlint-cli2": "0.23.2",
|
|
20
|
-
"eslint": "10.
|
|
20
|
+
"eslint": "10.9.0",
|
|
21
21
|
"@eslint/markdown": "8.0.3",
|
|
22
|
-
"eslint-markdown": "0.
|
|
22
|
+
"eslint-markdown": "0.14.0"
|
|
23
23
|
},
|
|
24
24
|
"engines": {
|
|
25
25
|
"npm": ">=10.0.0",
|
|
26
|
-
"node": ">=22.
|
|
26
|
+
"node": ">=22.13.0"
|
|
27
27
|
},
|
|
28
28
|
"scripts": {
|
|
29
29
|
"start": "stx -v4 -l warning -c etc/stx.conf"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: ase-code-craft
|
|
3
|
-
argument-hint: "[--help|-h] [--auto|-a] [--dry|-d] [--direct|-D] [--quick|-Q] [--next|-n <option>[,...]] [<task-id>:] <feature>"
|
|
3
|
+
argument-hint: "[--help|-h] [--auto|-a] [--dry|-d] [--direct|-D] [--interactive|-i] [--quick|-Q] [--next|-n <option>[,...]] [<task-id>:] <feature>"
|
|
4
4
|
description: >
|
|
5
5
|
Craft Source Code:
|
|
6
6
|
Use when user wants to "create", "add", or "craft" a new feature from scratch.
|
|
@@ -24,7 +24,7 @@ Craft Source Code
|
|
|
24
24
|
|
|
25
25
|
<expand name="getopt"
|
|
26
26
|
arg1="ase-code-craft"
|
|
27
|
-
arg2="--auto|-a --dry|-d --direct|-D --quick|-Q --next|-n=(none|DONE|EDIT|GRILL|PREFLIGHT|IMPLEMENT)...">
|
|
27
|
+
arg2="--auto|-a --dry|-d --direct|-D --interactive|-i --quick|-Q --next|-n=(none|DONE|EDIT|GRILL|PREFLIGHT|IMPLEMENT)...">
|
|
28
28
|
$ARGUMENTS
|
|
29
29
|
</expand>
|
|
30
30
|
|
|
@@ -34,6 +34,11 @@ to `true`, <getopt-option-dry/> to `true`, and <getopt-option-next/> to
|
|
|
34
34
|
`IMPLEMENT,DELETE`. Do not output anything.
|
|
35
35
|
</if>
|
|
36
36
|
|
|
37
|
+
<if condition="<getopt-option-interactive/> is equal `true`">
|
|
38
|
+
The `--interactive`/`-i` flag *implies* the `--direct`/`-D` mode: set
|
|
39
|
+
<getopt-option-direct/> to `true`. Do not output anything.
|
|
40
|
+
</if>
|
|
41
|
+
|
|
37
42
|
<objective>
|
|
38
43
|
From scratch *craft* the following feature:
|
|
39
44
|
<feature><getopt-arguments/></feature>
|
|
@@ -48,8 +53,9 @@ Procedure
|
|
|
48
53
|
|
|
49
54
|
<if condition="<getopt-option-direct/> is not equal to 'true'">
|
|
50
55
|
You *MUST* *NOT* call `Edit`, `Write`, `NotebookEdit`, or any
|
|
51
|
-
filesystem-modifying tool
|
|
52
|
-
|
|
56
|
+
filesystem-modifying tool, nor execute any filesystem-modifying
|
|
57
|
+
shell command, during this entire skill. The *only* permitted way
|
|
58
|
+
to persist artifacts is via the `ase_task_save(...)` MCP tool.
|
|
53
59
|
</if>
|
|
54
60
|
<else>
|
|
55
61
|
The `--direct`/`-D` mode applies the crafting *in place*, so STEP 4
|
|
@@ -162,7 +168,35 @@ crafting actually demands, and you *MUST* *NOT* call
|
|
|
162
168
|
⧉ **ASE**: ◉ task: **<ase-task-id/>**, ▶ status: **changes directly applied**
|
|
163
169
|
</template>
|
|
164
170
|
|
|
165
|
-
3.
|
|
171
|
+
3. <if condition="<getopt-option-interactive/> is equal `true`">
|
|
172
|
+
Enter the *interactive crafting loop*:
|
|
173
|
+
|
|
174
|
+
<while condition="`true`">
|
|
175
|
+
|
|
176
|
+
1. In the following, you *MUST* *NOT* use your built-in
|
|
177
|
+
<user-dialog-tool/> tool! Instead, you *MUST* just show a
|
|
178
|
+
custom dialog according to the expanded `custom-dialog`
|
|
179
|
+
definition. You *MUST* closely follow this definition.
|
|
180
|
+
|
|
181
|
+
Ask the user for the next change with the following
|
|
182
|
+
custom dialog:
|
|
183
|
+
|
|
184
|
+
<expand name="custom-dialog" arg1="--other">
|
|
185
|
+
Next Change: What is the next change to craft?
|
|
186
|
+
DONE: Finish the interactive crafting loop
|
|
187
|
+
</expand>
|
|
188
|
+
|
|
189
|
+
2. If <result/> is `DONE` or `CANCEL`, <break/>.
|
|
190
|
+
|
|
191
|
+
3. Otherwise <result/> has the format `OTHER: <text/>`: set
|
|
192
|
+
<feature/> to <text/>, then directly craft it and report
|
|
193
|
+
it exactly as specified by the items 1 and 2 above
|
|
194
|
+
(including the CHANGELOG.md entry).
|
|
195
|
+
|
|
196
|
+
</while>
|
|
197
|
+
</if>
|
|
198
|
+
|
|
199
|
+
4. Then *IMMEDIATELY* *STOP* all further skill processing. You
|
|
166
200
|
*MUST* *NOT* output anything else in this STEP 4 or after it --
|
|
167
201
|
*independent* of <ase-project-boxing/>, whose exposure rules
|
|
168
202
|
are explicitly *overridden* here. Especially, do not output a
|
|
@@ -207,16 +241,16 @@ crafting actually demands, and you *MUST* *NOT* call
|
|
|
207
241
|
`ase` MCP server and use the `text` field of its response for
|
|
208
242
|
<timestamp-created/> and <timestamp-modified/> information. Then
|
|
209
243
|
insert the current <ase-task-id/>, <timestamp-created/>,
|
|
210
|
-
<timestamp-modified/>, and <task-kind/> information
|
|
211
|
-
the number of words <words/> of <task-content/>.
|
|
244
|
+
<timestamp-modified/>, and <task-kind/> information.
|
|
212
245
|
|
|
213
246
|
3. You then *MUST* *save* the resulting plan content with the
|
|
214
|
-
`ase_task_save(id: "<ase-task-id/>", text: "<task-content/>")
|
|
247
|
+
`ase_task_save(id: "<ase-task-id/>", text: "<task-content/>")`
|
|
248
|
+
MCP tool call only -- *NEVER* by executing a shell command.
|
|
215
249
|
|
|
216
250
|
4. Output a hint with the following <template/>:
|
|
217
251
|
|
|
218
252
|
<template>
|
|
219
|
-
⧉ **ASE**: ◉ task: **<ase-task-id/>**,
|
|
253
|
+
⧉ **ASE**: ◉ task: **<ase-task-id/>**, ▶ status: **plan created**
|
|
220
254
|
</template>
|
|
221
255
|
|
|
222
256
|
5. Directly pass-through control to the next skill:
|
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
[`--auto`|`-a`]
|
|
11
11
|
[`--dry`|`-d`]
|
|
12
12
|
[`--direct`|`-D`]
|
|
13
|
+
[`--interactive`|`-i`]
|
|
13
14
|
[`--quick`|`-Q`]
|
|
14
15
|
[`--next`|`-n` *option*[,...]]
|
|
15
16
|
[*task-id*:] *feature*
|
|
@@ -51,6 +52,12 @@ entirely and applies the change set to the affected artifacts itself.
|
|
|
51
52
|
`--next` have no effect, as neither approaches are proposed nor a
|
|
52
53
|
plan is composed.
|
|
53
54
|
|
|
55
|
+
`--interactive`|`-i`:
|
|
56
|
+
Craft *interactively*: implies `--direct` and, once the initial
|
|
57
|
+
*feature* has been applied, repeatedly asks for the *next change*
|
|
58
|
+
with a free-text dialog and immediately applies it in place, too,
|
|
59
|
+
until the user stops the loop by answering `DONE`.
|
|
60
|
+
|
|
54
61
|
`--quick`|`-Q`:
|
|
55
62
|
Shorthand alias for `-a -d -n IMPLEMENT,DELETE`: automatically pick
|
|
56
63
|
the recommended feature approach, compose the plan *without* the
|
|
@@ -96,6 +103,12 @@ Craft a feature under a named task and directly hand off to implementation:
|
|
|
96
103
|
❯ /ase-code-craft --next IMPLEMENT auth: add JWT authentication middleware
|
|
97
104
|
```
|
|
98
105
|
|
|
106
|
+
Craft interactively, applying one change after the other in place:
|
|
107
|
+
|
|
108
|
+
```text
|
|
109
|
+
❯ /ase-code-craft -i add a --verbose option to the CLI
|
|
110
|
+
```
|
|
111
|
+
|
|
99
112
|
## SEE ALSO
|
|
100
113
|
|
|
101
114
|
[`ase-code-refactor`](../ase-code-refactor/help.md), [`ase-code-resolve`](../ase-code-resolve/help.md), [`ase-task-edit`](../ase-task-edit/help.md),
|