ethan-skill 1.5.9 → 1.7.0

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 (50) hide show
  1. package/dist/cli/index.js +32 -26
  2. package/dist/cli/index.js.map +1 -1
  3. package/dist/loader/custom-pipeline-loader.d.ts +15 -0
  4. package/dist/loader/custom-pipeline-loader.d.ts.map +1 -0
  5. package/dist/loader/custom-pipeline-loader.js +131 -0
  6. package/dist/loader/custom-pipeline-loader.js.map +1 -0
  7. package/dist/loader/custom-skill-loader.d.ts +7 -2
  8. package/dist/loader/custom-skill-loader.d.ts.map +1 -1
  9. package/dist/loader/custom-skill-loader.js +112 -3
  10. package/dist/loader/custom-skill-loader.js.map +1 -1
  11. package/dist/loader/custom-skill-loader.test.d.ts +2 -0
  12. package/dist/loader/custom-skill-loader.test.d.ts.map +1 -0
  13. package/dist/loader/custom-skill-loader.test.js +201 -0
  14. package/dist/loader/custom-skill-loader.test.js.map +1 -0
  15. package/dist/skills/11-api-design.d.ts +3 -0
  16. package/dist/skills/11-api-design.d.ts.map +1 -0
  17. package/dist/skills/11-api-design.js +214 -0
  18. package/dist/skills/11-api-design.js.map +1 -0
  19. package/dist/skills/12-security-review.d.ts +3 -0
  20. package/dist/skills/12-security-review.d.ts.map +1 -0
  21. package/dist/skills/12-security-review.js +194 -0
  22. package/dist/skills/12-security-review.js.map +1 -0
  23. package/dist/skills/13-deployment.d.ts +3 -0
  24. package/dist/skills/13-deployment.d.ts.map +1 -0
  25. package/dist/skills/13-deployment.js +189 -0
  26. package/dist/skills/13-deployment.js.map +1 -0
  27. package/dist/skills/14-prd.d.ts +3 -0
  28. package/dist/skills/14-prd.d.ts.map +1 -0
  29. package/dist/skills/14-prd.js +214 -0
  30. package/dist/skills/14-prd.js.map +1 -0
  31. package/dist/skills/index.d.ts +4 -0
  32. package/dist/skills/index.d.ts.map +1 -1
  33. package/dist/skills/index.js +17 -1
  34. package/dist/skills/index.js.map +1 -1
  35. package/dist/skills/pipeline.d.ts +2 -1
  36. package/dist/skills/pipeline.d.ts.map +1 -1
  37. package/dist/skills/pipeline.js +41 -3
  38. package/dist/skills/pipeline.js.map +1 -1
  39. package/package.json +1 -1
  40. package/rules/claude-code/CLAUDE.md +641 -3
  41. package/rules/cline/.clinerules +578 -2
  42. package/rules/codebuddy/CODEBUDDY.md +618 -2
  43. package/rules/continue/.continuerules +578 -2
  44. package/rules/copilot/copilot-instructions.md +606 -2
  45. package/rules/cursor/.cursorrules +636 -2
  46. package/rules/cursor/smart-flow.mdc +636 -2
  47. package/rules/jetbrains/smart-flow.md +606 -2
  48. package/rules/lingma/smart-flow.md +615 -3
  49. package/rules/windsurf/.windsurf/rules/smart-flow.md +607 -3
  50. package/rules/zed/smart-flow.rules +573 -1
