@rse/ase 0.9.55 → 0.9.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.
Files changed (78) hide show
  1. package/dst/ase-setup.js +4 -2
  2. package/dst/ase-statusline.js +6 -8
  3. package/dst/ase-task.js +36 -11
  4. package/package.json +5 -5
  5. package/plugin/.claude-plugin/plugin.json +1 -1
  6. package/plugin/.codex-plugin/plugin.json +1 -1
  7. package/plugin/.github/plugin/plugin.json +1 -1
  8. package/plugin/agents/ase-code-analyze.md +1 -1
  9. package/plugin/agents/ase-code-lint.md +4 -4
  10. package/plugin/agents/ase-meta-chat.md +1 -1
  11. package/plugin/agents/ase-meta-proximity.md +1 -1
  12. package/plugin/meta/ase-common-code.md +164 -1
  13. package/plugin/meta/ase-common-task.md +14 -13
  14. package/plugin/meta/ase-constitution.md +3 -3
  15. package/plugin/meta/ase-control.md +7 -7
  16. package/plugin/meta/ase-dialog.md +5 -4
  17. package/plugin/meta/ase-format-arch.md +7 -8
  18. package/plugin/meta/ase-format-spec.md +10 -11
  19. package/plugin/meta/ase-format-task.md +2 -2
  20. package/plugin/meta/ase-getopt.md +1 -1
  21. package/plugin/meta/ase-persona.md +3 -3
  22. package/plugin/meta/ase-skill.md +14 -24
  23. package/plugin/meta/ase-tenets.md +5 -5
  24. package/plugin/package.json +2 -2
  25. package/plugin/skills/ase-arch-analyze/SKILL.md +1 -1
  26. package/plugin/skills/ase-arch-analyze/help.md +1 -1
  27. package/plugin/skills/ase-arch-discover/SKILL.md +8 -6
  28. package/plugin/skills/ase-code-analyze/SKILL.md +1 -1
  29. package/plugin/skills/ase-code-analyze/help.md +1 -1
  30. package/plugin/skills/ase-code-craft/SKILL.md +2 -153
  31. package/plugin/skills/ase-code-craft/help.md +1 -1
  32. package/plugin/skills/ase-code-explain/SKILL.md +3 -3
  33. package/plugin/skills/ase-code-insight/SKILL.md +9 -7
  34. package/plugin/skills/ase-code-lint/SKILL.md +7 -5
  35. package/plugin/skills/ase-code-refactor/SKILL.md +4 -155
  36. package/plugin/skills/ase-code-resolve/SKILL.md +8 -159
  37. package/plugin/skills/ase-docs-distill/SKILL.md +2 -2
  38. package/plugin/skills/ase-docs-distill/help.md +1 -1
  39. package/plugin/skills/ase-docs-proofread/SKILL.md +7 -3
  40. package/plugin/skills/ase-help-intent/SKILL.md +33 -9
  41. package/plugin/skills/ase-help-skill/SKILL.md +1 -1
  42. package/plugin/skills/ase-meta-brainstorm/SKILL.md +11 -2
  43. package/plugin/skills/ase-meta-changelog/SKILL.md +12 -8
  44. package/plugin/skills/ase-meta-commit/SKILL.md +11 -1
  45. package/plugin/skills/ase-meta-compat/SKILL.md +2 -2
  46. package/plugin/skills/ase-meta-config/help.md +1 -1
  47. package/plugin/skills/ase-meta-diaboli/SKILL.md +12 -3
  48. package/plugin/skills/ase-meta-diff/SKILL.md +11 -13
  49. package/plugin/skills/ase-meta-eli5/SKILL.md +3 -3
  50. package/plugin/skills/ase-meta-eli5/help.md +1 -1
  51. package/plugin/skills/ase-meta-evaluate/SKILL.md +3 -3
  52. package/plugin/skills/ase-meta-quorum/SKILL.md +17 -17
  53. package/plugin/skills/ase-meta-quotes/SKILL.md +1 -1
  54. package/plugin/skills/ase-meta-review/SKILL.md +7 -5
  55. package/plugin/skills/ase-meta-review/help.md +2 -2
  56. package/plugin/skills/ase-meta-search/SKILL.md +18 -0
  57. package/plugin/skills/ase-meta-steelman/SKILL.md +11 -2
  58. package/plugin/skills/ase-meta-why/SKILL.md +15 -6
  59. package/plugin/skills/ase-meta-why/help.md +3 -3
  60. package/plugin/skills/ase-sync-export/SKILL.md +2 -1
  61. package/plugin/skills/ase-sync-export/help.md +1 -1
  62. package/plugin/skills/ase-sync-reconcile/SKILL.md +16 -2
  63. package/plugin/skills/ase-task-condense/SKILL.md +13 -67
  64. package/plugin/skills/ase-task-delete/SKILL.md +1 -1
  65. package/plugin/skills/ase-task-dissect/SKILL.md +5 -18
  66. package/plugin/skills/ase-task-edit/SKILL.md +49 -22
  67. package/plugin/skills/ase-task-grill/SKILL.md +31 -129
  68. package/plugin/skills/ase-task-id/SKILL.md +12 -2
  69. package/plugin/skills/ase-task-implement/SKILL.md +11 -7
  70. package/plugin/skills/ase-task-implement/help.md +1 -1
  71. package/plugin/skills/ase-task-list/SKILL.md +9 -0
  72. package/plugin/skills/ase-task-preflight/SKILL.md +13 -7
  73. package/plugin/skills/ase-task-reboot/SKILL.md +18 -61
  74. package/plugin/skills/ase-task-reboot/help.md +1 -1
  75. package/plugin/skills/ase-task-view/SKILL.md +4 -2
  76. package/dst/ase-guidance.js +0 -89
  77. package/dst/ase-persona.js +0 -87
  78. package/dst/ase-stdout.js +0 -18
