mirror of
https://github.com/heygen-com/hyperframes.git
synced 2026-09-01 19:42:03 +00:00
fix(skills): make media-use frontmatter valid YAML so skills add works (#1709)
The `media-use` SKILL.md `description:` was an unquoted YAML scalar containing a mid-value `: ` (`...the full cascade: project cache...`). YAML 1.2 reads that as a nested mapping and the parse fails with "Nested mappings are not allowed in compact mappings". `skills add` aborts the entire install when any one skill fails to parse, so this single file blocked installing all 19 skills for everyone following the README's `npx skills add heygen-com/hyperframes`. - Replace the offending `: ` with ` — ` (keeps the plain-scalar style used by the other 18 skills; the description already uses `—` as a separator). - Add a frontmatter guard to scripts/lint-skills.ts that flags unquoted top-level scalars containing `: ` — the exact ambiguity — so this can't regress. No new dependency. Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
34bb496566
commit
814c96cefa
+43
-1
@@ -56,6 +56,43 @@ function collectSkillFiles(dir: string): string[] {
|
||||
return files;
|
||||
}
|
||||
|
||||
/**
|
||||
* Flag YAML frontmatter that won't parse, which aborts `skills add` for the
|
||||
* WHOLE repo (one bad SKILL.md blocks installing every skill).
|
||||
*
|
||||
* ponytail: targets the one failure mode we've actually hit — an unquoted
|
||||
* top-level scalar whose value contains `: ` (colon-space), which YAML 1.2
|
||||
* reads as a nested mapping ("Nested mappings are not allowed in compact
|
||||
* mappings"). Not a full YAML parse; if a different malformation appears,
|
||||
* swap this for a real parser (the `yaml` package).
|
||||
*/
|
||||
function lintFrontmatter(content: string): Omit<Violation, "file">[] {
|
||||
const match = content.match(/^---\n([\s\S]*?)\n---/);
|
||||
if (!match) return [];
|
||||
const violations: Omit<Violation, "file">[] = [];
|
||||
const fmLines = match[1].split("\n");
|
||||
for (let i = 0; i < fmLines.length; i++) {
|
||||
const line = fmLines[i];
|
||||
// Top-level `key: value` (no indentation). Skip block scalars (> |),
|
||||
// already-quoted values, and flow collections — those handle colons fine.
|
||||
const m = line.match(/^([A-Za-z0-9_-]+):[ \t]+(.+)$/);
|
||||
if (!m) continue;
|
||||
const value = m[2].trim();
|
||||
if (/^["'>|[{]/.test(value)) continue;
|
||||
if (/:[ \t]/.test(value)) {
|
||||
violations.push({
|
||||
line: i + 2, // +1 for the opening `---`, +1 for 1-based
|
||||
message:
|
||||
`Unquoted frontmatter value for "${m[1]}" contains ": " — YAML reads ` +
|
||||
`this as a nested mapping and the parse fails, which aborts ` +
|
||||
`\`skills add\` for the entire repo. Quote the value or rephrase the colon.`,
|
||||
text: line.trim(),
|
||||
});
|
||||
}
|
||||
}
|
||||
return violations;
|
||||
}
|
||||
|
||||
/** Strip fenced code blocks so we only lint prose + inline code. */
|
||||
function stripFencedBlocks(content: string): string {
|
||||
return content.replace(/^```[\s\S]*?^```/gm, (match) =>
|
||||
@@ -68,9 +105,14 @@ function stripFencedBlocks(content: string): string {
|
||||
|
||||
function lintFile(filePath: string): Violation[] {
|
||||
const raw = readFileSync(filePath, "utf-8");
|
||||
const file = relative(process.cwd(), filePath);
|
||||
const violations: Violation[] = lintFrontmatter(raw).map((v) => ({
|
||||
...v,
|
||||
file,
|
||||
}));
|
||||
|
||||
const stripped = stripFencedBlocks(raw);
|
||||
const lines = stripped.split("\n");
|
||||
const violations: Violation[] = [];
|
||||
|
||||
for (let i = 0; i < lines.length; i++) {
|
||||
const line = lines[i];
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
name: media-use
|
||||
description: Agent Media OS — resolve any media need (BGM, SFX, image, icon) into a frozen local file + ledger record. One verb (`resolve`) handles the full cascade: project cache, global cache, HeyGen catalog search, freeze, register. Keeps search noise on disk, hands the agent a path. Use when a composition needs background music, sound effects, images, or icons.
|
||||
description: Agent Media OS — resolve any media need (BGM, SFX, image, icon) into a frozen local file + ledger record. One verb (`resolve`) handles the full cascade — project cache, global cache, HeyGen catalog search, freeze, register. Keeps search noise on disk, hands the agent a path. Use when a composition needs background music, sound effects, images, or icons.
|
||||
---
|
||||
|
||||
# media-use
|
||||
|
||||
Reference in New Issue
Block a user