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);
}
}