@@ -78,25 +78,31 @@ Procedure
78
78
  previous run of this skill, *replace* this entire existing
79
79
  section.
80
80
 
81
+ Set <fence/> to a run of backtick characters *one longer* than
82
+ the longest backtick run occurring anywhere inside
83
+ <unified-diff/>, but to at least three, so a diff which itself
84
+ carries fenced code blocks (e.g. one over Markdown artifacts)
85
+ cannot terminate the block prematurely.
86
+
81
87
  <template>
82
88
 
83
89
  ## IMPLEMENTATION DRAFT
84
90
 
85
- ```text
91
+ <fence/>text
86
92
  <unified-diff/>
87
- ```
93
+ <fence/>
88
94
 
89
95
  </template>
90
96
 
91
- 3. <if condition="the frontmatter of <task-content/> carries a `Modified:` key">
92
- Update <timestamp-modified/> with the current time in
97
+ 3. Update <timestamp-modified/> with the current time in
93
98
  ISO-style format, which has to be determined by calling the
94
99
  `ase_timestamp(format: "yyyy-LL-dd HH:mm")` tool of the `ase`
95
- MCP server and use the `text` field of its response. Update
100
+ MCP server and using the `text` field of its response. Update
96
101
  the `Modified: ...` frontmatter key of <task-content/> with the
97
- new <timestamp-modified/> value.
102
+ new <timestamp-modified/> value, *creating* the whole key at its
103
+ position in the key order of the plan <format/> if the plan does
104
+ not carry it yet.
98
105
  Do not output anything.
99
- </if>
100
106
 
101
107
  Additionally *add* the value `preflighted` to the `Properties:`
102
108
  frontmatter key of <task-content/> if it is still absent, keeping
@@ -21,7 +21,7 @@ Reboot a Task Plan
21
21
 
22
22
  <expand name="getopt"
23
23
  arg1="ase-task-reboot"
24
- arg2="--next|-n=(none|DONE|EDIT|IMPLEMENT|PREFLIGHT)...">
24
+ arg2="--next|-n=(none|DONE|EDIT|IMPLEMENT|PREFLIGHT)... --int-reuse-task">
25
25
  $ARGUMENTS
26
26
  </expand>
27
27
 
@@ -46,51 +46,13 @@ Procedure
46
46
 
47
47
  2. React on task id:
48
48
 
49
- 1. <if condition="
50
- <instruction/> matches the regexp `^[a-zA-Z][a-zA-Z0-9_-]*$`
51
- ">
52
- Set <ase-task-id><instruction/></ase-task-id> (set task
53
- id to instruction) and <instruction></instruction> (set
54
- instruction empty), call the `ase_task_id(id: "<ase-task-id/>",
55
- session: "<ase-session-id/>")` tool from the `ase` MCP
56
- server to switch the task, and then only output the
57
- following <template/>:
58
-
59
- <template>
60
- ⧉ **ASE**: ◉ task: **<ase-task-id/>**, ▶ status: **task given**
61
- </template>
62
- </if>
63
-
64
- 2. <elseif condition="<instruction/> is NOT empty">
65
- The argument is neither empty nor a valid task id. As this
66
- skill only accepts an optional `[<id>]` argument and *never*
67
- a free-text instruction, only output the following <template/>
68
- and then immediately *STOP* processing the entire current skill:
69
-
70
- <template>
71
- ⧉ **ASE**: ☻ skill: **ase-task-reboot**, ▶ ERROR: expected single `[<id>]` argument
72
- </template>
73
- </elseif>
49
+ <expand name="task-react-id" arg1="ase-task-reboot"></expand>
74
50
 
