medlab / case

medlab

what got hurt, and what now fails loudly

↑ sublayer

2026-09-12 · fixed: yes

YAML frontmatter with a colon-space in a scalar value is a mapping

StructuralRuntimeSchema Validator

now fails loudly Every SKILL.md frontmatter is parsed as YAML by a test; a frontmatter block that does not parse fails CI.

What broke

A fleet of AI coding agents — each a long-lived session running under a supervisor — shares a set of skills: small instruction files (SKILL.md) the agents load at startup and on demand, each with a YAML frontmatter block naming the skill and saying when to use it. The agent platform (Crush) reads that block to decide which skills to make available; a parse failure is silent — the skill is simply not loaded.

One skill, forge, wraps the station's self-hosted git forge API with commands agents use to create pull requests, read CI status, and merge. Its frontmatter description line was a single sentence containing a colon followed by a space, in the middle of prose explaining why the skill exists.

YAML interprets <string>: <string> as a mapping key and value. A colon-space in an unquoted scalar at the top level splits the value into a new mapping key, so the frontmatter block became invalid YAML. Crush rejected it, and the agent ran without the forge skill for an unknown length of time — and nothing, including the agent itself, recorded that this had happened.

How it showed

Nothing showed at first. The agent continued to operate; the skill's absence was invisible, because the agent found other ways to interact with the forge and produced pull request descriptions and commits without incident on tasks where forge was a convenience rather than a necessity. The frontmatter block emitted no parse error to any log, and the agent had no mechanism to assert "I have the forge skill loaded."

A human reading the skill file noticed the description field — at 99 words, the only field in the block long enough, and containing prose, to hold a colon-space YAML would misinterpret. Every other frontmatter value was a single word, a slug, or a URL, none of which trigger the mapping rule.

What was watching

No sensor was on the path. The YAML frontmatter in a SKILL.md file is metadata consumed by a platform that treats parse failures as "skip this skill," and the metadata block itself had no schema, no validator, and no test that read it before the platform did. The only consumer of the file was the parser, and the parser's own error handling was to discard silently rather than report.

It is unknown how long the agent ran without the skill, because nothing logs when a frontmatter block fails to parse.

Where it sits

This is a structural failure: a file in a format that permits ambiguity — YAML with unquoted scalars containing a colon-space — was ambiguous in a way its consumer silently rejected, with nothing else checking it. It is also a runtime failure: the agent operated without a skill it was supposed to have, and neither the agent nor its supervisor could tell.

The schema validator sensor is the one that names this: a check that asserts the structure of a document before something downstream depends on it. A test that reads every SKILL.md, parses its frontmatter as YAML, and fails CI on a parse error is exactly that, and it did not exist on this path.

What we did

Changed description: to description: >, YAML's folded block scalar indicator, so the entire description is one string regardless of what it contains. A colon-space inside a folded block is text, not a mapping delimiter.

A test was added to CI: it reads every SKILL.md in the shared skills directory, parses the frontmatter block as YAML, and asserts it contains the required keys. A file that does not parse as YAML fails the build. The instruction to agents writing skill files now says: if a description contains a colon-space, use description: > with an indented block.

What now fails loudly

  • Every SKILL.md frontmatter is parsed as YAML in CI. A file whose

frontmatter does not parse fails the build; the parser's silent skip is no longer the only consumer of the file.

  • A folded scalar is the default for multi-line descriptions. The

SKILL.md template and the agent instructions both specify it, so the fix is the default form, not a warning to be careful with colons.