sillyspec 3.7.6 → 3.7.8

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sillyspec",
3
- "version": "3.7.6",
3
+ "version": "3.7.8",
4
4
  "description": "SillySpec CLI — 流程状态机,让 AI 严格按步骤来",
5
5
  "type": "module",
6
6
  "bin": {
package/src/setup.js CHANGED
@@ -17,7 +17,7 @@ const SKILLS = [
17
17
  name: 'Playwright E2E 测试参考',
18
18
  description: 'E2E 测试编写最佳实践,AI 执行测试任务时自动读取',
19
19
  source: join(__dirname, '..', 'templates', 'skills', 'playwright-e2e'),
20
- target: '.sillyspec/skills/playwright-e2e',
20
+ target: 'playwright-e2e',
21
21
  },
22
22
  ];
23
23
 
@@ -40,6 +40,22 @@ const MCP_TOOLS = [
40
40
  args: ['chrome-devtools-mcp@latest'],
41
41
  url: 'https://github.com/ChromeDevTools/chrome-devtools-mcp',
42
42
  },
43
+ {
44
+ id: 'agent-browser',
45
+ name: 'Agent Browser (Vercel)',
46
+ description: 'Rust 原生浏览器 CLI,token 消耗极低,50+ 命令覆盖导航/表单/截图/网络',
47
+ command: 'npx',
48
+ args: ['@anthropic-ai/agent-browser@latest'],
49
+ url: 'https://github.com/vercel-labs/agent-browser',
50
+ },
51
+ {
52
+ id: 'pinchtab',
53
+ name: 'PinchTab',
54
+ description: '12MB Go 二进制,零依赖,accessibility tree 极省 token,有 MCP 支持',
55
+ command: 'npx',
56
+ args: ['pinchtab-mcp@latest'],
57
+ url: 'https://github.com/pinchtab/pinchtab',
58
+ },
43
59
  ];
44
60
 
45
61
  // ── 数据库 MCP 定义(需要连接信息)──
@@ -283,11 +299,20 @@ export async function cmdSetup(dir, options = {}) {
283
299
  ...globalChoices.length > 0 ? [{ name: chalk.bold('── 全局工具 ──'), value: '_global_header', disabled: true }] : [],
284
300
  ...globalChoices,
285
301
  ...[{ name: chalk.bold('── AI Skills(编写参考)──'), value: '_skill_header', disabled: true }],
286
- ...SKILLS.filter(s => !existsSync(join(dir, s.target, 'SKILL.md'))).map(s => ({
287
- name: `${s.name} ${s.description}`,
288
- value: `skill:${s.id}`,
289
- checked: false,
290
- })),
302
+ ...(() => {
303
+ const installed = new Set();
304
+ for (const { path } of availableTools) {
305
+ const skillDir = join(dir, dirname(path), 'skills');
306
+ for (const s of SKILLS) {
307
+ if (existsSync(join(skillDir, s.target, 'SKILL.md'))) installed.add(s.id);
308
+ }
309
+ }
310
+ return SKILLS.filter(s => !installed.has(s.id)).map(s => ({
311
+ name: `${s.name} — ${s.description}`,
312
+ value: `skill:${s.id}`,
313
+ checked: false,
314
+ }));
315
+ })(),
291
316
  ];
292
317
 