75
51
  2. **Determine Operation:**
76
52
 
77
- 1. Call the `ase_task_load(id: "<ase-task-id/>")` tool of the `ase` MCP
78
- server to load the current task plan content and set <text/> to
79
- the `text` output field of the `ase_task_load` tool call.
80
-
81
- - If <text/> starts with `ERROR:` or `WARNING:`:
82
- Set <task-content></task-content> (set task content to empty).
83
- Set <words/> to "0".
84
-
85
- - If <text/> starts NOT with `ERROR:` and NOT with `WARNING:`:
86
- Set <task-content><text/></task-content> (set task content to text).
87
- Calculate the number of words <words/> of <task-content/>.
53
+ 1. Determine the current task plan content:
88
54
 
89
- Only output the following <template/>:
90
-
91
- <template>
92
- ⧉ **ASE**: ◉ task: **<ase-task-id/>**, ✪ plan: **<words/>** words, ▶ status: **plan loaded**
93
- </template>
55
+ <expand name="task-load-content"></expand>
94
56
 
95
57
  2. <if condition="<task-content/> is empty">
96
58
  Complain and tell the user to use the `ase-code-resolve`,
@@ -102,33 +64,28 @@ Procedure
102
64
  3. **Reboot Task Plan:**
103
65
 
104
66
  1. Start with <instruction></instruction> (set instruction to empty).
67
+ Do not output anything.
105
68
 
106
- The loaded <task-content/> is the *rendering-prepared* variant of
107
- the plan, so its bullet markers can be rendered as `◯` instead
108
- of the authored `-`. Set <marker>◯</marker> if the bullet points
109
- of <task-content/> start with `◯`, and set <marker>-</marker>
110
- otherwise. Do not output anything.
111
-
112
- 2. <if condition="<task-content/> contains neither '<marker/> **WHAT**:' nor '<marker/> **WHY**:'">
69
+ 2. <if condition="<task-content/> contains neither '- **WHAT**:' nor '- **WHY**:'">
113
70
  Set <instruction><task-content/></instruction> (set instruction to task content).
114
71
  </if>
115
72
 
116
- 3. <if condition="<task-content/> contains '<marker/> **WHAT**: <text/>'">
73
+ 3. <if condition="<task-content/> contains '- **WHAT**: <text/>'">
117
74
  Set <instruction><text/></instruction> (set instruction to extracted text).
118
75
  </if>
119
76
 
120
- 4. <if condition="<task-content/> contains '<marker/> **WHY**: <text/>' and <instruction/> is empty">
77
+ 4. <if condition="<task-content/> contains '- **WHY**: <text/>' and <instruction/> is empty">
121
78
  Set <instruction><text/></instruction> (set instruction to extracted text).
122
79
  </if>
123
80
 
124
- 5. <if condition="<task-content/> contains '<marker/> **WHY**: <text/>' and <instruction/> is NOT empty">
81
+ 5. <if condition="<task-content/> contains '- **WHY**: <text/>' and <instruction/> is NOT empty">
125
82
  Set <instruction><instruction/>, BECAUSE <text/></instruction>
126
83
  (append extracted text to instruction).
127
84
  </if>
128
85
 
129
86
  6. <if condition="the frontmatter of <task-content/> carries a `Created: <text/>` key">
130
87
  Set <timestamp-created><text/></timestamp-created> (set
131
- timestamp-created to extracted text)
88
+ timestamp-created to extracted text).
132
89
  </if>
133
90
 
134
91
  7. <if condition="<instruction/> is empty or contains only whitespace">
@@ -148,19 +105,19 @@ Procedure
148
105
  </if>
149
106
  </if>
150
107
 
151
- 8. Create a new plan from scratch and store the result as
108
+ 8. Only output the following <template/> and continue processing:
109
+
110
+ <template>
111
+ ⧉ **ASE**: ◉ task: **<ase-task-id/>**, ⇌ instruction: **<instruction/>**, ▶ status: **instruction given**
112
+ </template>
113
+
114
+ 9. Create a new plan from scratch and store the result as
152
115
  <task-content/> by closely following the defined plan format
153
116
  <format/> and injecting into it all the information from
