namespace ClaudeDo.Worker.Skills; internal static class SkillFrontmatter { public sealed record ParsedFrontmatter(string Name, string Description); /// /// Parses the YAML frontmatter block (between the first two "---" lines) of a SKILL.md /// file, extracting "name" (required) and "description" (optional). The description may /// be a folded scalar ("description: >"), whose indented continuation lines are joined /// with spaces into a single string. /// public static ParsedFrontmatter Parse(string skillMdPath) { var lines = File.ReadAllLines(skillMdPath); if (lines.Length == 0 || lines[0].Trim() != "---") throw new InvalidOperationException($"'{skillMdPath}' has no YAML frontmatter block."); string? name = null; var description = ""; var i = 1; for (; i < lines.Length; i++) { var line = lines[i]; if (line.Trim() == "---") break; if (line.StartsWith("name:", StringComparison.Ordinal)) { name = line["name:".Length..].Trim().Trim('"', '\''); } else if (line.StartsWith("description:", StringComparison.Ordinal)) { var rest = line["description:".Length..].Trim(); if (rest == ">" || rest == ">-" || rest == "|" || rest == "|-") { var folded = new List(); var j = i + 1; for (; j < lines.Length; j++) { var contLine = lines[j]; if (contLine.Trim() == "---") break; if (contLine.Length == 0) continue; if (!char.IsWhiteSpace(contLine[0])) break; folded.Add(contLine.Trim()); } description = string.Join(" ", folded); i = j - 1; } else { description = rest.Trim('"', '\''); } } } if (string.IsNullOrWhiteSpace(name)) throw new InvalidOperationException($"'{skillMdPath}' frontmatter is missing required 'name'."); return new ParsedFrontmatter(name, description); } }