Skip to content

fix(ce-compound): quote YAML array items starting with reserved indicators#607

Closed
nathanvale wants to merge 1 commit intoEveryInc:mainfrom
nathanvale:fix/ce-compound-yaml-safety
Closed

fix(ce-compound): quote YAML array items starting with reserved indicators#607
nathanvale wants to merge 1 commit intoEveryInc:mainfrom
nathanvale:fix/ce-compound-yaml-safety

Conversation

@nathanvale
Copy link
Copy Markdown
Contributor

Summary

Fixes #606/ce-compound emits invalid YAML frontmatter when an array item in symptoms:, applies_when:, tags:, related_components: (or any future array-of-strings field) starts with a backtick or other YAML 1.2 reserved indicator. Strict parsers (yq, js-yaml strict, PyYAML) reject the file; ce-learnings-researcher's grep-first retrieval still matches on substrings, so users silently accumulate unparseable files until a structural consumer fails.

This PR encodes the quoting rule in the support-file contract that every ce-compound and ce-compound-refresh subagent reads at write time, then reinforces it with one-line pointers at the three SKILL.md spots that write or dispatch writes of frontmatter, and a preamble comment on the frontmatter template. A regression test asserts the rule is present in every surface.

Same shape of fix as #603 (which handled the description: angle-bracket-token case): codify the rule + add a test.

Changes

Surface Change
references/schema.yaml Added a validation_rules entry for array-item quoting
references/yaml-schema.md New "## YAML Safety Rules" section with indicator list, ": " trap, and before/after example
assets/resolution-template.md Added a preamble comment above each frontmatter block pointing to the rule
ce-compound/SKILL.md Added one-line pointer at Phase 2 step 5 (Full mode) and step 3 (Lightweight mode)
ce-compound-refresh/SKILL.md Added pointer to the Replace-flow subagent dispatch
tests/compound-support-files.test.ts Added 8 regression tests asserting rule presence across all 4 support files and both SKILL.md files

Support-file edits are applied to both skill copies in the same commit to keep tests/compound-support-files.test.ts's existing drift assertions green.

Rule body lives in the on-demand-loaded reference file, not in SKILL.md — keeps the load-time token footprint flat per plugin AGENTS.md Rationale Discipline.

Scope Boundaries

  • Does not auto-repair existing invalid frontmatter in users' repos — this fix is forward-looking. A cleanup utility is a possible follow-up PR.
  • Does not extend quoting guidance to description: or other scalar string fields — fix(ce-release-notes): backtick-wrap <skill-name> token in description #603 already covered that.
  • Does not audit other skills that write frontmatter (ce-brainstorm, ce-plan, ce-release-notes). Each has its own prompt surface; this PR addresses ce-compound and ce-compound-refresh only.

Test plan

  • bun test tests/compound-support-files.test.ts — 11/11 pass (3 drift + 8 new regression)
  • bun test tests/frontmatter.test.ts — 192/192 pass (SKILL.md frontmatter validity preserved)
  • Mutation test: removing the validation_rules entry → 2 expected failures fire (the YAML-safety assertion + the drift test). Rule presence is enforced.
  • Full suite: 888/889 pass. The single failure (tests/resolve-base.sh > resolves against origin/HEAD in a detached shallow checkout) reproduces on clean main in this shallow-clone checkout and is unrelated to these changes.

Plan document: docs/plans/2026-04-20-001-fix-ce-compound-yaml-safety-plan.md (included in the commit for traceability).

…ators

Array items in frontmatter fields like `symptoms:` that start with a
backtick or other YAML 1.2 reserved indicator (`, [, *, &, !, |, >, %,
@, ?) or contain `: ` must be wrapped in double quotes — otherwise
strict parsers (`yq`, `js-yaml` strict, PyYAML) reject the file.
`ce-learnings-researcher`'s grep-first retrieval still matches, masking
the problem until a structural consumer fails.

Encode the rule in the support-file contract that every ce-compound
and ce-compound-refresh subagent reads at write time:

- Add a validation rule to `references/schema.yaml`
- Add a "YAML Safety Rules" section to `references/yaml-schema.md`
  with indicator list, `: ` trap, and before/after example
- Add preamble comments above each frontmatter block in
  `assets/resolution-template.md`
- Add one-line pointers at the three SKILL.md spots that write or
  dispatch writes of frontmatter
- Add 8 regression tests asserting the rule is present in every
  surface; mutation-tested by removing the rule and confirming failure

Support-file edits are applied to both skill copies in the same commit
to keep `tests/compound-support-files.test.ts` drift assertions green.

Fixes EveryInc#606.

Co-Authored-By: Claude <[email protected]>
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 3895b1acf7

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment on lines +82 to +84
const mentions = raw.match(/yaml-schema\.md/g) ?? []
// Both Full-mode Phase 2 step 5 and Lightweight mode step 3 should mention the rule.
expect(mentions.length).toBeGreaterThanOrEqual(2)
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Require YAML-safety pointers in each ce-compound write path

This test claims to protect both frontmatter-writing locations, but mentions.length >= 2 counts all yaml-schema.md occurrences in the file, including unrelated references. Because ce-compound/SKILL.md already contains a non-write-path mention, one of the two targeted write-path pointers can be removed and the test will still pass. That leaves either Full mode or Lightweight mode unprotected against regressing the YAML-quoting guidance.

Useful? React with 👍 / 👎.

@tmchow
Copy link
Copy Markdown
Collaborator

tmchow commented Apr 20, 2026

@nathanvale Thanks for the contribution!

  1. Can you look at the codex feedback?
  2. How much testing have you done yourself with this change?

@tmchow
Copy link
Copy Markdown
Collaborator

tmchow commented Apr 20, 2026

Closing in favor of #613

@tmchow tmchow closed this Apr 20, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

/ce-compound emits invalid YAML frontmatter when symptoms[] item starts with backtick

2 participants