154
117
  the <instruction/> and all decisions you derived from the
155
118
  <instruction/>.
156
119
 
157
- 9. <expand name="task-save-content" arg1="plan rebooted"></expand>
158
-
159
- 10. Only output the following <template/> and continue processing:
160
-
161
- <template>
162
- ⧉ **ASE**: ◉ task: **<ase-task-id/>**, ⇌ instruction: **<instruction/>**, ▶ status: **instruction given**
163
- </template>
120
+ 10. <expand name="task-save-content" arg1="plan rebooted"></expand>
164
121
 
165
122
  4. **Decide Next Step:**
166
123
 
@@ -15,7 +15,7 @@
15
15
  The `ase-task-reboot` skill re-creates an existing task plan *from
16
16
  scratch* by extracting the original `**WHAT**` and `**WHY**` sections
17
17
  (if present) from the current plan, using them as the new instruction,
18
- preserving the original creation timestamp, and writing a fresh plan
18
+ preserving the original creation timestamp, and writing fresh plan
19
19
  content via `ase_task_save`.
20
20
 
21
21
  After the reboot, the user is asked whether to stop or hand off to
@@ -54,8 +54,10 @@ Procedure
54
54
 
55
55
  2. **Perform Operation**:
56
56
 
57
- 1. Call the `ase_task_load(id: "<id/>")` tool of the `ase` MCP
58
- server to load the task plan content and set <text/> to the
57
+ 1. Call the `ase_task_load(id: "<id/>", variant: "render")` tool
58
+ of the `ase` MCP server to load the task plan content in its
59
+ *rendering-prepared* form -- this skill is *display-only* and
60
+ hence never persists the plan again -- and set <text/> to the
59
61
  `text` output field of this `ase_task_load` tool call. Do not
60
62
  output anything related to this MCP tool call.
61
63
 