@@ -0,0 +1,131 @@
1
+ "use strict";
2
+ /**
3
+ * 自定义 Pipeline 加载器
4
+ * 从项目的 .ethan/pipelines/ 目录加载用户自定义 Pipeline(YAML 或 JSON 格式)
5
+ */
6
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
7
+ if (k2 === undefined) k2 = k;
8
+ var desc = Object.getOwnPropertyDescriptor(m, k);
9
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
10
+ desc = { enumerable: true, get: function() { return m[k]; } };
11
+ }
12
+ Object.defineProperty(o, k2, desc);
13
+ }) : (function(o, m, k, k2) {
14
+ if (k2 === undefined) k2 = k;
15
+ o[k2] = m[k];
16
+ }));
17
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
18
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
19
+ }) : function(o, v) {
20
+ o["default"] = v;
21
+ });
22
+ var __importStar = (this && this.__importStar) || (function () {
23
+ var ownKeys = function(o) {
24
+ ownKeys = Object.getOwnPropertyNames || function (o) {
25
+ var ar = [];
26
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
27
+ return ar;
28
+ };
29
+ return ownKeys(o);
30
+ };
31
+ return function (mod) {
32
+ if (mod && mod.__esModule) return mod;
33
+ var result = {};
34
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
35
+ __setModuleDefault(result, mod);
36
+ return result;
37
+ };
38
+ })();
39
+ Object.defineProperty(exports, "__esModule", { value: true });
40
+ exports.loadCustomPipelines = loadCustomPipelines;
41
+ exports.generatePipelineTemplate = generatePipelineTemplate;
42
+ const fs = __importStar(require("fs"));
43
+ const path = __importStar(require("path"));
44
+ const CUSTOM_PIPELINES_DIR = '.ethan/pipelines';
45
+ /**
46
+ * 从指定目录加载自定义 Pipeline 定义
47
+ * 支持 .yaml、.yml、.json 格式
48
+ */
49
+ function loadCustomPipelines(cwd = process.cwd()) {
50
+ const pipelinesDir = path.join(cwd, CUSTOM_PIPELINES_DIR);
51
+ if (!fs.existsSync(pipelinesDir))
52
+ return [];
53
+ const files = fs.readdirSync(pipelinesDir).filter((f) => /\.(ya?ml|json)$/i.test(f));
54
+ const pipelines = [];
55
+ for (const file of files) {
56
+ const filePath = path.join(pipelinesDir, file);
57
+ try {
58
+ const raw = fs.readFileSync(filePath, 'utf-8');
59
+ let data;
60
+ if (/\.json$/i.test(file)) {
61
+ data = JSON.parse(raw);
62
+ }
63
+ else {
64
+ // eslint-disable-next-line @typescript-eslint/no-require-imports
65
+ const yaml = require('js-yaml');
66
+ data = yaml.load(raw);
67
+ }
68
+ const pipeline = validateCustomPipeline(data, file);
69
+ if (pipeline) {
70
+ pipelines.push(pipeline);
71
+ }
72
+ }
73
+ catch (err) {
74
+ console.warn(` ⚠️ Failed to load custom pipeline: ${file} — ${err.message}`);
75
+ }
76
+ }
77
+ return pipelines;
78
+ }
79
+ /**
80
+ * 验证自定义 Pipeline 数据结构,返回合法的 PipelineDefinition 或 null
81
+ */
82
+ function validateCustomPipeline(data, filename) {
83
+ if (typeof data !== 'object' || data === null) {
84
+ console.warn(` ⚠️ ${filename}: root must be an object`);
85
+ return null;
86
+ }
87
+ const d = data;
88
+ const required = ['id', 'name', 'description', 'skillIds'];
89
+ for (const key of required) {
90
+ if (!d[key]) {
91
+ console.warn(` ⚠️ ${filename}: missing required field "${key}"`);
92
+ return null;
93
+ }
94
+ }
95
+ if (!Array.isArray(d.skillIds) || d.skillIds.length === 0) {
96
+ console.warn(` ⚠️ ${filename}: "skillIds" must be a non-empty array`);
97
+ return null;
98
+ }
99
+ return {
100
+ id: String(d.id),
101
+ name: String(d.name),
102
+ description: String(d.description),
103
+ skillIds: d.skillIds.map(String),
104
+ };
105
+ }
106
+ /**
107
+ * 生成自定义 Pipeline 的 YAML 模板文件
108
+ */
109
+ function generatePipelineTemplate() {
110
+ return `# Ethan 自定义 Pipeline 模板
111
+ # Pipeline 是多个 Skill 的有序组合,支持链式工作流
112
+
113
+ id: my-pipeline # 唯一标识符(用于 ethan pipeline run <id>)
114
+ name: 我的工作流 # 显示名称
115
+ description: 一句话描述这条 Pipeline 的用途
116
+
117
+ # skillIds: 按执行顺序填写 Skill ID
118
+ # 可用内置 Skill ID:
119
+ # requirement-understanding, task-breakdown, solution-design,
120
+ # implementation, progress-tracking, task-report, weekly-report,
121
+ # code-review, debug, tech-research,
122
+ # api-design, security-review, deployment, prd
123
+ # 也可以使用自定义 Skill 的 ID(需先在 .ethan/skills/ 中定义)
124
+ skillIds:
125
+ - requirement-understanding
126
+ - solution-design
127
+ - implementation
128
+ - code-review
129
+ `;
130
+ }
131
+ //# sourceMappingURL=custom-pipeline-loader.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"custom-pipeline-loader.js","sourceRoot":"","sources":["../../src/loader/custom-pipeline-loader.ts"],"names":[],"mappings":"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"}
@@ -1,15 +1,20 @@
1
1
  /**
2
2
  * 自定义 Skill 加载器
3
- * 从项目的 .ethan/skills/ 目录加载用户自定义 Skill(YAML 或 JSON 格式)
3
+ * 从项目的 .ethan/skills/ 目录加载用户自定义 Skill(YAML、JSONMarkdown 格式)
4
4
  */
