Fix invalid YAML frontmatter and consolidate build transformers

Fixes #67: argument-hint values starting with [ were parsed as YAML flow
sequences. Replace structured args arrays in source files with pre-formatted
argument-hint strings, and quote values starting with [ or { in
generateYamlFrontmatter().

Also consolidates 8 nearly-identical transformer files into a single
config-driven createTransformer() factory. Adding a new provider now
requires only a config object in providers.js instead of a full file.

- Replace args source frontmatter with argument-hint strings
- Add YAML quoting for values starting with [ or {
- Add quote stripping to parseFrontmatter() for round-trip support
- Create factory.js + providers.js, delete 8 individual transformers
- Replace 16 explicit build.js calls with a loop over PROVIDERS
- Consolidate 8 test files into 2 (factory + providers)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Paul Bakaus
2026-03-24 09:48:42 -07:00
co-authored by Claude Opus 4.6
parent e9ac702849
commit 6de73abf1b
121 changed files with 904 additions and 7332 deletions
+8 -3
View File
@@ -61,7 +61,11 @@ export function parseFrontmatter(content) {
const value = trimmed.slice(colonIndex + 1).trim();
if (value) {
frontmatter[key] = value === 'true' ? true : value === 'false' ? false : value;
// Strip YAML quotes
const unquoted = (value.startsWith('"') && value.endsWith('"')) || (value.startsWith("'") && value.endsWith("'"))
? value.slice(1, -1)
: value;
frontmatter[key] = unquoted === 'true' ? true : unquoted === 'false' ? false : unquoted;
currentKey = key;
currentArray = null;
} else {
@@ -148,7 +152,7 @@ export function readSourceFiles(rootDir) {
metadata: frontmatter.metadata || null,
allowedTools: frontmatter['allowed-tools'] || '',
userInvocable: frontmatter['user-invocable'] === true || frontmatter['user-invocable'] === 'true',
args: frontmatter.args || [],
argumentHint: frontmatter['argument-hint'] || '',
context: frontmatter.context || null,
body,
filePath: skillMdPath,
@@ -381,7 +385,8 @@ export function generateYamlFrontmatter(data) {
} else if (typeof value === 'boolean') {
lines.push(`${key}: ${value}`);
} else {
lines.push(`${key}: ${value}`);
const needsQuoting = typeof value === 'string' && /^[\[{]/.test(value);
lines.push(`${key}: ${needsQuoting ? `"${value.replace(/\\/g, '\\\\').replace(/"/g, '\\"')}"` : value}`);
}
}