293
318
  if (allChoices.length === 0) {
@@ -382,16 +407,32 @@ export async function cmdSetup(dir, options = {}) {
382
407
  const selectedSkills = SKILLS.filter(s => selected.includes(`skill:${s.id}`));
383
408
 
384
409
  if (selectedSkills.length > 0) {
410
+ // 跟 MCP 一样,选择安装到哪些 AI 工具
411
+ const skillTargets = availableTools.map(t => ({
412
+ name: t.tool,
413
+ value: t.key,
414
+ checked: true,
415
+ }));
416
+
417
+ const selectedTools = await checkbox({
418
+ message: 'Skill 安装到哪些 AI 工具?',
419
+ choices: skillTargets,
420
+ });
421
+
422
+ const targets = availableTools.filter(t => selectedTools.includes(t.key));
423
+
385
424
  console.log('');
386
- for (const skill of selectedSkills) {
387
- const spinner = ora(`安装 ${skill.name}...`).start();
388
- try {
389
- const targetDir = join(dir, skill.target);
390
- mkdirSync(targetDir, { recursive: true });
391
- cpSync(skill.source, targetDir, { recursive: true });
392
- spinner.succeed(`${skill.name} 安装完成 ${skill.target}/SKILL.md`);
393
- } catch (err) {
394
- spinner.fail(`${skill.name} 安装失败: ${err.message}`);
425
+ for (const { tool, path } of targets) {
426
+ const spinner = ora(`安装 Skills 到 ${tool}...`).start();
427
+ for (const skill of selectedSkills) {
428
+ try {
429
+ const targetDir = join(dir, dirname(path), 'skills', skill.target);
430
+ mkdirSync(targetDir, { recursive: true });
431
+ cpSync(skill.source, targetDir, { recursive: true });
432
+ spinner.succeed(`${tool} ${dirname(path)}/skills/${skill.target}/SKILL.md`);
433
+ } catch (err) {
434
+ spinner.fail(`${skill.name} 安装失败: ${err.message}`);
435
+ }
395
436
  }
396
437
  }
397
438
  }
@@ -139,6 +139,21 @@ find tests/e2e e2e cypress/e2e __tests__ src -name "*.spec.ts" -o -name "*.test.
139
139
  > **11. 参照已有测试风格:** 编写新测试时必须参照以上「测试模式参考」中的风格,包括断言方式、fixtures 使用、文件组织。不要凭记忆写测试。
140
140
  > **12. 参考已有实现:** 写新功能前,先 grep 项目中类似功能的已有代码(`grep -r "关键词" src/`),照着项目现有的模式、风格和封装方式写,不要凭记忆编造。
141
141
 
142
+ **Skill 扫描(主代理执行):**
143
+ 对每个子代理 dispatch 前,扫描项目中已安装的 skill,匹配相关 skill 注入子代理 prompt 的「本地 Skills」段。
144
+
145
+ ```bash
146
+ for skill_dir in .claude/skills/*/SKILL.md .cursor/skills/*/SKILL.md .opencode/skills/*/SKILL.md; do
147
+ [ -f "$skill_dir" ] && echo "=== $skill_dir ===" && cat "$skill_dir"
148
+ done
149
+ ```
150
+
151
+ 扫描后,根据当前任务描述的关键词匹配 skill 的 name 和 description:
152
+ - 任务包含"E2E"/"端到端"/"测试用例" → 匹配 playwright-e2e skill
153
+ - 未来可扩展更多 skill
154
+
155
+ 匹配到的 skill → 将 SKILL.md 全文注入子代理 prompt。未匹配则省略该段。
156
+
142
157
  **MCP 能力检测(主代理执行):**
143
158
  检查当前可用工具列表中是否存在以下类型的 MCP 工具(不要只依赖配置文件路径,不同客户端配置位置不同):
144
159
  - Context7 / 文档查询工具
@@ -209,6 +224,9 @@ find tests/e2e e2e cypress/e2e __tests__ src -name "*.spec.ts" -o -name "*.test.
209
224
  ## 文档查询指引
210
225
  {主代理根据 MCP 检测结果动态注入:有 Context7 提示用 MCP,无则提示用 web search}
211
226
 
227
+ ## 本地 Skills(如有)
228
+ {主代理在 dispatch 前扫描 .claude/skills/、.cursor/skills/、.opencode/skills/ 下的 SKILL.md,根据当前任务关键词匹配相关 skill,将 SKILL.md 全文注入此段。无匹配 skill 则省略此段。}
229
+
212
230
  ## 数据操作
213
231
  {主代理根据 MCP 检测结果动态注入:如检测到数据库 MCP,提示可用}
214
232
  ⛔ 任何改变现有数据的操作(DML: INSERT/UPDATE/DELETE/DML、DDL: ALTER/DROP/TRUNCATE/RENAME,以及所有非 SELECT 的数据库操作)必须暂停并报告给用户确认,不得自动执行。新建表不受此限制。
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: playwright-e2e
3
- description: Playwright E2E 测试编写参考。AI 执行 E2E 任务时自动读取,不要凭记忆编写 Playwright API。
3
+ description: Playwright E2E 测试编写参考。当任务涉及编写端到端测试、浏览器自动化测试、Playwright 测试用例时自动读取,不要凭记忆编写 Playwright API。
4
4
  ---
5
5
 
6
6
  # Playwright E2E 测试编写参考