5
5
  import type { SkillDefinition } from '../skills/types';
6
6
  /**
7
7
  * 从指定目录加载自定义 Skill 定义
8
- * 支持 .yaml、.yml、.json 格式
8
+ * 支持 .yaml、.yml、.json、.md 格式
9
9
  */
10
10
  export declare function loadCustomSkills(cwd?: string): SkillDefinition[];
11
11
  /**
12
12
  * 生成自定义 Skill 的 YAML 模板文件
13
13
  */
14
14
  export declare function generateSkillTemplate(): string;
15
+ /**
16
+ * 生成自定义 Skill 的 Markdown 模板文件
17
+ * 格式:YAML frontmatter(元数据)+ Markdown 正文(步骤,每个 ## 标题为一步)
18
+ */
19
+ export declare function generateMdSkillTemplate(): string;
15
20
  //# sourceMappingURL=custom-skill-loader.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"custom-skill-loader.d.ts","sourceRoot":"","sources":["../../src/loader/custom-skill-loader.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAIvD;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,GAAE,MAAsB,GAAG,eAAe,EAAE,CAiC/E;AAwDD;;GAEG;AACH,wBAAgB,qBAAqB,IAAI,MAAM,CA2B9C"}
1
+ {"version":3,"file":"custom-skill-loader.d.ts","sourceRoot":"","sources":["../../src/loader/custom-skill-loader.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAIvD;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,GAAE,MAAsB,GAAG,eAAe,EAAE,CAwC/E;AAwDD;;GAEG;AACH,wBAAgB,qBAAqB,IAAI,MAAM,CA2B9C;AAED;;;GAGG;AACH,wBAAgB,uBAAuB,IAAI,MAAM,CAiChD"}
@@ -1,7 +1,7 @@
1
1
  "use strict";
2
2
  /**
3
3
  * 自定义 Skill 加载器
4
- * 从项目的 .ethan/skills/ 目录加载用户自定义 Skill(YAML 或 JSON 格式)
4
+ * 从项目的 .ethan/skills/ 目录加载用户自定义 Skill(YAML、JSONMarkdown 格式)
5
5
  */
6
6
  var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
7
7
  if (k2 === undefined) k2 = k;
@@ -39,23 +39,31 @@ var __importStar = (this && this.__importStar) || (function () {
39
39
  Object.defineProperty(exports, "__esModule", { value: true });
40
40
  exports.loadCustomSkills = loadCustomSkills;
41
41
  exports.generateSkillTemplate = generateSkillTemplate;
42
+ exports.generateMdSkillTemplate = generateMdSkillTemplate;
42
43
  const fs = __importStar(require("fs"));
43
44
  const path = __importStar(require("path"));
44
45
  const CUSTOM_SKILLS_DIR = '.ethan/skills';
45
46
  /**
46
47
  * 从指定目录加载自定义 Skill 定义
47
- * 支持 .yaml、.yml、.json 格式
48
+ * 支持 .yaml、.yml、.json、.md 格式
48
49
  */
49
50
  function loadCustomSkills(cwd = process.cwd()) {
50
51
  const skillsDir = path.join(cwd, CUSTOM_SKILLS_DIR);
51
52
  if (!fs.existsSync(skillsDir))
52
53
  return [];
53
- const files = fs.readdirSync(skillsDir).filter((f) => /\.(ya?ml|json)$/i.test(f));
54
+ const files = fs.readdirSync(skillsDir).filter((f) => /\.(ya?ml|json|md)$/i.test(f));
54
55
  const skills = [];
55
56
  for (const file of files) {
56
57
  const filePath = path.join(skillsDir, file);
57
58
  try {
58
59
  const raw = fs.readFileSync(filePath, 'utf-8');
60
+ if (/\.md$/i.test(file)) {
61
+ // .md 格式:YAML frontmatter + Markdown body 步骤
62
+ const skill = parseMdSkill(raw, file);
63
+ if (skill)
64
+ skills.push(skill);
65
+ continue;
66
+ }
59
67
  let data;
60
68
  if (/\.json$/i.test(file)) {
61
69
  data = JSON.parse(raw);
@@ -155,4 +163,105 @@ notes:
155
163
  - 使用注意事项(可选)
156
164
  `;
157
165
  }
166
+ /**
167
+ * 生成自定义 Skill 的 Markdown 模板文件
168
+ * 格式:YAML frontmatter(元数据)+ Markdown 正文(步骤,每个 ## 标题为一步)
169
+ */
170
+ function generateMdSkillTemplate() {
171
+ return `---
172
+ id: my-custom-skill
173
+ name: 自定义技能
174
+ nameEn: my_custom_skill
175
+ description: 一句话描述这个 Skill 的作用
176
+ detailDescription: 详细描述(可选,用于规则文件头部)
177
+ triggers:
178
+ - 自定义触发词
179
+ - custom skill
180
+ - '@ethan custom'
181
+ outputFormat: 描述输出格式(如:Markdown 文档、JSON 数据等)
182
+ category: 质量侧
183
+ order: 100
184
+ notes:
185
+ - 使用注意事项(可选)
186
+ ---
187
+
188
+ ## 1. 第一步标题
189
+
190
+ - 步骤详细说明
191
+ - 支持任意 Markdown 格式
192
+
193
+ **重点内容**可以加粗,也可以使用代码块:
194
+
195
+ \`\`\`
196
+ 示例代码
197
+ \`\`\`
198
+
199
+ ## 2. 第二步标题
200
+
201
+ 继续描述步骤内容...
202
+ `;
203
+ }
204
+ /**
205
+ * 解析 .md 格式的 Skill 文件
206
+ * 格式:YAML frontmatter(元数据)+ Markdown 正文(## 标题为步骤)
207
+ */
208
+ function parseMdSkill(raw, filename) {
209
+ const fmMatch = raw.match(/^---\r?\n([\s\S]+?)\r?\n---\r?\n?([\s\S]*)$/);
210
+ if (!fmMatch) {
211
+ console.warn(` ⚠️ ${filename}: .md Skill 必须以 YAML frontmatter 开头(--- ... ---)`);
212
+ return null;
213
+ }
214
+ let meta;
215
+ try {
216
+ // eslint-disable-next-line @typescript-eslint/no-require-imports
217
+ const yaml = require('js-yaml');
218
+ meta = yaml.load(fmMatch[1]);
219
+ }
220
+ catch (err) {
221
+ console.warn(` ⚠️ ${filename}: YAML frontmatter 解析失败 — ${err.message}`);
222
+ return null;
223
+ }
224
+ if (typeof meta !== 'object' || meta === null) {
225
+ console.warn(` ⚠️ ${filename}: frontmatter 必须是对象`);
226
+ return null;
227
+ }
228
+ const body = fmMatch[2].trim();
229
+ const mdSteps = parseMdSteps(body);
230
+ // body 中的步骤优先;若 body 无 ## 标题则 fallback 到 frontmatter.steps
231
+ const data = {
232
+ ...meta,
233
+ ...(mdSteps.length > 0 ? { steps: mdSteps } : {}),
234
+ };
235
+ return validateCustomSkill(data, filename);
236
+ }
237
+ /**
238
+ * 从 Markdown 正文中提取步骤
239
+ * 每个 ## 或 ### 标题 → 一个步骤(title = 标题文字,content = 标题到下一标题前的内容)
240
+ */
241
+ function parseMdSteps(body) {
242
+ const steps = [];
243
+ if (!body)
244
+ return steps;
245
+ const lines = body.split(/\r?\n/);
246
+ let currentTitle = '';
247
+ const currentContent = [];
248
+ const flush = () => {
249
+ if (currentTitle) {
250
+ steps.push({ title: currentTitle, content: currentContent.join('\n').trim() });
251
+ currentContent.length = 0;
252
+ }
253
+ };
254
+ for (const line of lines) {
255
+ const headingMatch = line.match(/^#{2,3}\s+(.+)/);
256
+ if (headingMatch) {
257
+ flush();
258
+ currentTitle = headingMatch[1].trim();
259
+ }
260
+ else if (currentTitle) {
261
+ currentContent.push(line);
262
+ }
263
+ }
264
+ flush();
265
+ return steps;
266
+ }
158
267
  //# sourceMappingURL=custom-skill-loader.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"custom-skill-loader.js","sourceRoot":"","sources":["../../src/loader/custom-skill-loader.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"custom-skill-loader.js","sourceRoot":"","sources":["../../src/loader/custom-skill-loader.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=custom-skill-loader.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"custom-skill-loader.test.d.ts","sourceRoot":"","sources":["../../src/loader/custom-skill-loader.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,201 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ const vitest_1 = require("vitest");
37
+ const fs = __importStar(require("fs"));
38
+ const path = __importStar(require("path"));
39
+ const os = __importStar(require("os"));
40
+ const custom_skill_loader_1 = require("./custom-skill-loader");
41
+ // ─── helpers ──────────────────────────────────────────────────────────────────
42
+ function mkTmpDir() {
43
+ return fs.mkdtempSync(path.join(os.tmpdir(), 'ethan-loader-'));
44
+ }
45
+ function writeSkillFile(dir, filename, content) {
46
+ const skillsDir = path.join(dir, '.ethan', 'skills');
47
+ fs.mkdirSync(skillsDir, { recursive: true });
48
+ fs.writeFileSync(path.join(skillsDir, filename), content, 'utf-8');
49
+ }
50
+ // ─── YAML loader (existing) ───────────────────────────────────────────────────
51
+ (0, vitest_1.describe)('loadCustomSkills — YAML', () => {
52
+ let tmpDir;
53
+ (0, vitest_1.beforeEach)(() => { tmpDir = mkTmpDir(); });
54
+ (0, vitest_1.afterEach)(() => { fs.rmSync(tmpDir, { recursive: true, force: true }); });
55
+ (0, vitest_1.it)('returns [] when .ethan/skills does not exist', () => {
56
+ (0, vitest_1.expect)((0, custom_skill_loader_1.loadCustomSkills)(tmpDir)).toEqual([]);
57
+ });
58
+ (0, vitest_1.it)('loads a valid YAML skill', () => {
59
+ writeSkillFile(tmpDir, 'test.yaml', (0, custom_skill_loader_1.generateSkillTemplate)());
60
+ const skills = (0, custom_skill_loader_1.loadCustomSkills)(tmpDir);
61
+ (0, vitest_1.expect)(skills).toHaveLength(1);
62
+ (0, vitest_1.expect)(skills[0].id).toBe('my-custom-skill');
63
+ (0, vitest_1.expect)(skills[0].order).toBe(100);
64
+ });
65
+ (0, vitest_1.it)('warns and skips invalid YAML skill (missing required field)', () => {
66
+ writeSkillFile(tmpDir, 'bad.yaml', 'id: only-id\nname: X\n');
67
+ const skills = (0, custom_skill_loader_1.loadCustomSkills)(tmpDir);
68
+ (0, vitest_1.expect)(skills).toHaveLength(0);
69
+ });
70
+ });
71
+ // ─── Markdown loader (new) ────────────────────────────────────────────────────
72
+ const VALID_MD = `---
73
+ id: md-skill
74
+ name: MD 技能
75
+ nameEn: md_skill
76
+ description: Markdown 格式的测试 Skill
77
+ triggers:
78
+ - md 技能
79
+ - md skill
80
+ outputFormat: Markdown 文档
81
+ order: 101
82
+ ---
83
+
84
+ ## 1. 第一步
85
+
86
+ - 步骤说明 A
87
+ - 步骤说明 B
88
+
89
+ ## 2. 第二步
90
+
91
+ 详细内容...
92
+ `;
93
+ (0, vitest_1.describe)('loadCustomSkills — Markdown (.md)', () => {
94
+ let tmpDir;
95
+ (0, vitest_1.beforeEach)(() => { tmpDir = mkTmpDir(); });
96
+ (0, vitest_1.afterEach)(() => { fs.rmSync(tmpDir, { recursive: true, force: true }); });
97
+ (0, vitest_1.it)('loads a valid .md skill with frontmatter + body steps', () => {
98
+ writeSkillFile(tmpDir, 'test.md', VALID_MD);
99
+ const skills = (0, custom_skill_loader_1.loadCustomSkills)(tmpDir);
100
+ (0, vitest_1.expect)(skills).toHaveLength(1);
101
+ const s = skills[0];
102
+ (0, vitest_1.expect)(s.id).toBe('md-skill');
103
+ (0, vitest_1.expect)(s.name).toBe('MD 技能');
104
+ (0, vitest_1.expect)(s.nameEn).toBe('md_skill');
105
+ (0, vitest_1.expect)(s.order).toBe(101);
106
+ (0, vitest_1.expect)(s.triggers).toContain('md skill');
107
+ });
108
+ (0, vitest_1.it)('parses body steps from ## headings', () => {
109
+ writeSkillFile(tmpDir, 'test.md', VALID_MD);
110
+ const skills = (0, custom_skill_loader_1.loadCustomSkills)(tmpDir);
111
+ (0, vitest_1.expect)(skills[0].steps).toHaveLength(2);
112
+ (0, vitest_1.expect)(skills[0].steps[0].title).toBe('1. 第一步');
113
+ (0, vitest_1.expect)(skills[0].steps[0].content).toContain('步骤说明 A');
114
+ (0, vitest_1.expect)(skills[0].steps[1].title).toBe('2. 第二步');
115
+ });
116
+ (0, vitest_1.it)('warns and skips .md without frontmatter', () => {
117
+ writeSkillFile(tmpDir, 'no-fm.md', '## Step 1\n\ncontent\n');
118
+ (0, vitest_1.expect)((0, custom_skill_loader_1.loadCustomSkills)(tmpDir)).toHaveLength(0);
119
+ });
120
+ (0, vitest_1.it)('warns and skips .md missing required fields in frontmatter', () => {
121
+ writeSkillFile(tmpDir, 'missing.md', '---\nid: x\nname: X\n---\n\n## Step\nok\n');
122
+ (0, vitest_1.expect)((0, custom_skill_loader_1.loadCustomSkills)(tmpDir)).toHaveLength(0);
123
+ });
124
+ (0, vitest_1.it)('falls back to frontmatter steps when body has no ## headings', () => {
125
+ const mdWithFmSteps = `---
126
+ id: fm-steps-skill
127
+ name: FM Steps
128
+ nameEn: fm_steps_skill
129
+ description: fallback test
130
+ triggers:
131
+ - fm steps
132
+ outputFormat: doc
133
+ steps:
134
+ - title: "Step from FM"
135
+ content: "From frontmatter"
136
+ ---
137
+
138
+ This body has no headings, just prose.
139
+ `;
140
+ writeSkillFile(tmpDir, 'fmsteps.md', mdWithFmSteps);
141
+ const skills = (0, custom_skill_loader_1.loadCustomSkills)(tmpDir);
142
+ (0, vitest_1.expect)(skills).toHaveLength(1);
143
+ (0, vitest_1.expect)(skills[0].steps[0].title).toBe('Step from FM');
144
+ });
145
+ (0, vitest_1.it)('body steps take precedence over frontmatter steps when both present', () => {
146
+ const md = `---
147
+ id: both-steps
148
+ name: Both
149
+ nameEn: both_steps
150
+ description: test
151
+ triggers:
152
+ - both
153
+ outputFormat: doc
154
+ steps:
155
+ - title: "FM Step"
156
+ content: "should be ignored"
157
+ ---
158
+
159
+ ## Body Step
160
+
161
+ body step content
162
+ `;
163
+ writeSkillFile(tmpDir, 'both.md', md);
164
+ const skills = (0, custom_skill_loader_1.loadCustomSkills)(tmpDir);
165
+ (0, vitest_1.expect)(skills[0].steps[0].title).toBe('Body Step');
166
+ });
167
+ (0, vitest_1.it)('loads both .yaml and .md files from the same directory', () => {
168
+ writeSkillFile(tmpDir, 'yaml-skill.yaml', (0, custom_skill_loader_1.generateSkillTemplate)());
169
+ writeSkillFile(tmpDir, 'md-skill.md', VALID_MD);
170
+ const skills = (0, custom_skill_loader_1.loadCustomSkills)(tmpDir);
171
+ (0, vitest_1.expect)(skills).toHaveLength(2);
172
+ const ids = skills.map((s) => s.id);
173
+ (0, vitest_1.expect)(ids).toContain('my-custom-skill');
174
+ (0, vitest_1.expect)(ids).toContain('md-skill');
175
+ });
176
+ });
177
+ // ─── generateMdSkillTemplate ──────────────────────────────────────────────────
178
+ (0, vitest_1.describe)('generateMdSkillTemplate', () => {
179
+ let tmpDir;
180
+ (0, vitest_1.beforeEach)(() => { tmpDir = mkTmpDir(); });
181
+ (0, vitest_1.afterEach)(() => { fs.rmSync(tmpDir, { recursive: true, force: true }); });
182
+ (0, vitest_1.it)('returns a non-empty string starting with ---', () => {
183
+ const tpl = (0, custom_skill_loader_1.generateMdSkillTemplate)();
184
+ (0, vitest_1.expect)(typeof tpl).toBe('string');
185
+ (0, vitest_1.expect)(tpl.startsWith('---')).toBe(true);
186
+ });
187
+ (0, vitest_1.it)('generated template is parseable and produces a valid skill after editing', () => {
188
+ // Replace placeholder values with valid data
189
+ const filled = (0, custom_skill_loader_1.generateMdSkillTemplate)()
190
+ .replace('id: my-custom-skill', 'id: tpl-test')
191
+ .replace('name: 自定义技能', 'name: 模板测试')
192
+ .replace('nameEn: my_custom_skill', 'nameEn: tpl_test')
193
+ .replace('description: 一句话描述这个 Skill 的作用', 'description: template test');
194
+ writeSkillFile(tmpDir, 'tpl-test.md', filled);
195
+ const skills = (0, custom_skill_loader_1.loadCustomSkills)(tmpDir);
196
+ (0, vitest_1.expect)(skills).toHaveLength(1);
197
+ (0, vitest_1.expect)(skills[0].id).toBe('tpl-test');
198
+ (0, vitest_1.expect)(skills[0].steps.length).toBeGreaterThanOrEqual(1);
199
+ });
200
+ });
201
+ //# sourceMappingURL=custom-skill-loader.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"custom-skill-loader.test.js","sourceRoot":"","sources":["../../src/loader/custom-skill-loader.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { SkillDefinition } from './types';
2
+ export declare const apiDesignSkill: SkillDefinition;
3
+ //# sourceMappingURL=11-api-design.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"11-api-design.d.ts","sourceRoot":"","sources":["../../src/skills/11-api-design.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAE/C,eAAO,MAAM,cAAc,EAAE,eAkN5B,CAAC"}