/** * SKILL.md frontmatter — the reader the skills store keys on, parsed by a REAL YAML grammar. * * A skill's identity in the manifest is its frontmatter `name` (verified against the live garden * plugin: all 142 SKILL.md files carry `name: wicked-garden-`, unique). * Everything the store derives is a flat scalar — `name`, `context: fork`, `user-invocable: true`. * * Earlier passes hand-rolled a bracket-depth heuristic; it accepted invalid YAML a real parser * rejects (`[a, {b: c]]`, `"bad\q"`, `"hello" "world"` — codex round 3). We now parse the block * with the `yaml` library (the same grammar Claude Code loads a skill with) and refuse ANYTHING it * rejects, then enforce a STRICT SUBSET on top: * * - a single YAML document that is a top-level MAPPING (`key: value` pairs) — not a sequence, * not a bare scalar, not multiple documents; * - `name`, if present, is a SCALAR (a mapping/sequence is refused — the manifest is keyed by it); * - `mandates`, if present, is a LIST of non-empty STRINGS (a scalar/mapping, or an entry that is * not a string, is refused). * * `fields` flattens the top-level scalars to strings (`user-invocable: true` → `"true"`, * `name: "x"` → `"x"`) — the only shapes the store reads. A non-scalar value (a nested mapping the * strict checks above do not forbid for that key) is serialized to JSON so `fields` stays a flat * `Record`; the store never reads those. * * `mandates` is ALSO handed out structurally (`MandateDecl[]`): the qualified name each entry * spells AS THE PARSER DECODED IT (`"wicked-garden-gamma"` is `wicked-garden-gamma`; the Claude * plugin form `wicked-garden:x` is normalized to `wicked-garden-x`) with the 1-based line of the * entry, taken from the YAML node's range — never from a regex over the raw block (codex round 4: * the core closure used to find mandates by scanning raw text, so an escaped scalar hid one). */ import type { SkillKind } from '../core/types.js'; /** One declared mandate: the catalog name it spells (normalized) and its 1-based line in the file. */ export interface MandateDecl { name: string; line: number; } export type FrontmatterResult = { ok: true; fields: Record; mandates: MandateDecl[]; } | { ok: false; reason: string; }; /** * `text` with its frontmatter block (both fences included) replaced by blank lines — the same * line count, so a line number found in the result is a line number in the file. Prose scans * (core-closure.ts) run over THIS, never over the frontmatter: a declared mandate comes from the * parser (`parseFrontmatter().mandates`), a frontmatter scalar is not prose. A text without a * complete frontmatter block is returned unchanged (its guard reports the missing fence). */ export declare function bodyWithFrontmatterBlanked(text: string): string; /** * Parse the frontmatter block at the top of `text` with a real YAML parser and enforce the strict * subset (single-document mapping, scalar `name`, list `mandates`). Anything the parser rejects is * a parse failure carrying the parser's own reason; a well-formed block yields the flat scalar * `fields` the store keys on. */ export declare function parseFrontmatter(text: string): FrontmatterResult; /** The catalog name a declared mandate spells: the Claude plugin form `wicked-garden:x` is `wicked-garden-x`. */ export declare function qualifiedSkillName(raw: string): string; /** * The skill kind the frontmatter declares (design v3 §5, fork-first): `context: fork` is a fork * worker (a subagent body) even when it is also user-invocable (`archetype`, `smaht`); * `user-invocable: true` a router (an operator-facing entry point); everything else a module (a * nested reference skill routers/workers pull in). */ export declare function skillKindOf(fields: Readonly>): SkillKind; /** The plugin the effective root impersonates — the identity workers already invoke skills under. */ export declare const PLUGIN_NAME = "wicked-garden"; /** Every manifest key carries this prefix: `wicked-garden-`. */ export declare const SKILL_NAME_PREFIX = "wicked-garden-"; /** * The frontmatter name a skill at `skills/` must declare — `relDir` is POSIX-relative to * the plugin's `skills/` directory (`engineering/frontend` → `wicked-garden-engineering-frontend`). */ export declare function derivedSkillName(relDir: string): string; //# sourceMappingURL=frontmatter.d.ts.map