beth-copilot 1.1.0 → 2.0.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.
- package/CHANGELOG.md +39 -1
- package/README.md +51 -62
- package/assets/beth-questioning.png +0 -0
- package/assets/yellowstone-beth.png +0 -0
- package/bin/cli.js +19 -410
- package/dist/__tests__/inject-skills.test.d.ts +9 -0
- package/dist/__tests__/inject-skills.test.d.ts.map +1 -0
- package/dist/__tests__/inject-skills.test.js +143 -0
- package/dist/__tests__/inject-skills.test.js.map +1 -0
- package/dist/__tests__/skills/disambiguation.test.d.ts +10 -0
- package/dist/__tests__/skills/disambiguation.test.d.ts.map +1 -0
- package/dist/__tests__/skills/disambiguation.test.js +192 -0
- package/dist/__tests__/skills/disambiguation.test.js.map +1 -0
- package/dist/__tests__/skills/hook-injection.test.d.ts +11 -0
- package/dist/__tests__/skills/hook-injection.test.d.ts.map +1 -0
- package/dist/__tests__/skills/hook-injection.test.js +173 -0
- package/dist/__tests__/skills/hook-injection.test.js.map +1 -0
- package/dist/__tests__/skills/mapping-completeness.test.d.ts +17 -0
- package/dist/__tests__/skills/mapping-completeness.test.d.ts.map +1 -0
- package/dist/__tests__/skills/mapping-completeness.test.js +281 -0
- package/dist/__tests__/skills/mapping-completeness.test.js.map +1 -0
- package/dist/__tests__/skills/pipeline-integration.test.d.ts +18 -0
- package/dist/__tests__/skills/pipeline-integration.test.d.ts.map +1 -0
- package/dist/__tests__/skills/pipeline-integration.test.js +234 -0
- package/dist/__tests__/skills/pipeline-integration.test.js.map +1 -0
- package/dist/__tests__/skills/skill-routing.test.d.ts +15 -0
- package/dist/__tests__/skills/skill-routing.test.d.ts.map +1 -0
- package/dist/__tests__/skills/skill-routing.test.js +723 -0
- package/dist/__tests__/skills/skill-routing.test.js.map +1 -0
- package/dist/__tests__/skills/trigger-coverage.test.d.ts +24 -0
- package/dist/__tests__/skills/trigger-coverage.test.d.ts.map +1 -0
- package/dist/__tests__/skills/trigger-coverage.test.js +746 -0
- package/dist/__tests__/skills/trigger-coverage.test.js.map +1 -0
- package/dist/__tests__/smoke.test.js +13 -0
- package/dist/__tests__/smoke.test.js.map +1 -1
- package/dist/__tests__/verify-skills.test.d.ts +9 -0
- package/dist/__tests__/verify-skills.test.d.ts.map +1 -0
- package/dist/__tests__/verify-skills.test.js +78 -0
- package/dist/__tests__/verify-skills.test.js.map +1 -0
- package/dist/cli/commands/beads.e2e.test.d.ts +4 -2
- package/dist/cli/commands/beads.e2e.test.d.ts.map +1 -1
- package/dist/cli/commands/beads.e2e.test.js +97 -38
- package/dist/cli/commands/beads.e2e.test.js.map +1 -1
- package/dist/cli/commands/cli-edge-cases.e2e.test.js +1 -1
- package/dist/cli/commands/cli-edge-cases.e2e.test.js.map +1 -1
- package/dist/cli/commands/close.d.ts +11 -46
- package/dist/cli/commands/close.d.ts.map +1 -1
- package/dist/cli/commands/close.e2e.test.d.ts +4 -20
- package/dist/cli/commands/close.e2e.test.d.ts.map +1 -1
- package/dist/cli/commands/close.e2e.test.js +23 -204
- package/dist/cli/commands/close.e2e.test.js.map +1 -1
- package/dist/cli/commands/close.js +26 -240
- package/dist/cli/commands/close.js.map +1 -1
- package/dist/cli/commands/close.test.d.ts +7 -9
- package/dist/cli/commands/close.test.d.ts.map +1 -1
- package/dist/cli/commands/close.test.js +44 -424
- package/dist/cli/commands/close.test.js.map +1 -1
- package/dist/cli/commands/doctor.d.ts +5 -22
- package/dist/cli/commands/doctor.d.ts.map +1 -1
- package/dist/cli/commands/doctor.e2e.test.js +3 -59
- package/dist/cli/commands/doctor.e2e.test.js.map +1 -1
- package/dist/cli/commands/doctor.js +38 -111
- package/dist/cli/commands/doctor.js.map +1 -1
- package/dist/cli/commands/doctor.test.js +32 -234
- package/dist/cli/commands/doctor.test.js.map +1 -1
- package/dist/cli/commands/framework-isolation.test.d.ts +1 -1
- package/dist/cli/commands/framework-isolation.test.js +2 -3
- package/dist/cli/commands/framework-isolation.test.js.map +1 -1
- package/dist/cli/commands/help.e2e.test.js +1 -5
- package/dist/cli/commands/help.e2e.test.js.map +1 -1
- package/dist/cli/commands/init-logic.e2e.test.js +12 -2
- package/dist/cli/commands/init-logic.e2e.test.js.map +1 -1
- package/dist/cli/commands/init.test.js +4 -21
- package/dist/cli/commands/init.test.js.map +1 -1
- package/dist/cli/commands/land.d.ts +3 -15
- package/dist/cli/commands/land.d.ts.map +1 -1
- package/dist/cli/commands/land.js +13 -68
- package/dist/cli/commands/land.js.map +1 -1
- package/dist/cli/commands/land.test.d.ts +0 -1
- package/dist/cli/commands/land.test.d.ts.map +1 -1
- package/dist/cli/commands/land.test.js +2 -57
- package/dist/cli/commands/land.test.js.map +1 -1
- package/dist/cli/commands/mcp.e2e.test.js +3 -3
- package/dist/cli/commands/mcp.e2e.test.js.map +1 -1
- package/dist/cli/commands/pipeline.e2e.test.js +23 -26
- package/dist/cli/commands/pipeline.e2e.test.js.map +1 -1
- package/dist/cli/commands/pre-push-guard.d.ts +2 -12
- package/dist/cli/commands/pre-push-guard.d.ts.map +1 -1
- package/dist/cli/commands/pre-push-guard.e2e.test.js +1 -1
- package/dist/cli/commands/pre-push-guard.e2e.test.js.map +1 -1
- package/dist/cli/commands/pre-push-guard.js +2 -47
- package/dist/cli/commands/pre-push-guard.js.map +1 -1
- package/dist/cli/commands/pre-push-guard.test.d.ts +0 -1
- package/dist/cli/commands/pre-push-guard.test.d.ts.map +1 -1
- package/dist/cli/commands/pre-push-guard.test.js +15 -98
- package/dist/cli/commands/pre-push-guard.test.js.map +1 -1
- package/dist/cli/commands/quickstart-expanded.e2e.test.d.ts +1 -1
- package/dist/cli/commands/quickstart-expanded.e2e.test.js +3 -30
- package/dist/cli/commands/quickstart-expanded.e2e.test.js.map +1 -1
- package/dist/cli/commands/quickstart.d.ts +0 -1
- package/dist/cli/commands/quickstart.d.ts.map +1 -1
- package/dist/cli/commands/quickstart.js +2 -60
- package/dist/cli/commands/quickstart.js.map +1 -1
- package/dist/cli/commands/quickstart.test.js +10 -104
- package/dist/cli/commands/quickstart.test.js.map +1 -1
- package/dist/cli/commands/update.d.ts +35 -0
- package/dist/cli/commands/update.d.ts.map +1 -0
- package/dist/cli/commands/update.e2e.test.d.ts +24 -0
- package/dist/cli/commands/update.e2e.test.d.ts.map +1 -0
- package/dist/cli/commands/update.e2e.test.js +240 -0
- package/dist/cli/commands/update.e2e.test.js.map +1 -0
- package/dist/cli/commands/update.js +255 -0
- package/dist/cli/commands/update.js.map +1 -0
- package/dist/core/agents/frontmatter.test.js +1 -1
- package/dist/core/agents/frontmatter.test.js.map +1 -1
- package/dist/core/agents/handoffs.test.js +1 -1
- package/dist/core/agents/handoffs.test.js.map +1 -1
- package/dist/core/agents/loader.d.ts +4 -2
- package/dist/core/agents/loader.d.ts.map +1 -1
- package/dist/core/agents/loader.js +5 -3
- package/dist/core/agents/loader.js.map +1 -1
- package/dist/core/agents/loader.test.js +42 -4
- package/dist/core/agents/loader.test.js.map +1 -1
- package/dist/core/agents/suite.test.js +8 -7
- package/dist/core/agents/suite.test.js.map +1 -1
- package/dist/core/agents/tools.test.js +10 -8
- package/dist/core/agents/tools.test.js.map +1 -1
- package/dist/core/agents/types.test.js +1 -1
- package/dist/core/agents/types.test.js.map +1 -1
- package/dist/core/skills/loader.test.js +1 -1
- package/dist/core/skills/loader.test.js.map +1 -1
- package/dist/index.d.ts +0 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +0 -2
- package/dist/index.js.map +1 -1
- package/dist/lib/pathValidation.d.ts +0 -5
- package/dist/lib/pathValidation.d.ts.map +1 -1
- package/dist/lib/pathValidation.js +0 -11
- package/dist/lib/pathValidation.js.map +1 -1
- package/dist/lib/pathValidation.test.js +2 -14
- package/dist/lib/pathValidation.test.js.map +1 -1
- package/package.json +3 -6
- package/sbom.json +259 -371
- package/templates/.github/agents/beth.agent.md +194 -122
- package/templates/.github/agents/developer.agent.md +30 -22
- package/templates/.github/agents/product-manager.agent.md +15 -6
- package/templates/.github/agents/researcher.agent.md +10 -7
- package/templates/.github/agents/security-reviewer.agent.md +16 -7
- package/templates/.github/agents/tester.agent.md +16 -8
- package/templates/.github/agents/ux-designer.agent.md +12 -9
- package/templates/.github/copilot-instructions.md +33 -4
- package/templates/.github/copilot-mcp-config.json +12 -0
- package/templates/.github/dependabot.yml +68 -0
- package/templates/.github/hooks/scripts/inject-skills.mjs +139 -0
- package/templates/.github/hooks/scripts/verify-skills.mjs +47 -0
- package/templates/.github/hooks/skill-enforcement.json +18 -0
- package/templates/.github/pull_request_template.md +48 -0
- package/templates/.github/skills/framer-components/SKILL.md +0 -0
- package/templates/.github/skills/prd/SKILL.md +0 -0
- package/templates/.github/skills/security-analysis/SKILL.md +798 -798
- package/templates/.github/skills/shadcn-ui/SKILL.md +561 -561
- package/templates/.github/skills/vercel-react-best-practices/AGENTS.md +0 -0
- package/templates/.github/skills/vercel-react-best-practices/SKILL.md +0 -0
- package/templates/.github/skills/vercel-react-best-practices/rules/advanced-event-handler-refs.md +0 -0
- package/templates/.github/skills/vercel-react-best-practices/rules/advanced-use-latest.md +0 -0
- package/templates/.github/skills/vercel-react-best-practices/rules/async-api-routes.md +0 -0
- package/templates/.github/skills/vercel-react-best-practices/rules/async-defer-await.md +0 -0
- package/templates/.github/skills/vercel-react-best-practices/rules/async-dependencies.md +0 -0
- package/templates/.github/skills/vercel-react-best-practices/rules/async-parallel.md +0 -0
- package/templates/.github/skills/vercel-react-best-practices/rules/async-suspense-boundaries.md +0 -0
- package/templates/.github/skills/vercel-react-best-practices/rules/bundle-barrel-imports.md +0 -0
- package/templates/.github/skills/vercel-react-best-practices/rules/bundle-conditional.md +0 -0
- package/templates/.github/skills/vercel-react-best-practices/rules/bundle-defer-third-party.md +0 -0
- package/templates/.github/skills/vercel-react-best-practices/rules/bundle-dynamic-imports.md +0 -0
- package/templates/.github/skills/vercel-react-best-practices/rules/bundle-preload.md +0 -0
- package/templates/.github/skills/vercel-react-best-practices/rules/client-event-listeners.md +0 -0
- package/templates/.github/skills/vercel-react-best-practices/rules/client-localstorage-schema.md +0 -0
- package/templates/.github/skills/vercel-react-best-practices/rules/client-passive-event-listeners.md +0 -0
- package/templates/.github/skills/vercel-react-best-practices/rules/client-swr-dedup.md +0 -0
- package/templates/.github/skills/vercel-react-best-practices/rules/js-batch-dom-css.md +0 -0
- package/templates/.github/skills/vercel-react-best-practices/rules/js-cache-function-results.md +0 -0
- package/templates/.github/skills/vercel-react-best-practices/rules/js-cache-property-access.md +0 -0
- package/templates/.github/skills/vercel-react-best-practices/rules/js-cache-storage.md +0 -0
- package/templates/.github/skills/vercel-react-best-practices/rules/js-combine-iterations.md +0 -0
- package/templates/.github/skills/vercel-react-best-practices/rules/js-early-exit.md +0 -0
- package/templates/.github/skills/vercel-react-best-practices/rules/js-hoist-regexp.md +0 -0
- package/templates/.github/skills/vercel-react-best-practices/rules/js-index-maps.md +0 -0
- package/templates/.github/skills/vercel-react-best-practices/rules/js-length-check-first.md +0 -0
- package/templates/.github/skills/vercel-react-best-practices/rules/js-min-max-loop.md +0 -0
- package/templates/.github/skills/vercel-react-best-practices/rules/js-set-map-lookups.md +0 -0
- package/templates/.github/skills/vercel-react-best-practices/rules/js-tosorted-immutable.md +0 -0
- package/templates/.github/skills/vercel-react-best-practices/rules/rendering-activity.md +0 -0
- package/templates/.github/skills/vercel-react-best-practices/rules/rendering-animate-svg-wrapper.md +0 -0
- package/templates/.github/skills/vercel-react-best-practices/rules/rendering-conditional-render.md +0 -0
- package/templates/.github/skills/vercel-react-best-practices/rules/rendering-content-visibility.md +0 -0
- package/templates/.github/skills/vercel-react-best-practices/rules/rendering-hoist-jsx.md +0 -0
- package/templates/.github/skills/vercel-react-best-practices/rules/rendering-hydration-no-flicker.md +0 -0
- package/templates/.github/skills/vercel-react-best-practices/rules/rendering-svg-precision.md +0 -0
- package/templates/.github/skills/vercel-react-best-practices/rules/rerender-defer-reads.md +0 -0
- package/templates/.github/skills/vercel-react-best-practices/rules/rerender-dependencies.md +0 -0
- package/templates/.github/skills/vercel-react-best-practices/rules/rerender-derived-state.md +0 -0
- package/templates/.github/skills/vercel-react-best-practices/rules/rerender-functional-setstate.md +0 -0
- package/templates/.github/skills/vercel-react-best-practices/rules/rerender-lazy-state-init.md +0 -0
- package/templates/.github/skills/vercel-react-best-practices/rules/rerender-memo.md +0 -0
- package/templates/.github/skills/vercel-react-best-practices/rules/rerender-simple-expression-in-memo.md +0 -0
- package/templates/.github/skills/vercel-react-best-practices/rules/rerender-transitions.md +0 -0
- package/templates/.github/skills/vercel-react-best-practices/rules/server-after-nonblocking.md +0 -0
- package/templates/.github/skills/vercel-react-best-practices/rules/server-auth-actions.md +0 -0
- package/templates/.github/skills/vercel-react-best-practices/rules/server-cache-lru.md +0 -0
- package/templates/.github/skills/vercel-react-best-practices/rules/server-cache-react.md +0 -0
- package/templates/.github/skills/vercel-react-best-practices/rules/server-dedup-props.md +0 -0
- package/templates/.github/skills/vercel-react-best-practices/rules/server-parallel-fetching.md +0 -0
- package/templates/.github/skills/vercel-react-best-practices/rules/server-serialization.md +0 -0
- package/templates/.github/skills/web-design-guidelines/SKILL.md +0 -0
- package/templates/.vscode/settings.json +16 -16
- package/templates/AGENTS.md +59 -98
- package/templates/Backlog.md +80 -80
- package/assets/beth-portrait-small.txt +0 -13
- package/assets/beth-portrait.txt +0 -60
- package/bin/beth-animation.sh +0 -155
- package/bin/lib/animation.js +0 -189
- package/bin/lib/pathValidation.js +0 -233
- package/bin/lib/pathValidation.test.js +0 -280
|
@@ -0,0 +1,746 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Skill Trigger Coverage Tests
|
|
3
|
+
*
|
|
4
|
+
* For each of the 72 test cases in docs/E2E-SKILL-TESTS.md, this test verifies
|
|
5
|
+
* that the expected skill's description/triggers actually CONTAIN keywords from
|
|
6
|
+
* the test prompt. This is the closest we can get to testing "given this prompt,
|
|
7
|
+
* will VS Code's skill matching engine pick the right skill?" without actually
|
|
8
|
+
* calling the LLM.
|
|
9
|
+
*
|
|
10
|
+
* Why this matters: The existing structural tests verify that SKILL.md files
|
|
11
|
+
* exist and are non-empty. But they don't verify that the skill's triggers
|
|
12
|
+
* would actually MATCH the prompt that should invoke them. A skill could exist
|
|
13
|
+
* but have triggers that don't overlap with how users would describe the task.
|
|
14
|
+
*
|
|
15
|
+
* Test approach:
|
|
16
|
+
* - Extract keywords from each test prompt (nouns and domain terms)
|
|
17
|
+
* - Read the skill's SKILL.md description/triggers section
|
|
18
|
+
* - Verify at least N keywords from the prompt appear in the skill content
|
|
19
|
+
* - This catches: missing triggers, wrong skill descriptions, keyword drift
|
|
20
|
+
*
|
|
21
|
+
* Test plan reference: docs/E2E-SKILL-TESTS.md — All categories
|
|
22
|
+
*/
|
|
23
|
+
import { describe, it, expect } from 'vitest';
|
|
24
|
+
import { join } from 'node:path';
|
|
25
|
+
import { readFileSync, existsSync } from 'node:fs';
|
|
26
|
+
const PROJECT_ROOT = process.cwd();
|
|
27
|
+
const EXTERNAL_SKILLS_DIR = join(process.env.HOME || '~', '.agents/skills');
|
|
28
|
+
// ─── Helpers ───────────────────────────────────────────────────────────────
|
|
29
|
+
function readSkillContent(test) {
|
|
30
|
+
const fullPath = test.external ? test.skillPath : join(PROJECT_ROOT, test.skillPath);
|
|
31
|
+
return readFileSync(fullPath, 'utf8').toLowerCase();
|
|
32
|
+
}
|
|
33
|
+
function skillFileExists(test) {
|
|
34
|
+
const fullPath = test.external ? test.skillPath : join(PROJECT_ROOT, test.skillPath);
|
|
35
|
+
return existsSync(fullPath);
|
|
36
|
+
}
|
|
37
|
+
/** Count how many keywords from the list appear in the content */
|
|
38
|
+
function countKeywordHits(content, keywords) {
|
|
39
|
+
const hits = [];
|
|
40
|
+
const misses = [];
|
|
41
|
+
for (const kw of keywords) {
|
|
42
|
+
if (content.includes(kw.toLowerCase())) {
|
|
43
|
+
hits.push(kw);
|
|
44
|
+
}
|
|
45
|
+
else {
|
|
46
|
+
misses.push(kw);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
return { hits, misses };
|
|
50
|
+
}
|
|
51
|
+
// ─── Category 1: Hook-Enforced (9 tests) ──────────────────────────────────
|
|
52
|
+
// These skills are loaded by hook, not by prompt matching — but the skill
|
|
53
|
+
// content should STILL contain relevant keywords (defense in depth).
|
|
54
|
+
const HOOK_ENFORCED = [
|
|
55
|
+
{
|
|
56
|
+
id: 1, skill: 'web-design-guidelines',
|
|
57
|
+
skillPath: '.github/skills/web-design-guidelines/SKILL.md',
|
|
58
|
+
agent: 'ux-designer',
|
|
59
|
+
testPrompt: 'Review the login page for accessibility compliance',
|
|
60
|
+
requiredKeywords: ['accessibility', 'review'],
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
id: 2, skill: 'framer-components',
|
|
64
|
+
skillPath: '.github/skills/framer-components/SKILL.md',
|
|
65
|
+
agent: 'ux-designer',
|
|
66
|
+
testPrompt: 'Create a Framer component with property controls for a card',
|
|
67
|
+
requiredKeywords: ['framer', 'component', 'property controls'],
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
id: 3, skill: 'ui-ux-pro-max',
|
|
71
|
+
skillPath: '.github/prompts/ui-ux-pro-max/PROMPT.md',
|
|
72
|
+
agent: 'ux-designer',
|
|
73
|
+
testPrompt: 'Design a color palette and style guide for the dashboard',
|
|
74
|
+
requiredKeywords: ['color', 'style'],
|
|
75
|
+
},
|
|
76
|
+
{
|
|
77
|
+
id: 4, skill: 'vercel-react-best-practices',
|
|
78
|
+
skillPath: '.github/skills/vercel-react-best-practices/SKILL.md',
|
|
79
|
+
agent: 'developer',
|
|
80
|
+
testPrompt: 'Optimize the data fetching in our Next.js product page',
|
|
81
|
+
requiredKeywords: ['react', 'next.js'],
|
|
82
|
+
},
|
|
83
|
+
{
|
|
84
|
+
id: 5, skill: 'shadcn-ui',
|
|
85
|
+
skillPath: '.github/skills/shadcn-ui/SKILL.md',
|
|
86
|
+
agent: 'developer',
|
|
87
|
+
testPrompt: 'Add a shadcn dialog component for the settings modal',
|
|
88
|
+
requiredKeywords: ['shadcn', 'component'],
|
|
89
|
+
},
|
|
90
|
+
{
|
|
91
|
+
id: 6, skill: 'vercel-react-best-practices',
|
|
92
|
+
skillPath: '.github/skills/vercel-react-best-practices/AGENTS.md',
|
|
93
|
+
agent: 'developer',
|
|
94
|
+
testPrompt: 'Refactor the server components to eliminate waterfalls',
|
|
95
|
+
requiredKeywords: ['server component', 'waterfall'],
|
|
96
|
+
},
|
|
97
|
+
{
|
|
98
|
+
id: 7, skill: 'prd',
|
|
99
|
+
skillPath: '.github/skills/prd/SKILL.md',
|
|
100
|
+
agent: 'product-manager',
|
|
101
|
+
testPrompt: 'Create a PRD for the user notifications feature',
|
|
102
|
+
requiredKeywords: ['prd', 'product requirements'],
|
|
103
|
+
},
|
|
104
|
+
{
|
|
105
|
+
id: 8, skill: 'security-analysis',
|
|
106
|
+
skillPath: '.github/skills/security-analysis/SKILL.md',
|
|
107
|
+
agent: 'security-reviewer',
|
|
108
|
+
testPrompt: 'Run an OWASP security review on the auth module',
|
|
109
|
+
requiredKeywords: ['owasp', 'security'],
|
|
110
|
+
},
|
|
111
|
+
{
|
|
112
|
+
id: 9, skill: 'web-design-guidelines',
|
|
113
|
+
skillPath: '.github/skills/web-design-guidelines/SKILL.md',
|
|
114
|
+
agent: 'tester',
|
|
115
|
+
testPrompt: 'Audit the checkout flow for WCAG 2.1 AA compliance',
|
|
116
|
+
requiredKeywords: ['accessibility', 'review'],
|
|
117
|
+
},
|
|
118
|
+
];
|
|
119
|
+
// ─── Category 2: Azure Skills (22 tests) ──────────────────────────────────
|
|
120
|
+
const AZURE_SKILLS = [
|
|
121
|
+
{
|
|
122
|
+
id: 10, skill: 'azure-prepare',
|
|
123
|
+
skillPath: '.github/skills/azure-prepare/SKILL.md',
|
|
124
|
+
agent: 'developer',
|
|
125
|
+
testPrompt: 'Create a new containerized Node.js app and deploy it to Azure Container Apps',
|
|
126
|
+
requiredKeywords: ['container', 'deploy', 'azure'],
|
|
127
|
+
},
|
|
128
|
+
{
|
|
129
|
+
id: 11, skill: 'azure-validate',
|
|
130
|
+
skillPath: '.github/skills/azure-validate/SKILL.md',
|
|
131
|
+
agent: 'developer',
|
|
132
|
+
testPrompt: "Validate my app's deployment readiness and check the Bicep configuration",
|
|
133
|
+
requiredKeywords: ['validate', 'bicep', 'deployment'],
|
|
134
|
+
},
|
|
135
|
+
{
|
|
136
|
+
id: 12, skill: 'azure-deploy',
|
|
137
|
+
skillPath: '.github/skills/azure-deploy/SKILL.md',
|
|
138
|
+
agent: 'developer',
|
|
139
|
+
testPrompt: 'Run azd up to push the app to production',
|
|
140
|
+
requiredKeywords: ['azd', 'deploy', 'production'],
|
|
141
|
+
},
|
|
142
|
+
{
|
|
143
|
+
id: 13, skill: 'azure-compute',
|
|
144
|
+
skillPath: '.github/skills/azure-compute/SKILL.md',
|
|
145
|
+
agent: 'developer',
|
|
146
|
+
testPrompt: 'Recommend the best VM size for our ML training workload on Azure',
|
|
147
|
+
requiredKeywords: ['vm', 'compute'],
|
|
148
|
+
},
|
|
149
|
+
{
|
|
150
|
+
id: 14, skill: 'azure-storage',
|
|
151
|
+
skillPath: '.github/skills/azure-storage/SKILL.md',
|
|
152
|
+
agent: 'developer',
|
|
153
|
+
testPrompt: 'Set up blob storage with lifecycle management for our file upload service',
|
|
154
|
+
requiredKeywords: ['blob', 'storage', 'lifecycle'],
|
|
155
|
+
},
|
|
156
|
+
{
|
|
157
|
+
id: 15, skill: 'azure-ai',
|
|
158
|
+
skillPath: '.github/skills/azure-ai/SKILL.md',
|
|
159
|
+
agent: 'developer',
|
|
160
|
+
testPrompt: 'Configure Azure AI Search with vector search for our product catalog',
|
|
161
|
+
requiredKeywords: ['ai search', 'vector'],
|
|
162
|
+
},
|
|
163
|
+
{
|
|
164
|
+
id: 16, skill: 'azure-aigateway',
|
|
165
|
+
skillPath: '.github/skills/azure-aigateway/SKILL.md',
|
|
166
|
+
agent: 'developer',
|
|
167
|
+
testPrompt: 'Set up semantic caching and token limits for our Azure OpenAI gateway',
|
|
168
|
+
requiredKeywords: ['semantic caching', 'token'],
|
|
169
|
+
},
|
|
170
|
+
{
|
|
171
|
+
id: 17, skill: 'azure-kusto',
|
|
172
|
+
skillPath: '.github/skills/azure-kusto/SKILL.md',
|
|
173
|
+
agent: 'developer',
|
|
174
|
+
testPrompt: 'Write KQL queries to analyze the IoT telemetry in Azure Data Explorer',
|
|
175
|
+
requiredKeywords: ['kql', 'data explorer'],
|
|
176
|
+
},
|
|
177
|
+
{
|
|
178
|
+
id: 18, skill: 'azure-messaging',
|
|
179
|
+
skillPath: '.github/skills/azure-messaging/SKILL.md',
|
|
180
|
+
agent: 'developer',
|
|
181
|
+
testPrompt: 'Troubleshoot this AMQP connection error with our Event Hub consumer',
|
|
182
|
+
requiredKeywords: ['amqp', 'event hub'],
|
|
183
|
+
},
|
|
184
|
+
{
|
|
185
|
+
id: 19, skill: 'azure-hosted-copilot-sdk',
|
|
186
|
+
skillPath: '.github/skills/azure-hosted-copilot-sdk/SKILL.md',
|
|
187
|
+
agent: 'developer',
|
|
188
|
+
testPrompt: 'Build a copilot app using @github/copilot-sdk and deploy to Azure',
|
|
189
|
+
requiredKeywords: ['copilot', 'sdk'],
|
|
190
|
+
},
|
|
191
|
+
{
|
|
192
|
+
id: 20, skill: 'appinsights-instrumentation',
|
|
193
|
+
skillPath: '.github/skills/appinsights-instrumentation/SKILL.md',
|
|
194
|
+
agent: 'developer',
|
|
195
|
+
testPrompt: 'Instrument our web app with Application Insights telemetry',
|
|
196
|
+
requiredKeywords: ['application insights', 'telemetry'],
|
|
197
|
+
},
|
|
198
|
+
{
|
|
199
|
+
id: 21, skill: 'microsoft-foundry',
|
|
200
|
+
skillPath: '.github/skills/microsoft-foundry/SKILL.md',
|
|
201
|
+
agent: 'developer',
|
|
202
|
+
testPrompt: 'Deploy our agent to Microsoft Foundry and run batch evaluation',
|
|
203
|
+
requiredKeywords: ['foundry', 'agent'],
|
|
204
|
+
},
|
|
205
|
+
{
|
|
206
|
+
id: 22, skill: 'azure-rbac',
|
|
207
|
+
skillPath: '.github/skills/azure-rbac/SKILL.md',
|
|
208
|
+
agent: 'security-reviewer',
|
|
209
|
+
testPrompt: 'Find the least privilege RBAC role for our managed identity to read blobs',
|
|
210
|
+
requiredKeywords: ['rbac', 'role', 'privilege'],
|
|
211
|
+
},
|
|
212
|
+
{
|
|
213
|
+
id: 23, skill: 'azure-compliance',
|
|
214
|
+
skillPath: '.github/skills/azure-compliance/SKILL.md',
|
|
215
|
+
agent: 'security-reviewer',
|
|
216
|
+
testPrompt: 'Run a compliance scan and security audit on our Azure subscription',
|
|
217
|
+
requiredKeywords: ['compliance', 'audit'],
|
|
218
|
+
},
|
|
219
|
+
{
|
|
220
|
+
id: 24, skill: 'entra-app-registration',
|
|
221
|
+
skillPath: '.github/skills/entra-app-registration/SKILL.md',
|
|
222
|
+
agent: 'security-reviewer',
|
|
223
|
+
testPrompt: 'Create an Entra ID app registration with OAuth and MSAL configuration',
|
|
224
|
+
requiredKeywords: ['entra', 'oauth', 'msal'],
|
|
225
|
+
},
|
|
226
|
+
{
|
|
227
|
+
id: 25, skill: 'azure-cost-optimization',
|
|
228
|
+
skillPath: '.github/skills/azure-cost-optimization/SKILL.md',
|
|
229
|
+
agent: 'product-manager',
|
|
230
|
+
testPrompt: 'Analyze our Azure spending and find cost optimization opportunities',
|
|
231
|
+
requiredKeywords: ['cost', 'optimization'],
|
|
232
|
+
},
|
|
233
|
+
{
|
|
234
|
+
id: 26, skill: 'azure-cloud-migrate',
|
|
235
|
+
skillPath: '.github/skills/azure-cloud-migrate/SKILL.md',
|
|
236
|
+
agent: 'product-manager',
|
|
237
|
+
testPrompt: 'Assess migrating our Lambda functions to Azure Functions',
|
|
238
|
+
requiredKeywords: ['migrate', 'lambda'],
|
|
239
|
+
},
|
|
240
|
+
{
|
|
241
|
+
id: 27, skill: 'azure-diagnostics',
|
|
242
|
+
skillPath: '.github/skills/azure-diagnostics/SKILL.md',
|
|
243
|
+
agent: 'tester',
|
|
244
|
+
testPrompt: 'Troubleshoot why our Container App is failing health probes in production',
|
|
245
|
+
requiredKeywords: ['troubleshoot', 'container', 'health'],
|
|
246
|
+
},
|
|
247
|
+
{
|
|
248
|
+
id: 28, skill: 'azure-resource-lookup',
|
|
249
|
+
skillPath: '.github/skills/azure-resource-lookup/SKILL.md',
|
|
250
|
+
agent: 'Beth',
|
|
251
|
+
testPrompt: 'List all VMs and storage accounts across our Azure subscriptions',
|
|
252
|
+
requiredKeywords: ['list', 'vm', 'storage'],
|
|
253
|
+
},
|
|
254
|
+
{
|
|
255
|
+
id: 29, skill: 'azure-resource-visualizer',
|
|
256
|
+
skillPath: '.github/skills/azure-resource-visualizer/SKILL.md',
|
|
257
|
+
agent: 'Beth',
|
|
258
|
+
testPrompt: 'Generate a Mermaid architecture diagram of our Azure resource group',
|
|
259
|
+
requiredKeywords: ['mermaid', 'diagram', 'resource'],
|
|
260
|
+
},
|
|
261
|
+
{
|
|
262
|
+
id: 30, skill: 'azure-postgres',
|
|
263
|
+
skillPath: join(EXTERNAL_SKILLS_DIR, 'azure-postgres/SKILL.md'),
|
|
264
|
+
agent: 'developer',
|
|
265
|
+
testPrompt: 'Configure passwordless Entra ID authentication for our Postgres server',
|
|
266
|
+
requiredKeywords: ['postgres', 'passwordless'],
|
|
267
|
+
external: true,
|
|
268
|
+
},
|
|
269
|
+
{
|
|
270
|
+
id: 31, skill: 'azure-quotas',
|
|
271
|
+
skillPath: join(EXTERNAL_SKILLS_DIR, 'azure-quotas/SKILL.md'),
|
|
272
|
+
agent: 'developer',
|
|
273
|
+
testPrompt: 'Check our Azure subscription quotas and vCPU limits',
|
|
274
|
+
requiredKeywords: ['quota', 'vcpu'],
|
|
275
|
+
external: true,
|
|
276
|
+
},
|
|
277
|
+
];
|
|
278
|
+
// ─── Category 3: Design & Frontend (4 tests) ──────────────────────────────
|
|
279
|
+
const DESIGN_SKILLS = [
|
|
280
|
+
{
|
|
281
|
+
id: 32, skill: 'frontend-design',
|
|
282
|
+
skillPath: '.github/skills/frontend-design/SKILL.md',
|
|
283
|
+
agent: 'developer',
|
|
284
|
+
testPrompt: 'Build a distinctive, production-grade landing page with creative animations',
|
|
285
|
+
requiredKeywords: ['frontend', 'design', 'production'],
|
|
286
|
+
},
|
|
287
|
+
{
|
|
288
|
+
id: 33, skill: 'brainstorming',
|
|
289
|
+
skillPath: '.github/skills/brainstorming/SKILL.md',
|
|
290
|
+
agent: 'ux-designer',
|
|
291
|
+
testPrompt: 'Let\'s brainstorm approaches for the new onboarding flow',
|
|
292
|
+
requiredKeywords: ['brainstorm', 'explore'],
|
|
293
|
+
},
|
|
294
|
+
{
|
|
295
|
+
id: 34, skill: 'document-review',
|
|
296
|
+
skillPath: '.github/skills/document-review/SKILL.md',
|
|
297
|
+
agent: 'ux-designer',
|
|
298
|
+
testPrompt: 'Review and refine this brainstorm document before we proceed to planning',
|
|
299
|
+
requiredKeywords: ['review', 'refine', 'document'],
|
|
300
|
+
},
|
|
301
|
+
{
|
|
302
|
+
id: 35, skill: 'every-style-editor',
|
|
303
|
+
skillPath: '.github/skills/every-style-editor/SKILL.md',
|
|
304
|
+
agent: 'product-manager',
|
|
305
|
+
testPrompt: 'Edit this blog post for grammar and style guide compliance',
|
|
306
|
+
requiredKeywords: ['style', 'grammar'],
|
|
307
|
+
},
|
|
308
|
+
];
|
|
309
|
+
// ─── Category 4: Product & Research (4 tests) ─────────────────────────────
|
|
310
|
+
const PRODUCT_SKILLS = [
|
|
311
|
+
{
|
|
312
|
+
id: 36, skill: 'prd',
|
|
313
|
+
skillPath: '.github/skills/prd/SKILL.md',
|
|
314
|
+
agent: 'product-manager',
|
|
315
|
+
testPrompt: 'Write a product requirements document for the billing dashboard feature',
|
|
316
|
+
requiredKeywords: ['product requirements', 'prd'],
|
|
317
|
+
},
|
|
318
|
+
{
|
|
319
|
+
id: 37, skill: 'web-search',
|
|
320
|
+
skillPath: '.github/skills/web-search/SKILL.md',
|
|
321
|
+
agent: 'researcher',
|
|
322
|
+
testPrompt: 'Research the competitive landscape for AI code assistants',
|
|
323
|
+
requiredKeywords: ['research', 'search'],
|
|
324
|
+
},
|
|
325
|
+
{
|
|
326
|
+
id: 38, skill: 'proof',
|
|
327
|
+
skillPath: '.github/skills/proof/SKILL.md',
|
|
328
|
+
agent: 'product-manager',
|
|
329
|
+
testPrompt: 'Create a proof document and share it for team review',
|
|
330
|
+
requiredKeywords: ['proof', 'document'],
|
|
331
|
+
},
|
|
332
|
+
{
|
|
333
|
+
id: 39, skill: 'changelog',
|
|
334
|
+
skillPath: '.github/skills/changelog/SKILL.md',
|
|
335
|
+
agent: 'developer',
|
|
336
|
+
testPrompt: 'Generate a changelog from recent commits',
|
|
337
|
+
requiredKeywords: ['changelog', 'change log'],
|
|
338
|
+
},
|
|
339
|
+
];
|
|
340
|
+
// ─── Category 5: Developer Workflow (14 tests) ────────────────────────────
|
|
341
|
+
const WORKFLOW_SKILLS = [
|
|
342
|
+
{
|
|
343
|
+
id: 40, skill: 'create-agent-skills',
|
|
344
|
+
skillPath: '.github/skills/create-agent-skills/SKILL.md',
|
|
345
|
+
agent: 'developer',
|
|
346
|
+
testPrompt: 'Create a new Claude Code skill for database migration workflows',
|
|
347
|
+
requiredKeywords: ['skill', 'create'],
|
|
348
|
+
},
|
|
349
|
+
{
|
|
350
|
+
id: 41, skill: 'git-worktree',
|
|
351
|
+
skillPath: '.github/skills/git-worktree/SKILL.md',
|
|
352
|
+
agent: 'developer',
|
|
353
|
+
testPrompt: 'Create a git worktree for isolated parallel development on the feature branch',
|
|
354
|
+
requiredKeywords: ['worktree', 'git'],
|
|
355
|
+
},
|
|
356
|
+
{
|
|
357
|
+
id: 42, skill: 'feature-video',
|
|
358
|
+
skillPath: '.github/skills/feature-video/SKILL.md',
|
|
359
|
+
agent: 'developer',
|
|
360
|
+
testPrompt: 'Record a video walkthrough of the new settings feature for the PR',
|
|
361
|
+
requiredKeywords: ['video', 'feature'],
|
|
362
|
+
},
|
|
363
|
+
{
|
|
364
|
+
id: 43, skill: 'resolve_parallel',
|
|
365
|
+
skillPath: '.github/skills/resolve_parallel/SKILL.md',
|
|
366
|
+
agent: 'developer',
|
|
367
|
+
testPrompt: 'Resolve all code TODOs in the codebase using parallel processing',
|
|
368
|
+
requiredKeywords: ['resolve', 'todo'],
|
|
369
|
+
},
|
|
370
|
+
{
|
|
371
|
+
id: 44, skill: 'resolve_todo_parallel',
|
|
372
|
+
skillPath: '.github/skills/resolve_todo_parallel/SKILL.md',
|
|
373
|
+
agent: 'developer',
|
|
374
|
+
testPrompt: 'Resolve all pending CLI todos in my todo list',
|
|
375
|
+
requiredKeywords: ['resolve', 'todo'],
|
|
376
|
+
},
|
|
377
|
+
{
|
|
378
|
+
id: 45, skill: 'resolve-pr-parallel',
|
|
379
|
+
skillPath: '.github/skills/resolve-pr-parallel/SKILL.md',
|
|
380
|
+
agent: 'developer',
|
|
381
|
+
testPrompt: 'Address all PR review comments using parallel processing',
|
|
382
|
+
requiredKeywords: ['pr', 'review'],
|
|
383
|
+
},
|
|
384
|
+
{
|
|
385
|
+
id: 46, skill: 'lfg',
|
|
386
|
+
skillPath: '.github/skills/lfg/SKILL.md',
|
|
387
|
+
agent: 'developer',
|
|
388
|
+
testPrompt: "Execute the work plan sequentially — let's go",
|
|
389
|
+
requiredKeywords: ['execute', 'plan'],
|
|
390
|
+
},
|
|
391
|
+
{
|
|
392
|
+
id: 47, skill: 'slfg',
|
|
393
|
+
skillPath: '.github/skills/slfg/SKILL.md',
|
|
394
|
+
agent: 'developer',
|
|
395
|
+
testPrompt: 'Execute the work plan using swarm parallel processing',
|
|
396
|
+
requiredKeywords: ['swarm', 'parallel'],
|
|
397
|
+
},
|
|
398
|
+
{
|
|
399
|
+
id: 48, skill: 'deepen-plan',
|
|
400
|
+
skillPath: '.github/skills/deepen-plan/SKILL.md',
|
|
401
|
+
agent: 'developer',
|
|
402
|
+
testPrompt: 'Enhance this plan with parallel research agents to add depth and best practices',
|
|
403
|
+
requiredKeywords: ['enhance', 'plan', 'research'],
|
|
404
|
+
},
|
|
405
|
+
{
|
|
406
|
+
id: 49, skill: 'agent-browser',
|
|
407
|
+
skillPath: '.github/skills/agent-browser/SKILL.md',
|
|
408
|
+
agent: 'developer',
|
|
409
|
+
testPrompt: 'Browse the staging site and fill out the signup form to test it',
|
|
410
|
+
requiredKeywords: ['browse', 'form'],
|
|
411
|
+
},
|
|
412
|
+
{
|
|
413
|
+
id: 50, skill: 'agent-native-architecture',
|
|
414
|
+
skillPath: '.github/skills/agent-native-architecture/SKILL.md',
|
|
415
|
+
agent: 'developer',
|
|
416
|
+
testPrompt: 'Design an application where agents are first-class citizens with MCP tools',
|
|
417
|
+
requiredKeywords: ['agent', 'mcp'],
|
|
418
|
+
},
|
|
419
|
+
{
|
|
420
|
+
id: 51, skill: 'rclone',
|
|
421
|
+
skillPath: '.github/skills/rclone/SKILL.md',
|
|
422
|
+
agent: 'developer',
|
|
423
|
+
testPrompt: 'Upload the generated video files to our S3 bucket',
|
|
424
|
+
requiredKeywords: ['upload', 's3'],
|
|
425
|
+
},
|
|
426
|
+
{
|
|
427
|
+
id: 52, skill: 'gemini-imagegen',
|
|
428
|
+
skillPath: '.github/skills/gemini-imagegen/SKILL.md',
|
|
429
|
+
agent: 'developer',
|
|
430
|
+
testPrompt: 'Generate a product mockup image using Gemini for the landing page',
|
|
431
|
+
requiredKeywords: ['gemini', 'image'],
|
|
432
|
+
},
|
|
433
|
+
{
|
|
434
|
+
id: 53, skill: 'generate_command',
|
|
435
|
+
skillPath: '.github/skills/generate_command/SKILL.md',
|
|
436
|
+
agent: 'developer',
|
|
437
|
+
testPrompt: 'Generate a shell command to find all TypeScript files with TODO comments',
|
|
438
|
+
requiredKeywords: ['generate', 'command'],
|
|
439
|
+
},
|
|
440
|
+
];
|
|
441
|
+
// ─── Category 6: Testing & QA (5 tests) ───────────────────────────────────
|
|
442
|
+
const TESTING_SKILLS = [
|
|
443
|
+
{
|
|
444
|
+
id: 54, skill: 'test-browser',
|
|
445
|
+
skillPath: '.github/skills/test-browser/SKILL.md',
|
|
446
|
+
agent: 'tester',
|
|
447
|
+
testPrompt: 'Run browser tests on pages affected by the current PR',
|
|
448
|
+
requiredKeywords: ['browser', 'test'],
|
|
449
|
+
},
|
|
450
|
+
{
|
|
451
|
+
id: 55, skill: 'test-xcode',
|
|
452
|
+
skillPath: '.github/skills/test-xcode/SKILL.md',
|
|
453
|
+
agent: 'tester',
|
|
454
|
+
testPrompt: 'Run Xcode tests for the iOS module',
|
|
455
|
+
requiredKeywords: ['xcode', 'test'],
|
|
456
|
+
},
|
|
457
|
+
{
|
|
458
|
+
id: 56, skill: 'report-bug',
|
|
459
|
+
skillPath: '.github/skills/report-bug/SKILL.md',
|
|
460
|
+
agent: 'tester',
|
|
461
|
+
testPrompt: 'File a bug report for the broken pagination on the search results page',
|
|
462
|
+
requiredKeywords: ['bug', 'report'],
|
|
463
|
+
},
|
|
464
|
+
{
|
|
465
|
+
id: 57, skill: 'reproduce-bug',
|
|
466
|
+
skillPath: '.github/skills/reproduce-bug/SKILL.md',
|
|
467
|
+
agent: 'tester',
|
|
468
|
+
testPrompt: 'Reproduce the intermittent crash reported in issue #42',
|
|
469
|
+
requiredKeywords: ['reproduce', 'bug'],
|
|
470
|
+
},
|
|
471
|
+
{
|
|
472
|
+
id: 58, skill: 'triage',
|
|
473
|
+
skillPath: '.github/skills/triage/SKILL.md',
|
|
474
|
+
agent: 'tester',
|
|
475
|
+
testPrompt: 'Triage the incoming bug reports and prioritize by severity',
|
|
476
|
+
requiredKeywords: ['triage', 'severity'],
|
|
477
|
+
},
|
|
478
|
+
];
|
|
479
|
+
// ─── Category 7: Orchestration & Swarm (4 tests) ──────────────────────────
|
|
480
|
+
const ORCHESTRATION_SKILLS = [
|
|
481
|
+
{
|
|
482
|
+
id: 59, skill: 'orchestrating-swarms',
|
|
483
|
+
skillPath: '.github/skills/orchestrating-swarms/SKILL.md',
|
|
484
|
+
agent: 'Beth',
|
|
485
|
+
testPrompt: 'Orchestrate a swarm of agents to parallelize the migration work',
|
|
486
|
+
requiredKeywords: ['swarm', 'orchestrat'],
|
|
487
|
+
},
|
|
488
|
+
{
|
|
489
|
+
id: 60, skill: 'setup',
|
|
490
|
+
skillPath: '.github/skills/setup/SKILL.md',
|
|
491
|
+
agent: 'Beth',
|
|
492
|
+
testPrompt: 'Set up the project structure and initialize the development environment',
|
|
493
|
+
requiredKeywords: ['setup', 'project'],
|
|
494
|
+
},
|
|
495
|
+
{
|
|
496
|
+
id: 61, skill: 'heal-skill',
|
|
497
|
+
skillPath: '.github/skills/heal-skill/SKILL.md',
|
|
498
|
+
agent: 'Beth',
|
|
499
|
+
testPrompt: "Fix this broken skill that isn't loading correctly",
|
|
500
|
+
requiredKeywords: ['skill', 'fix'],
|
|
501
|
+
},
|
|
502
|
+
{
|
|
503
|
+
id: 62, skill: 'file-todos',
|
|
504
|
+
skillPath: '.github/skills/file-todos/SKILL.md',
|
|
505
|
+
agent: 'developer',
|
|
506
|
+
testPrompt: 'Scan the codebase and create tasks for all TODO/FIXME comments',
|
|
507
|
+
requiredKeywords: ['todo', 'task'],
|
|
508
|
+
},
|
|
509
|
+
];
|
|
510
|
+
// ─── Category 8: CE Workflow Pipeline (5 tests) ───────────────────────────
|
|
511
|
+
const CE_SKILLS = [
|
|
512
|
+
{
|
|
513
|
+
id: 63, skill: 'ce:brainstorm',
|
|
514
|
+
skillPath: '.github/skills/ce:brainstorm/SKILL.md',
|
|
515
|
+
agent: 'ux-designer',
|
|
516
|
+
testPrompt: '/ce:brainstorm — explore requirements for the new dashboard',
|
|
517
|
+
requiredKeywords: ['brainstorm', 'explore', 'requirement'],
|
|
518
|
+
},
|
|
519
|
+
{
|
|
520
|
+
id: 64, skill: 'ce:plan',
|
|
521
|
+
skillPath: '.github/skills/ce:plan/SKILL.md',
|
|
522
|
+
agent: 'developer',
|
|
523
|
+
testPrompt: '/ce:plan — transform the feature description into a structured project plan',
|
|
524
|
+
requiredKeywords: ['plan', 'transform'],
|
|
525
|
+
},
|
|
526
|
+
{
|
|
527
|
+
id: 65, skill: 'ce:work',
|
|
528
|
+
skillPath: '.github/skills/ce:work/SKILL.md',
|
|
529
|
+
agent: 'developer',
|
|
530
|
+
testPrompt: '/ce:work — execute the work plan and finish the feature',
|
|
531
|
+
requiredKeywords: ['work', 'execute'],
|
|
532
|
+
},
|
|
533
|
+
{
|
|
534
|
+
id: 66, skill: 'ce:review',
|
|
535
|
+
skillPath: '.github/skills/ce:review/SKILL.md',
|
|
536
|
+
agent: 'developer',
|
|
537
|
+
testPrompt: '/ce:review — perform exhaustive multi-agent code review',
|
|
538
|
+
requiredKeywords: ['review', 'code'],
|
|
539
|
+
},
|
|
540
|
+
{
|
|
541
|
+
id: 67, skill: 'ce:compound',
|
|
542
|
+
skillPath: '.github/skills/ce:compound/SKILL.md',
|
|
543
|
+
agent: 'developer',
|
|
544
|
+
testPrompt: '/ce:compound — document what we solved to compound team knowledge',
|
|
545
|
+
requiredKeywords: ['compound', 'document'],
|
|
546
|
+
},
|
|
547
|
+
];
|
|
548
|
+
// ─── Category 9: Language-Specific (3 tests) ──────────────────────────────
|
|
549
|
+
const LANGUAGE_SKILLS = [
|
|
550
|
+
{
|
|
551
|
+
id: 68, skill: 'dhh-rails-style',
|
|
552
|
+
skillPath: '.github/skills/dhh-rails-style/SKILL.md',
|
|
553
|
+
agent: 'developer',
|
|
554
|
+
testPrompt: "Write a Rails controller for user management in DHH's 37signals style",
|
|
555
|
+
requiredKeywords: ['rails', 'dhh', '37signals'],
|
|
556
|
+
},
|
|
557
|
+
{
|
|
558
|
+
id: 69, skill: 'andrew-kane-gem-writer',
|
|
559
|
+
skillPath: '.github/skills/andrew-kane-gem-writer/SKILL.md',
|
|
560
|
+
agent: 'developer',
|
|
561
|
+
testPrompt: "Create a Ruby gem for CSV parsing following Andrew Kane's patterns",
|
|
562
|
+
requiredKeywords: ['gem', 'andrew kane'],
|
|
563
|
+
},
|
|
564
|
+
{
|
|
565
|
+
id: 70, skill: 'dspy-ruby',
|
|
566
|
+
skillPath: '.github/skills/dspy-ruby/SKILL.md',
|
|
567
|
+
agent: 'developer',
|
|
568
|
+
testPrompt: 'Build an LLM module using DSPy.rb signatures for intent classification',
|
|
569
|
+
requiredKeywords: ['dspy', 'signature'],
|
|
570
|
+
},
|
|
571
|
+
];
|
|
572
|
+
// ─── Category 10: Remaining (2 tests) ─────────────────────────────────────
|
|
573
|
+
const REMAINING_SKILLS = [
|
|
574
|
+
{
|
|
575
|
+
id: 71, skill: 'compound-docs',
|
|
576
|
+
skillPath: '.github/skills/compound-docs/SKILL.md',
|
|
577
|
+
agent: 'developer',
|
|
578
|
+
testPrompt: 'That worked! Document this solution for the team',
|
|
579
|
+
requiredKeywords: ['document', 'solution'],
|
|
580
|
+
},
|
|
581
|
+
{
|
|
582
|
+
id: 72, skill: 'agent-native-audit',
|
|
583
|
+
skillPath: '.github/skills/agent-native-audit/SKILL.md',
|
|
584
|
+
agent: 'security-reviewer',
|
|
585
|
+
testPrompt: 'Audit the agent-native architecture for security and reliability',
|
|
586
|
+
requiredKeywords: ['audit', 'agent', 'review'],
|
|
587
|
+
},
|
|
588
|
+
];
|
|
589
|
+
// ─── All tests combined ────────────────────────────────────────────────────
|
|
590
|
+
const ALL_TESTS = [
|
|
591
|
+
...HOOK_ENFORCED,
|
|
592
|
+
...AZURE_SKILLS,
|
|
593
|
+
...DESIGN_SKILLS,
|
|
594
|
+
...PRODUCT_SKILLS,
|
|
595
|
+
...WORKFLOW_SKILLS,
|
|
596
|
+
...TESTING_SKILLS,
|
|
597
|
+
...ORCHESTRATION_SKILLS,
|
|
598
|
+
...CE_SKILLS,
|
|
599
|
+
...LANGUAGE_SKILLS,
|
|
600
|
+
...REMAINING_SKILLS,
|
|
601
|
+
];
|
|
602
|
+
// ─── Parameterized tests ───────────────────────────────────────────────────
|
|
603
|
+
describe('Skill Trigger Coverage — Keyword Matching', () => {
|
|
604
|
+
describe('Category 1: Hook-Enforced Skills', () => {
|
|
605
|
+
describe.each(HOOK_ENFORCED)('Test #$id: "$skill" triggers on "$testPrompt"', (test) => {
|
|
606
|
+
it('skill file exists', () => {
|
|
607
|
+
expect(skillFileExists(test)).toBe(true);
|
|
608
|
+
});
|
|
609
|
+
it('skill content contains ALL required keywords', () => {
|
|
610
|
+
const content = readSkillContent(test);
|
|
611
|
+
const { misses } = countKeywordHits(content, test.requiredKeywords);
|
|
612
|
+
expect(misses).toHaveLength(0);
|
|
613
|
+
});
|
|
614
|
+
});
|
|
615
|
+
});
|
|
616
|
+
describe('Category 2: Azure Skills', () => {
|
|
617
|
+
describe.each(AZURE_SKILLS)('Test #$id: "$skill" triggers on "$testPrompt"', (test) => {
|
|
618
|
+
const shouldSkip = test.external && !skillFileExists(test);
|
|
619
|
+
it.skipIf(shouldSkip)('skill file exists', () => {
|
|
620
|
+
expect(skillFileExists(test)).toBe(true);
|
|
621
|
+
});
|
|
622
|
+
it.skipIf(shouldSkip)('skill content contains ALL required keywords', () => {
|
|
623
|
+
const content = readSkillContent(test);
|
|
624
|
+
const { misses } = countKeywordHits(content, test.requiredKeywords);
|
|
625
|
+
expect(misses).toHaveLength(0);
|
|
626
|
+
});
|
|
627
|
+
});
|
|
628
|
+
});
|
|
629
|
+
describe('Category 3: Design & Frontend', () => {
|
|
630
|
+
describe.each(DESIGN_SKILLS)('Test #$id: "$skill" triggers on "$testPrompt"', (test) => {
|
|
631
|
+
it('skill file exists', () => {
|
|
632
|
+
expect(skillFileExists(test)).toBe(true);
|
|
633
|
+
});
|
|
634
|
+
it('skill content contains ALL required keywords', () => {
|
|
635
|
+
const content = readSkillContent(test);
|
|
636
|
+
const { misses } = countKeywordHits(content, test.requiredKeywords);
|
|
637
|
+
expect(misses).toHaveLength(0);
|
|
638
|
+
});
|
|
639
|
+
});
|
|
640
|
+
});
|
|
641
|
+
describe('Category 4: Product & Research', () => {
|
|
642
|
+
describe.each(PRODUCT_SKILLS)('Test #$id: "$skill" triggers on "$testPrompt"', (test) => {
|
|
643
|
+
it('skill file exists', () => {
|
|
644
|
+
expect(skillFileExists(test)).toBe(true);
|
|
645
|
+
});
|
|
646
|
+
it('skill content contains ALL required keywords', () => {
|
|
647
|
+
const content = readSkillContent(test);
|
|
648
|
+
const { misses } = countKeywordHits(content, test.requiredKeywords);
|
|
649
|
+
expect(misses).toHaveLength(0);
|
|
650
|
+
});
|
|
651
|
+
});
|
|
652
|
+
});
|
|
653
|
+
describe('Category 5: Developer Workflow', () => {
|
|
654
|
+
describe.each(WORKFLOW_SKILLS)('Test #$id: "$skill" triggers on "$testPrompt"', (test) => {
|
|
655
|
+
it('skill file exists', () => {
|
|
656
|
+
expect(skillFileExists(test)).toBe(true);
|
|
657
|
+
});
|
|
658
|
+
it('skill content contains ALL required keywords', () => {
|
|
659
|
+
const content = readSkillContent(test);
|
|
660
|
+
const { misses } = countKeywordHits(content, test.requiredKeywords);
|
|
661
|
+
expect(misses).toHaveLength(0);
|
|
662
|
+
});
|
|
663
|
+
});
|
|
664
|
+
});
|
|
665
|
+
describe('Category 6: Testing & QA', () => {
|
|
666
|
+
describe.each(TESTING_SKILLS)('Test #$id: "$skill" triggers on "$testPrompt"', (test) => {
|
|
667
|
+
it('skill file exists', () => {
|
|
668
|
+
expect(skillFileExists(test)).toBe(true);
|
|
669
|
+
});
|
|
670
|
+
it('skill content contains ALL required keywords', () => {
|
|
671
|
+
const content = readSkillContent(test);
|
|
672
|
+
const { misses } = countKeywordHits(content, test.requiredKeywords);
|
|
673
|
+
expect(misses).toHaveLength(0);
|
|
674
|
+
});
|
|
675
|
+
});
|
|
676
|
+
});
|
|
677
|
+
describe('Category 7: Orchestration & Swarm', () => {
|
|
678
|
+
describe.each(ORCHESTRATION_SKILLS)('Test #$id: "$skill" triggers on "$testPrompt"', (test) => {
|
|
679
|
+
it('skill file exists', () => {
|
|
680
|
+
expect(skillFileExists(test)).toBe(true);
|
|
681
|
+
});
|
|
682
|
+
it('skill content contains ALL required keywords', () => {
|
|
683
|
+
const content = readSkillContent(test);
|
|
684
|
+
const { misses } = countKeywordHits(content, test.requiredKeywords);
|
|
685
|
+
expect(misses).toHaveLength(0);
|
|
686
|
+
});
|
|
687
|
+
});
|
|
688
|
+
});
|
|
689
|
+
describe('Category 8: CE Workflow Pipeline', () => {
|
|
690
|
+
describe.each(CE_SKILLS)('Test #$id: "$skill" triggers on "$testPrompt"', (test) => {
|
|
691
|
+
it('skill file exists', () => {
|
|
692
|
+
expect(skillFileExists(test)).toBe(true);
|
|
693
|
+
});
|
|
694
|
+
it('skill content contains ALL required keywords', () => {
|
|
695
|
+
const content = readSkillContent(test);
|
|
696
|
+
const { misses } = countKeywordHits(content, test.requiredKeywords);
|
|
697
|
+
expect(misses).toHaveLength(0);
|
|
698
|
+
});
|
|
699
|
+
});
|
|
700
|
+
});
|
|
701
|
+
describe('Category 9: Language-Specific', () => {
|
|
702
|
+
describe.each(LANGUAGE_SKILLS)('Test #$id: "$skill" triggers on "$testPrompt"', (test) => {
|
|
703
|
+
it('skill file exists', () => {
|
|
704
|
+
expect(skillFileExists(test)).toBe(true);
|
|
705
|
+
});
|
|
706
|
+
it('skill content contains ALL required keywords', () => {
|
|
707
|
+
const content = readSkillContent(test);
|
|
708
|
+
const { misses } = countKeywordHits(content, test.requiredKeywords);
|
|
709
|
+
expect(misses).toHaveLength(0);
|
|
710
|
+
});
|
|
711
|
+
});
|
|
712
|
+
});
|
|
713
|
+
describe('Category 10: Remaining', () => {
|
|
714
|
+
describe.each(REMAINING_SKILLS)('Test #$id: "$skill" triggers on "$testPrompt"', (test) => {
|
|
715
|
+
it('skill file exists', () => {
|
|
716
|
+
expect(skillFileExists(test)).toBe(true);
|
|
717
|
+
});
|
|
718
|
+
it('skill content contains ALL required keywords', () => {
|
|
719
|
+
const content = readSkillContent(test);
|
|
720
|
+
const { misses } = countKeywordHits(content, test.requiredKeywords);
|
|
721
|
+
expect(misses).toHaveLength(0);
|
|
722
|
+
});
|
|
723
|
+
});
|
|
724
|
+
});
|
|
725
|
+
});
|
|
726
|
+
// ─── Cross-cutting: keyword coverage statistics ────────────────────────────
|
|
727
|
+
describe('Cross-cutting: Trigger coverage statistics', () => {
|
|
728
|
+
it('all 72 test cases have at least 2 required keywords', () => {
|
|
729
|
+
for (const test of ALL_TESTS) {
|
|
730
|
+
expect(test.requiredKeywords.length).toBeGreaterThanOrEqual(2);
|
|
731
|
+
}
|
|
732
|
+
});
|
|
733
|
+
it('test IDs span 1–72 with no gaps', () => {
|
|
734
|
+
const ids = ALL_TESTS.map((t) => t.id).sort((a, b) => a - b);
|
|
735
|
+
expect(ids).toHaveLength(72);
|
|
736
|
+
for (let i = 0; i < 72; i++) {
|
|
737
|
+
expect(ids[i]).toBe(i + 1);
|
|
738
|
+
}
|
|
739
|
+
});
|
|
740
|
+
it('no two tests reference the same skill+prompt pair', () => {
|
|
741
|
+
const pairs = ALL_TESTS.map((t) => `${t.skill}::${t.testPrompt}`);
|
|
742
|
+
const uniquePairs = new Set(pairs);
|
|
743
|
+
expect(uniquePairs.size).toBe(pairs.length);
|
|
744
|
+
});
|
|
745
|
+
});
|
|
746
|
+
//# sourceMappingURL=trigger-coverage.test.js.map
|