@rse/ase 0.9.30 → 0.9.32
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-artifact.js +6 -7
- package/dst/ase-hook.js +50 -22
- package/dst/ase-meta.js +65 -0
- package/dst/ase-stdout.js +18 -0
- package/dst/ase-task.js +6 -7
- package/dst/ase.js +2 -0
- package/package.json +1 -1
- 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-format-arch.md +2 -2
- package/plugin/meta/ase-skill.md +2 -2
- package/plugin/meta/ase-tenets.md +1 -1
- package/plugin/package.json +1 -1
- package/plugin/skills/ase-meta-diaboli/help.md +2 -2
- package/plugin/skills/ase-task-grill/SKILL.md +1 -1
package/dst/ase-artifact.js
CHANGED
|
@@ -10,6 +10,7 @@ import { isScalar } from "yaml";
|
|
|
10
10
|
import { z } from "zod";
|
|
11
11
|
import { Config, configSchema } from "./ase-config.js";
|
|
12
12
|
import { Task } from "./ase-task.js";
|
|
13
|
+
import { writeStdout } from "./ase-stdout.js";
|
|
13
14
|
/* the recognized artifact kinds, in descending precedence order;
|
|
14
15
|
"othr" is the implicit catch-all and is always resolved last */
|
|
15
16
|
export const artifactKinds = ["spec", "arch", "code", "docs", "infr", "othr"];
|
|
@@ -223,17 +224,16 @@ export default class ArtifactCommand {
|
|
|
223
224
|
.description("Resolve one or more artifact kinds to project-relative file paths")
|
|
224
225
|
.option("--kind <kinds>", "comma-separated list of artifact kinds " +
|
|
225
226
|
`(${artifactKinds.join("|")})`, artifactKinds.join(","))
|
|
226
|
-
.action((opts) => {
|
|
227
|
+
.action(async (opts) => {
|
|
227
228
|
const kinds = opts.kind.split(",").map((k) => Artifact.validateKind(k.trim()));
|
|
228
229
|
const result = Artifact.list(this.log, kinds);
|
|
229
230
|
const single = result.length === 1;
|
|
230
231
|
for (const { kind, files } of result) {
|
|
231
232
|
if (!single)
|
|
232
|
-
|
|
233
|
+
await writeStdout(`# ${kind}:\n`);
|
|
233
234
|
for (const file of files)
|
|
234
|
-
|
|
235
|
+
await writeStdout(`- ${file}\n`);
|
|
235
236
|
}
|
|
236
|
-
process.exit(0);
|
|
237
237
|
});
|
|
238
238
|
/* register CLI sub-command "ase artifact name" */
|
|
239
239
|
artifact
|
|
@@ -242,10 +242,9 @@ export default class ArtifactCommand {
|
|
|
242
242
|
.argument("<filename>", "base-relative filename within the kind's basedir")
|
|
243
243
|
.option("--kind <kind>", "artifact kind " +
|
|
244
244
|
`(${configuredKinds.join("|")})`, "code")
|
|
245
|
-
.action((filename, opts) => {
|
|
245
|
+
.action(async (filename, opts) => {
|
|
246
246
|
const kind = Artifact.validateKind(opts.kind.trim());
|
|
247
|
-
|
|
248
|
-
process.exit(0);
|
|
247
|
+
await writeStdout(`${Artifact.name(this.log, kind, filename)}\n`);
|
|
249
248
|
});
|
|
250
249
|
}
|
|
251
250
|
}
|
package/dst/ase-hook.js
CHANGED
|
@@ -12,6 +12,7 @@ import getStdin from "get-stdin";
|
|
|
12
12
|
import * as v from "valibot";
|
|
13
13
|
import Version from "./ase-version.js";
|
|
14
14
|
import { Config, configSchema, parseScope } from "./ase-config.js";
|
|
15
|
+
import { writeStdout } from "./ase-stdout.js";
|
|
15
16
|
const addonMcpServers = [
|
|
16
17
|
"chat-alibaba-qwen",
|
|
17
18
|
"chat-deepseek",
|
|
@@ -87,18 +88,6 @@ export default class HookCommand {
|
|
|
87
88
|
async drainStdin() {
|
|
88
89
|
await this.readStdin();
|
|
89
90
|
}
|
|
90
|
-
/* write to stdout and resolve only once it has been fully
|
|
91
|
-
flushed to the underlying file descriptor */
|
|
92
|
-
writeStdout(text) {
|
|
93
|
-
return new Promise((resolve, reject) => {
|
|
94
|
-
process.stdout.write(text, (err) => {
|
|
95
|
-
if (err)
|
|
96
|
-
reject(err);
|
|
97
|
-
else
|
|
98
|
-
resolve();
|
|
99
|
-
});
|
|
100
|
-
});
|
|
101
|
-
}
|
|
102
91
|
/* best-effort JSON parse with valibot schema validation: returns
|
|
103
92
|
an empty object on blank input, malformed JSON, or schema
|
|
104
93
|
mismatch, so callers can treat the result uniformly. Extra
|
|
@@ -145,9 +134,9 @@ export default class HookCommand {
|
|
|
145
134
|
return this.expandReferences(content, path.dirname(abs), next);
|
|
146
135
|
});
|
|
147
136
|
}
|
|
148
|
-
/*
|
|
149
|
-
|
|
150
|
-
|
|
137
|
+
/* determine the plugin root directory (the environment variable
|
|
138
|
+
carrying it differs per tool), throwing if it cannot be found */
|
|
139
|
+
pluginRoot(tool) {
|
|
151
140
|
let pluginRootVars;
|
|
152
141
|
if (tool === "copilot")
|
|
153
142
|
pluginRootVars = ["COPILOT_PLUGIN_ROOT"];
|
|
@@ -163,6 +152,23 @@ export default class HookCommand {
|
|
|
163
152
|
}
|
|
164
153
|
if (pluginRoot === "")
|
|
165
154
|
throw new Error(`${pluginRootVars.join("/")} environment variable is not set`);
|
|
155
|
+
return pluginRoot;
|
|
156
|
+
}
|
|
157
|
+
/* determine the plugin root directory like "pluginRoot", but return
|
|
158
|
+
an empty string instead of throwing, so callers on the hot path of
|
|
159
|
+
a tool-approval decision can silently decline to auto-approve */
|
|
160
|
+
pluginRootSafe(tool) {
|
|
161
|
+
try {
|
|
162
|
+
return this.pluginRoot(tool);
|
|
163
|
+
}
|
|
164
|
+
catch (_e) {
|
|
165
|
+
return "";
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
/* handler for "ase hook session-start" (all tools) */
|
|
169
|
+
async doSessionStart(tool) {
|
|
170
|
+
/* determine plugin root (env var name differs per tool) */
|
|
171
|
+
const pluginRoot = this.pluginRoot(tool);
|
|
166
172
|
/* determine path to external files */
|
|
167
173
|
const filePkg = path.join(pluginRoot, ".claude-plugin", "plugin.json");
|
|
168
174
|
const fileMd = path.join(pluginRoot, "meta", "ase-constitution.md");
|
|
@@ -251,6 +257,7 @@ export default class HookCommand {
|
|
|
251
257
|
const envFile = tool === "claude" ? (process.env.CLAUDE_ENV_FILE ?? "") : "";
|
|
252
258
|
if (envFile !== "") {
|
|
253
259
|
const script = `export ASE_VERSION=${quote([versionCurrentPlugin])}\n` +
|
|
260
|
+
`export ASE_PLUGIN_ROOT=${quote([pluginRoot])}\n` +
|
|
254
261
|
`export ASE_USER_ID=${quote([userId])}\n` +
|
|
255
262
|
`export ASE_PROJECT_ID=${quote([projectId])}\n` +
|
|
256
263
|
`export ASE_TASK_ID=${quote([taskId])}\n` +
|
|
@@ -263,6 +270,7 @@ export default class HookCommand {
|
|
|
263
270
|
md =
|
|
264
271
|
`<ase-version>${versionCurrentPlugin}</ase-version>\n` +
|
|
265
272
|
`<ase-version-hint>${versionHint}</ase-version-hint>\n` +
|
|
273
|
+
`<ase-plugin-root>${pluginRoot}</ase-plugin-root>\n` +
|
|
266
274
|
`<ase-persona-style>${persona}</ase-persona-style>\n` +
|
|
267
275
|
`<ase-user-id>${userId}</ase-user-id>\n` +
|
|
268
276
|
`<ase-project-id>${projectId}</ase-project-id>\n` +
|
|
@@ -299,7 +307,7 @@ export default class HookCommand {
|
|
|
299
307
|
running headless -- mirroring the constitution box condition) */
|
|
300
308
|
if ((tool === "claude" || tool === "codex") && headless !== "true")
|
|
301
309
|
payload.systemMessage = banner;
|
|
302
|
-
await
|
|
310
|
+
await writeStdout(JSON.stringify(payload));
|
|
303
311
|
return 0;
|
|
304
312
|
}
|
|
305
313
|
/* publish the agent activity marker to tmux as a per-pane user
|
|
@@ -379,6 +387,23 @@ export default class HookCommand {
|
|
|
379
387
|
return "";
|
|
380
388
|
}
|
|
381
389
|
}
|
|
390
|
+
/* determine whether a "Read" target "filePath" resolves to a
|
|
391
|
+
location inside the plugin root, so the recurring loads of ASE
|
|
392
|
+
skill include files (e.g. "@${CLAUDE_SKILL_DIR}/../../meta/...")
|
|
393
|
+
can be auto-approved instead of prompting the user on every skill
|
|
394
|
+
invocation. The path is normalized and compared with a trailing
|
|
395
|
+
separator to prevent a sibling directory sharing the root's name
|
|
396
|
+
prefix (or a "../" escape) from being mistaken for a descendant. */
|
|
397
|
+
isUnderPluginRoot(tool, filePath) {
|
|
398
|
+
if (filePath === "")
|
|
399
|
+
return false;
|
|
400
|
+
const pluginRoot = this.pluginRootSafe(tool);
|
|
401
|
+
if (pluginRoot === "")
|
|
402
|
+
return false;
|
|
403
|
+
const root = path.resolve(pluginRoot) + path.sep;
|
|
404
|
+
const abs = path.resolve(filePath);
|
|
405
|
+
return (abs + path.sep).startsWith(root);
|
|
406
|
+
}
|
|
382
407
|
/* the edit-capable skills whose active state lets the pre-tool-use
|
|
383
408
|
hook auto-approve subsequent "Edit" invocations */
|
|
384
409
|
editCapableSkills = ["ase-code-lint", "ase-docs-proofread"];
|
|
@@ -387,7 +412,7 @@ export default class HookCommand {
|
|
|
387
412
|
reason. The input field names and value shapes differ between
|
|
388
413
|
tools, but the decision logic is shared by the "pre-tool-use" and
|
|
389
414
|
"permission-request" handlers. */
|
|
390
|
-
decideApproval(spec, input) {
|
|
415
|
+
decideApproval(tool, spec, input) {
|
|
391
416
|
const toolName = typeof input[spec.toolNameField] === "string" ?
|
|
392
417
|
input[spec.toolNameField] : "";
|
|
393
418
|
let toolInput = {};
|
|
@@ -395,7 +420,8 @@ export default class HookCommand {
|
|
|
395
420
|
if (spec.toolInputIsString && typeof rawInput === "string")
|
|
396
421
|
toolInput = this.parseJSON(rawInput, v.object({
|
|
397
422
|
command: v.optional(v.string()),
|
|
398
|
-
skill: v.optional(v.string())
|
|
423
|
+
skill: v.optional(v.string()),
|
|
424
|
+
file_path: v.optional(v.string())
|
|
399
425
|
}));
|
|
400
426
|
else if (!spec.toolInputIsString && typeof rawInput === "object" && rawInput !== null)
|
|
401
427
|
toolInput = rawInput;
|
|
@@ -407,6 +433,8 @@ export default class HookCommand {
|
|
|
407
433
|
return { approve: true, reason: "ASE MCP tool invocation auto-approved" };
|
|
408
434
|
else if (spec.addonMcpToolNamePattern.test(toolName))
|
|
409
435
|
return { approve: true, reason: "ASE addon MCP tool invocation auto-approved" };
|
|
436
|
+
else if (toolName === "Read" && this.isUnderPluginRoot(tool, toolInput.file_path ?? ""))
|
|
437
|
+
return { approve: true, reason: "ASE plugin file read auto-approved" };
|
|
410
438
|
else if (toolName === "Edit") {
|
|
411
439
|
const sessionId = this.pickSessionId(input);
|
|
412
440
|
const activeSkill = this.readActiveSkill(sessionId);
|
|
@@ -435,7 +463,7 @@ export default class HookCommand {
|
|
|
435
463
|
if (spec.approvalEvent !== "PreToolUse")
|
|
436
464
|
return 0;
|
|
437
465
|
/* determine whether to auto-approve the tool invocation */
|
|
438
|
-
const { approve, reason } = this.decideApproval(spec, input);
|
|
466
|
+
const { approve, reason } = this.decideApproval(tool, spec, input);
|
|
439
467
|
/* emit permission decision (or stay silent to defer to default flow).
|
|
440
468
|
Claude Code expects the decision nested in "hookSpecificOutput";
|
|
441
469
|
Copilot CLI expects flat top-level fields. */
|
|
@@ -450,7 +478,7 @@ export default class HookCommand {
|
|
|
450
478
|
"permissionDecision": "allow",
|
|
451
479
|
"permissionDecisionReason": reason
|
|
452
480
|
};
|
|
453
|
-
await
|
|
481
|
+
await writeStdout(JSON.stringify(payload));
|
|
454
482
|
}
|
|
455
483
|
return 0;
|
|
456
484
|
}
|
|
@@ -469,7 +497,7 @@ export default class HookCommand {
|
|
|
469
497
|
sessionId: v.optional(v.string())
|
|
470
498
|
}));
|
|
471
499
|
/* determine whether to auto-approve the tool invocation */
|
|
472
|
-
const { approve } = this.decideApproval(spec, input);
|
|
500
|
+
const { approve } = this.decideApproval(tool, spec, input);
|
|
473
501
|
/* emit the Codex "PermissionRequest" approval decision */
|
|
474
502
|
if (approve) {
|
|
475
503
|
const payload = {
|
|
@@ -478,7 +506,7 @@ export default class HookCommand {
|
|
|
478
506
|
"decision": { "behavior": "allow" }
|
|
479
507
|
}
|
|
480
508
|
};
|
|
481
|
-
await
|
|
509
|
+
await writeStdout(JSON.stringify(payload));
|
|
482
510
|
}
|
|
483
511
|
return 0;
|
|
484
512
|
}
|
package/dst/ase-meta.js
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/*
|
|
2
|
+
** Agentic Software Engineering (ASE)
|
|
3
|
+
** Copyright (c) 2025-2026 Dr. Ralf S. Engelschall <rse@engelschall.com>
|
|
4
|
+
** Licensed under Apache 2.0 <https://spdx.org/licenses/Apache-2.0>
|
|
5
|
+
*/
|
|
6
|
+
import path from "node:path";
|
|
7
|
+
import fs from "node:fs";
|
|
8
|
+
import { fileURLToPath } from "node:url";
|
|
9
|
+
import { writeStdout } from "./ase-stdout.js";
|
|
10
|
+
/* reusable functionality: resolve and read plugin "meta/" files */
|
|
11
|
+
export class Meta {
|
|
12
|
+
/* determine the plugin "meta/" directory; the build process copies
|
|
13
|
+
the sibling "plugin/" tree into the tool package (see the "copy
|
|
14
|
+
plugin directory into package for bundling" build step), so a
|
|
15
|
+
bundled "<pkgdir>/plugin/meta/" is always available right next to
|
|
16
|
+
the compiled tool, independent of any environment variables */
|
|
17
|
+
static dir() {
|
|
18
|
+
const pkgdir = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..");
|
|
19
|
+
return path.join(pkgdir, "plugin", "meta");
|
|
20
|
+
}
|
|
21
|
+
/* resolve a single requested meta name to an absolute path within
|
|
22
|
+
the "meta/" directory; the name is reduced to its basename to
|
|
23
|
+
reject path traversal and absolute paths, then expanded into the
|
|
24
|
+
canonical "ase-<name>.md" file name (the "ase-" prefix and ".md"
|
|
25
|
+
extension are added when not already present) */
|
|
26
|
+
static resolve(name) {
|
|
27
|
+
let base = path.basename(name.replace(/\\/g, "/"));
|
|
28
|
+
if (base === "" || base === "." || base === "..")
|
|
29
|
+
throw new Error(`meta: invalid file name "${name}"`);
|
|
30
|
+
if (path.extname(base) === "")
|
|
31
|
+
base = `${base}.md`;
|
|
32
|
+
if (!base.startsWith("ase-"))
|
|
33
|
+
base = `ase-${base}`;
|
|
34
|
+
return path.join(Meta.dir(), base);
|
|
35
|
+
}
|
|
36
|
+
/* read the contents of a single requested meta file */
|
|
37
|
+
static read(name) {
|
|
38
|
+
const abs = Meta.resolve(name);
|
|
39
|
+
try {
|
|
40
|
+
return fs.readFileSync(abs, "utf8");
|
|
41
|
+
}
|
|
42
|
+
catch (_e) {
|
|
43
|
+
throw new Error(`meta: failed to read file: ${abs}`);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
/* CLI command "ase meta" */
|
|
48
|
+
export default class MetaCommand {
|
|
49
|
+
log;
|
|
50
|
+
constructor(log) {
|
|
51
|
+
this.log = log;
|
|
52
|
+
}
|
|
53
|
+
/* register command */
|
|
54
|
+
register(program) {
|
|
55
|
+
program
|
|
56
|
+
.command("meta")
|
|
57
|
+
.description("Output the contents of one or more plugin meta files")
|
|
58
|
+
.argument("<name...>", "meta file name(s) (\"ase-\" prefix and \".md\" extension optional)")
|
|
59
|
+
.action(async (names) => {
|
|
60
|
+
this.log.write("debug", `meta: reading ${names.length} file(s)`);
|
|
61
|
+
for (const name of names)
|
|
62
|
+
await writeStdout(Meta.read(name));
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/*
|
|
2
|
+
** Agentic Software Engineering (ASE)
|
|
3
|
+
** Copyright (c) 2025-2026 Dr. Ralf S. Engelschall <rse@engelschall.com>
|
|
4
|
+
** Licensed under Apache 2.0 <https://spdx.org/licenses/Apache-2.0>
|
|
5
|
+
*/
|
|
6
|
+
/* write a string to stdout, awaiting the write callback which only
|
|
7
|
+
fires once the data has been flushed to the underlying pipe, so a
|
|
8
|
+
subsequent "process.exit" cannot truncate the output */
|
|
9
|
+
export const writeStdout = (text) => {
|
|
10
|
+
return new Promise((resolve, reject) => {
|
|
11
|
+
process.stdout.write(text, (err) => {
|
|
12
|
+
if (err)
|
|
13
|
+
reject(err);
|
|
14
|
+
else
|
|
15
|
+
resolve();
|
|
16
|
+
});
|
|
17
|
+
});
|
|
18
|
+
};
|
package/dst/ase-task.js
CHANGED
|
@@ -12,6 +12,7 @@ import { isScalar } from "yaml";
|
|
|
12
12
|
import { z } from "zod";
|
|
13
13
|
import { Config, configSchema, parseScope } from "./ase-config.js";
|
|
14
14
|
import { Markdown } from "./ase-markdown.js";
|
|
15
|
+
import { writeStdout } from "./ase-stdout.js";
|
|
15
16
|
/* reusable functionality: persisted task plans under
|
|
16
17
|
<project>/<basedir>/TASK-<id>.md (driven by the
|
|
17
18
|
"project.artifact.task.{basedir,files}" configuration) */
|
|
@@ -269,25 +270,23 @@ export default class TaskCommand {
|
|
|
269
270
|
.command("list")
|
|
270
271
|
.description("List all persisted task ids, one per line")
|
|
271
272
|
.option("-v, --verbose", "also show the task file modification time as (YYYY-MM-DD HH:MM)")
|
|
272
|
-
.action((opts) => {
|
|
273
|
+
.action(async (opts) => {
|
|
273
274
|
const items = Task.list(this.log, opts.verbose ?? false);
|
|
274
275
|
for (const item of items) {
|
|
275
276
|
if (opts.verbose)
|
|
276
|
-
|
|
277
|
+
await writeStdout(`${item.id}\t(${item.mtime})\n`);
|
|
277
278
|
else
|
|
278
|
-
|
|
279
|
+
await writeStdout(`${item.id}\n`);
|
|
279
280
|
}
|
|
280
|
-
process.exit(0);
|
|
281
281
|
});
|
|
282
282
|
/* register CLI sub-command "ase task load" */
|
|
283
283
|
task
|
|
284
284
|
.command("load")
|
|
285
285
|
.description("Load a task by id and write it to stdout")
|
|
286
286
|
.argument("<id>", "Task identifier")
|
|
287
|
-
.action((id) => {
|
|
287
|
+
.action(async (id) => {
|
|
288
288
|
const text = Task.load(this.log, id);
|
|
289
|
-
|
|
290
|
-
process.exit(0);
|
|
289
|
+
await writeStdout(text);
|
|
291
290
|
});
|
|
292
291
|
/* register CLI sub-command "ase task edit" */
|
|
293
292
|
task
|
package/dst/ase.js
CHANGED
|
@@ -15,6 +15,7 @@ import SetupCommand from "./ase-setup.js";
|
|
|
15
15
|
import StatuslineCommand from "./ase-statusline.js";
|
|
16
16
|
import TaskCommand from "./ase-task.js";
|
|
17
17
|
import ArtifactCommand from "./ase-artifact.js";
|
|
18
|
+
import MetaCommand from "./ase-meta.js";
|
|
18
19
|
import CompatCommand from "./ase-compat.js";
|
|
19
20
|
import pkg from "../package.json" with { type: "json" };
|
|
20
21
|
/* globally initialize logger */
|
|
@@ -52,6 +53,7 @@ const main = async () => {
|
|
|
52
53
|
new StatuslineCommand(log).register(program);
|
|
53
54
|
new TaskCommand(log).register(program);
|
|
54
55
|
new ArtifactCommand(log).register(program);
|
|
56
|
+
new MetaCommand(log).register(program);
|
|
55
57
|
new CompatCommand().register(program);
|
|
56
58
|
new DiagramCommand(log).register(program);
|
|
57
59
|
/* parse program arguments */
|
package/package.json
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
"homepage": "http://github.com/rse/ase",
|
|
7
7
|
"repository": { "url": "git+https://github.com/rse/ase.git", "type": "git" },
|
|
8
8
|
"bugs": { "url": "http://github.com/rse/ase/issues" },
|
|
9
|
-
"version": "0.9.
|
|
9
|
+
"version": "0.9.32",
|
|
10
10
|
"license": "Apache-2.0",
|
|
11
11
|
"author": {
|
|
12
12
|
"name": "Dr. Ralf S. Engelschall",
|
|
@@ -1003,7 +1003,7 @@ its purpose, and the alternatives that were considered but not chosen.
|
|
|
1003
1003
|
- In case the rationale is not present, the
|
|
1004
1004
|
entire `, **BECAUSE** [...]` clause is omitted.
|
|
1005
1005
|
|
|
1006
|
-
- The known *Client Aspects* which usually have to covered (at least for
|
|
1006
|
+
- The known *Client Aspects* which usually have to be covered (at least for
|
|
1007
1007
|
clients in a Rich-Client architecture):
|
|
1008
1008
|
|
|
1009
1009
|
- **Interface Theme**:
|
|
@@ -1079,7 +1079,7 @@ its purpose, and the alternatives that were considered but not chosen.
|
|
|
1079
1079
|
- **Environment Detection**:
|
|
1080
1080
|
Runtime Detection, Feature Detection.
|
|
1081
1081
|
|
|
1082
|
-
- The known *Server Aspects* which usually have to covered (at least for
|
|
1082
|
+
- The known *Server Aspects* which usually have to be covered (at least for
|
|
1083
1083
|
servers, sometimes called Thin-Servers, in a Rich-Client architecture):
|
|
1084
1084
|
|
|
1085
1085
|
- **Environment Detection**:
|
package/plugin/meta/ase-skill.md
CHANGED
|
@@ -143,10 +143,10 @@ Skill Sequential Processing
|
|
|
143
143
|
- *IMPORTANT*: You *MUST* *strictly sequentially* execute every <step/> in
|
|
144
144
|
a <flow/>. You *MUST* not implicitly skip any <step/> during
|
|
145
145
|
processing, except you were explicitly requested to do this or the
|
|
146
|
-
step is
|
|
146
|
+
step is configured to be a conditional step!
|
|
147
147
|
|
|
148
148
|
- *IMPORTANT*: You *MUST* *strictly sequentially* execute every numbered
|
|
149
|
-
|
|
149
|
+
item in a <step/>. You *MUST* not implicitly skip any numbered item during
|
|
150
150
|
processing, except you were explicitly requested to do this!
|
|
151
151
|
|
|
152
152
|
- *IMPORTANT*: For any <step/> that specifies an *agent* in its
|
|
@@ -120,7 +120,7 @@ you *MUST* honor the following so-called "CRAFTING TENETS":
|
|
|
120
120
|
RECONCILIATION TENETS
|
|
121
121
|
---------------------
|
|
122
122
|
|
|
123
|
-
When *
|
|
123
|
+
When *reconciling* a set of target artifacts to a set of source artifacts,
|
|
124
124
|
you *MUST* honor the following so-called **RECONCILIATION TENETS**:
|
|
125
125
|
|
|
126
126
|
- **Directional Authority**:
|
package/plugin/package.json
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
"homepage": "http://github.com/rse/ase",
|
|
7
7
|
"repository": { "url": "git+https://github.com/rse/ase.git", "type": "git" },
|
|
8
8
|
"bugs": { "url": "http://github.com/rse/ase/issues" },
|
|
9
|
-
"version": "0.9.
|
|
9
|
+
"version": "0.9.32",
|
|
10
10
|
"license": "Apache-2.0",
|
|
11
11
|
"author": {
|
|
12
12
|
"name": "Dr. Ralf S. Engelschall",
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
|
|
2
2
|
## NAME
|
|
3
3
|
|
|
4
|
-
`ase-meta-diaboli` - Play "Devil's Advocate" (
|
|
4
|
+
`ase-meta-diaboli` - Play "Devil's Advocate" (Latin: "Advocatus Diaboli")
|
|
5
5
|
|
|
6
6
|
## SYNOPSIS
|
|
7
7
|
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
|
|
13
13
|
## DESCRIPTION
|
|
14
14
|
|
|
15
|
-
The `ase-meta-diaboli` skill plays *Devil's Advocate* (
|
|
15
|
+
The `ase-meta-diaboli` skill plays *Devil's Advocate* (Latin:
|
|
16
16
|
*Advocatus Diaboli*) by relentlessly challenging or criticising a
|
|
17
17
|
supplied *thesis*. It applies a disciplined set of critical-thinking
|
|
18
18
|
tenets - steelmanning, stress-testing fundamentals, surfacing implicit
|
|
@@ -130,7 +130,7 @@ Procedure
|
|
|
130
130
|
For this process, determine the <n/> essential aspects <aspect-N/>
|
|
131
131
|
(a one or two word long short identifier like `Foo` or `Bar-Baz`)
|
|
132
132
|
and the corresponding decision/question <question-N/> where a shared
|
|
133
|
-
understanding is required
|
|
133
|
+
understanding is required.
|
|
134
134
|
|
|
135
135
|
Honor also the following checks for identifying the problematic
|
|
136
136
|
aspects:
|