diff options
Diffstat (limited to 'subagents')
| -rw-r--r-- | subagents/frontmatter.lua | 44 |
1 files changed, 39 insertions, 5 deletions
diff --git a/subagents/frontmatter.lua b/subagents/frontmatter.lua index 94fe2ac..8740870 100644 --- a/subagents/frontmatter.lua +++ b/subagents/frontmatter.lua @@ -13,8 +13,9 @@ -- (a lone `---` at the top of a prose file is a horizontal rule, not a -- broken header, so this case is deliberately silent) -- * empty fenced block -> empty mapping, no warning --- * lyaml missing or erroring -> body after the fence, warning returned +-- * parser missing or erroring-> body after the fence, warning returned -- * YAML document not a map -> body after the fence, warning returned +-- * unresolved anchor/alias -> that key dropped, warning returned -- -- In the warning cases the fenced block is dropped rather than folded back -- into the body: an unparseable header is noise the child agent should not be @@ -27,6 +28,34 @@ local function trim(s) return (s:gsub("^%s+", ""):gsub("%s+$", "")) end +-- tinyyaml parses a subset of YAML: it does not resolve anchors (`&a`) or +-- aliases (`*a`). Rather than failing on them it hands back the raw token as +-- a plain string, so `name: *base` arrives here as the literal "*base" and +-- would sail through any `type(v) == "string"` check to become a profile's +-- actual name. Detect that shape and drop those keys so the caller falls back +-- to its defaults instead of adopting a bogus value. +-- +-- The match is deliberately narrow -- a whole value that is exactly `*word`, +-- or one opening with `&word ` -- so ordinary prose containing `*` or `&` +-- (`'fetch & parse'`, `'a *b* c'`) is left alone. +local function strip_unresolved_aliases(data) + local hits = {} + for k, v in pairs(data) do + if type(v) == "string" + and (v:match("^%*[%w_%-]+$") or v:match("^&[%w_%-]+%s")) then + hits[#hits + 1] = tostring(k) + end + end + if #hits == 0 then + return nil + end + table.sort(hits) + for _, k in ipairs(hits) do + data[k] = nil + end + return table.concat(hits, ", ") +end + -- Iterate lines, yielding the line plus its start offset and the offset just -- past its newline, so the caller can slice the original text exactly. local function lines(text) @@ -79,17 +108,22 @@ function M.parse(text) return {}, body, nil end - local ok_lyaml, lyaml = pcall(require, "lyaml") - if not ok_lyaml then - return nil, body, "lyaml is not installed; ignoring the YAML frontmatter" + local ok_yaml, yaml = pcall(require, "tinyyaml") + if not ok_yaml then + return nil, body, "tinyyaml is not installed; ignoring the YAML frontmatter" end - local ok, data = pcall(lyaml.load, block) + local ok, data = pcall(yaml.parse, block) if not ok then return nil, body, "YAML frontmatter did not parse: " .. tostring(data) end if type(data) ~= "table" then return nil, body, "YAML frontmatter is not a mapping; ignoring it" end + local aliased = strip_unresolved_aliases(data) + if aliased then + return data, body, + "YAML anchors/aliases are not supported; ignoring: " .. aliased + end return data, body, nil end |