@@ -1,89 +0,0 @@
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 { isScalar } from "yaml";
7
- import { z } from "zod";
8
- import { Config, configSchema, parseScope, agentClassification } from "./ase-config.js";
9
- /* reusable functionality: ASE agent guidance level get/set */
10
- export class Guidance {
11
- /* allowed guidance level values */
12
- static levels = agentClassification.guidance;
13
- /* get the effective guidance level for an optional session;
14
- returns the default "normal" if nothing is configured */
15
- static get(log, session) {
16
- const scope = parseScope(session !== undefined ? `session:${session}` : undefined);
17
- const cfg = new Config("config", configSchema, log, scope);
18
- cfg.read();
19
- const val = cfg.get("agent.guidance");
20
- if (val === undefined)
21
- return "normal";
22
- const level = String(isScalar(val) ? val.value : val);
23
- return Guidance.levels.find((l) => l === level) ?? "normal";
24
- }
25
- /* set the guidance level on the strongest scope of an optional session */
26
- static set(log, level, session) {
27
- const scope = parseScope(session !== undefined ? `session:${session}` : undefined);
28
- const cfg = new Config("config", configSchema, log, scope);
29
- cfg.lock(() => {
30
- cfg.read();
31
- cfg.set("agent.guidance", level);
32
- cfg.write();
33
- });
34
- }
35
- }
36
- /* MCP registration entry point for guidance tools */
37
- export default class GuidanceMCP {
38
- log;
39
- constructor(log) {
40
- this.log = log;
41
- }
42
- register(mcp) {
43
- mcp.registerTool("ase_guidance", {
44
- title: "ASE guidance level get/set",
45
- description: "Get or set the active ASE agent guidance `level`. " +
46
- "If `level` is provided, it sets the guidance level, " +
47
- "otherwise it returns the current guidance `level`. " +
48
- "If `session` is provided, the operation is scoped to that session, " +
49
- "otherwise it operates on the strongest/closest scope (user/project cascade). " +
50
- "The guidance level controls the amount of unsolicited help hints -- " +
51
- "pointers to the available ASE skills, their options, and the recommended " +
52
- "next operations -- the agent emits. " +
53
- "Allowed levels: \"none\" (no help hints at all), " +
54
- "\"minimal\" (the single most essential help hint only), " +
55
- "\"normal\" (the essential help hints only), " +
56
- "\"verbose\" (all available help hints).",
57
- inputSchema: {
58
- level: z.enum(Guidance.levels).optional()
59
- .describe("guidance level to set; if omitted, the current guidance level is returned"),
60
- session: z.string().regex(/^[A-Za-z0-9._-]+$/).optional()
61
- .describe("session identifier (allowed characters: A-Z, a-z, 0-9, '.', '_', '-'); " +
62
- "if omitted, the operation is not scoped to a specific session")
63
- }
64
- }, async (args) => {
65
- try {
66
- if (args.level !== undefined) {
67
- Guidance.set(this.log, args.level, args.session);
68
- const where = args.session !== undefined ?
69
- ` for session "${args.session}"` : "";
70
- const msg = `OK: set agent.guidance to "${args.level}"${where}`;
71
- return {
72
- content: [{ type: "text", text: msg }]
73
- };
74
- }
75
- const text = Guidance.get(this.log, args.session);
76
- return {
77
- content: [{ type: "text", text }]
78
- };
79
- }
80
- catch (err) {
81
- const message = err instanceof Error ? err.message : String(err);
82
- return {
83
- isError: true,
84
- content: [{ type: "text", text: `ERROR: ${message}` }]
85
- };
86
- }
87
- });
88
- }
89
- }
@@ -1,87 +0,0 @@
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 { isScalar } from "yaml";
7
- import { z } from "zod";
8
- import { Config, configSchema, parseScope, agentClassification } from "./ase-config.js";
9
- /* reusable functionality: ASE agent persona style get/set */
10
- export class Persona {
11
- /* allowed persona style values */
12
- static styles = agentClassification.persona;
13
- /* get the effective persona style for an optional session;
14
- returns the default "engineer" if nothing is configured */
15
- static get(log, session) {
16
- const scope = parseScope(session !== undefined ? `session:${session}` : undefined);
17
- const cfg = new Config("config", configSchema, log, scope);
18
- cfg.read();
19
- const val = cfg.get("agent.persona");
20
- if (val === undefined)
21
- return "engineer";
22
- const style = String(isScalar(val) ? val.value : val);
23
- return Persona.styles.find((s) => s === style) ?? "engineer";
24
- }
25
- /* set the persona style on the strongest scope of an optional session */
26
- static set(log, style, session) {
27
- const scope = parseScope(session !== undefined ? `session:${session}` : undefined);
28
- const cfg = new Config("config", configSchema, log, scope);
29
- cfg.lock(() => {
30
- cfg.read();
31
- cfg.set("agent.persona", style);
32
- cfg.write();
33
- });
34
- }
35
- }
36
- /* MCP registration entry point for persona tools */
37
- export default class PersonaMCP {
38
- log;
39
- constructor(log) {
40
- this.log = log;
41
- }
42
- register(mcp) {
43
- mcp.registerTool("ase_persona", {
44
- title: "ASE persona style get/set",
45
- description: "Get or set the active ASE agent persona `style`. " +
46
- "If `style` is provided, it sets the persona style, " +
47
- "otherwise it returns the current persona `style`. " +
48
- "If `session` is provided, the operation is scoped to that session, " +
49
- "otherwise it operates on the strongest/closest scope (user/project cascade). " +
50
- "Allowed styles: \"writer\" (decorative, eloquent, explaining), " +
51
- "\"engineer\" (concise, factual, accurate), " +
52
- "\"journalist\" (layered, pyramid-structured title/core/detail), " +
53
- "\"telegrapher\" (very brief, factual, abbreviating), " +
54
- "\"caveman\" (ultra brief, rough, stuttering).",
55
- inputSchema: {
56
- style: z.enum(Persona.styles).optional()
57
- .describe("persona style to set; if omitted, the current persona style is returned"),
58
- session: z.string().regex(/^[A-Za-z0-9._-]+$/).optional()
59
- .describe("session identifier (allowed characters: A-Z, a-z, 0-9, '.', '_', '-'); " +
60
- "if omitted, the operation is not scoped to a specific session")
61
- }
62
- }, async (args) => {
63
- try {
64
- if (args.style !== undefined) {
65
- Persona.set(this.log, args.style, args.session);
66
- const where = args.session !== undefined ?
67
- ` for session "${args.session}"` : "";
68
- const msg = `OK: set agent.persona to "${args.style}"${where}`;
69
- return {
70
- content: [{ type: "text", text: msg }]
71
- };
72
- }
73
- const text = Persona.get(this.log, args.session);
74
- return {
75
- content: [{ type: "text", text }]
76
- };
77
- }
78
- catch (err) {
79
- const message = err instanceof Error ? err.message : String(err);
80
- return {
81
- isError: true,
82
- content: [{ type: "text", text: `ERROR: ${message}` }]
83
- };
84
- }
85
- });
86
- }
87
- }
package/dst/ase-stdout.js DELETED
@@ -1,18 +0,0 @@
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
- };