MCPcopy Create free account
hub / github.com/angular/dev-infra / validateSkill

Function validateSkill

ng-dev/misc/validate-skills/validate.ts:89–129  ·  view source on GitHub ↗
(filePath: string)

Source from the content-addressed store, hash-verified

87
88/** Validates a single skill file. */
89export async function validateSkill(filePath: string): Promise<ValidationResult> {
90 const name = basename(join(filePath, '..'));
91 const failures: string[] = [];
92
93 try {
94 const content = await readFile(filePath, {encoding: 'utf8'});
95 const frontmatterRaw = content.match(/^---\n([\s\S]*?)\n---/);
96
97 if (frontmatterRaw === null) {
98 failures.push('Missing or invalid frontmatter in SKILL.md');
99 return {name, failures};
100 }
101
102 let frontmatter: unknown;
103 try {
104 frontmatter = parse(frontmatterRaw[1]);
105 } catch (e) {
106 failures.push(`Failed to parse YAML frontmatter: ${(e as Error).message}`);
107 return {name, failures};
108 }
109
110 const frontmatterData = skillFrontmatterSchema.safeParse(frontmatter);
111 if (frontmatterData.success === false) {
112 for (const issue of frontmatterData.error.issues) {
113 failures.push(`Schema validation failure: [${issue.path.join('.')}] ${issue.message}`);
114 }
115 return {name, failures};
116 }
117
118 // Check name match if data looks like an object with a name
119 if (frontmatterData.data?.name !== name) {
120 failures.push(
121 `Name mismatch. Expected "${name}", found "${frontmatterData.data?.name ?? '<UNKNOWN>'}"`,
122 );
123 }
124 } catch (e) {
125 failures.push(`Unexpected error: ${(e as Error).message}`);
126 }
127
128 return {name, failures};
129}

Callers 1

validate.spec.tsFile · 0.85

Calls 3

parseFunction · 0.50
matchMethod · 0.45
pushMethod · 0.45

Tested by

no test coverage detected