Skip to content

fix: validate skill names and duplicate frontmatter keys - #277

Merged
conorbronsdon merged 7 commits into
conorbronsdon:mainfrom
sharadvc:cursor/fix-duplicate-skill-name-259-5814
Sep 16, 2026
Merged

conorbronsdon merged 7 commits into
conorbronsdon:mainfrom
sharadvc:cursor/fix-duplicate-skill-name-259-5814

Conversation

@sharadvc

@sharadvc sharadvc commented Sep 13, 2026

Copy link
Copy Markdown
Contributor

This change retains the required name in every installable and generated skill manifest. The validator now rejects names that differ from their skill directory and detects duplicate top-level frontmatter keys, including equivalent plain, quoted, and Unicode-escaped keys. Duplicate sibling skill identities remain rejected within each plugin.

The contributor history is preserved and current main is incorporated. Generated distributions keep their original required names; metadata stripping remains byte-exact for the remaining content.

Validation:

  • All 20 npm test suites passed; self-scan and local plugin validation passed.
  • Regression controls cover missing/empty names, quoted name mismatches, sibling collisions, mixed quoted/unquoted duplicates, JSON-style quoted keys, nested-key exclusions, and generated-name preservation. The original parser misses the quoted duplicate that the new parser detects.
  • Built and extracted the 44-file plugin. skills-ref 0.1.0 accepts six of seven skills; the canonical skill is rejected only for its pre-existing version field, identically reproduced on unchanged main. No extracted skill is missing its required name.
  • The Windows symlink test is skipped because the OS does not grant symlink creation; Linux CI covers that check.

Fixes #259.

Generated SKILL.full.md and the OpenAI bundled skill copy no longer repeat
the top-level name field when the parent directory already defines the skill
id. Root SKILL.md keeps an explicit name for single-file installs.

Add frontmatter duplicate-key checks in the OpenAI plugin validator.

Fixes conorbronsdon#259
@qodo-free-for-open-source-projects

Copy link
Copy Markdown

PR Summary by Qodo

Remove redundant names from generated skill copies

🐞 Bug fix 🧪 Tests 🕐 20-40 Minutes

Grey Divider

AI Description

• Removes redundant name frontmatter from flattened and OpenAI bundled skill copies.
• Preserves the root skill name for standalone installations while directories identify bundled
 skills.
• Detects duplicate frontmatter keys and verifies generated-copy transformations with regression
 tests.
Diagram

graph TD
  ROOT["Root SKILL.md"] --> FLAT["Flatten script"] --> FULL["Flattened copies"]
  ROOT --> SYNC["Plugin sync"] --> COPY["OpenAI transform"] --> BUNDLE["Bundled skill"] --> VALIDATE["Plugin validator"]
  ROOT --> VALIDATE
Loading
High-Level Assessment

The current approach is appropriate: keep name in the standalone canonical skill, strip it only within generation paths where the directory is authoritative, and reuse the OpenAI transformation for both synchronization and drift validation. A general YAML parser was considered but would add a dependency and make byte-preserving transformations harder, while separate sync and validation transforms could diverge.

Files changed (9) +117 / -26

Bug fix (6) +87 / -13
SKILL.full.mdRemove name from flattened skill artifact +0/-1

Remove name from flattened skill artifact

• Removes the redundant 'name' key from the generated all-in-one skill while retaining the remaining frontmatter and content.

SKILL.full.md

avoid-ai-writing.mdRemove name from distribution copy +0/-1

Remove name from distribution copy

• Drops the redundant skill name from the generated distribution artifact's frontmatter.

dist/avoid-ai-writing.md

flatten-skill.jsStrip names when generating flattened skills +10/-1

Strip names when generating flattened skills

• Adds a frontmatter transformation that removes top-level 'name' lines from flattened output. The root 'SKILL.md' remains unchanged for standalone installation support.

scripts/flatten-skill.js

sync-plugin-skill.shUse the canonical OpenAI copy transform +5/-4

Use the canonical OpenAI copy transform

• Switches plugin synchronization to a dedicated transformation that removes both portal-rejected metadata and the redundant name. Comments now document both intentional differences from the canonical root skill.

scripts/sync-plugin-skill.sh

validate-openai-plugin.pyValidate frontmatter uniqueness and directory-based names +72/-5

Validate frontmatter uniqueness and directory-based names

• Adds duplicate top-level frontmatter key detection and permits bundled skills to derive their name from the containing directory. It also validates explicit names against directory names and centralizes OpenAI copy generation that strips metadata and 'name'.

scripts/validate-openai-plugin.py

SKILL.mdRemove name from bundled OpenAI skill +0/-1

Remove name from bundled OpenAI skill

• Removes the redundant 'name' field because the 'avoid-ai-writing' directory already supplies the bundled skill identifier.

skills/avoid-ai-writing/SKILL.md

Tests (1) +25 / -12
validate-openai-plugin.test.pyCover directory names and frontmatter transformations +25/-12

Cover directory names and frontmatter transformations

• Adds coverage for nameless directory-scoped skills, OpenAI copy transformation, CLI output, and generated flattened artifacts. Existing required-field tests now target missing descriptions rather than requiring explicit names.

scripts/validate-openai-plugin.test.py

Documentation (2) +5 / -1
CHANGELOG.mdDocument generated skill name removal +4/-0

Document generated skill name removal

• Adds an Unreleased fix entry explaining that generated directory-scoped skill copies no longer repeat the authoritative directory name in frontmatter.

CHANGELOG.md

submission-pack.jsonDescribe both canonical copy omissions +1/-1

Describe both canonical copy omissions

• Updates submission metadata to state that the OpenAI copy intentionally omits both the metadata block and redundant name field.

submission/submission-pack.json

@qodo-free-for-open-source-projects

qodo-free-for-open-source-projects Bot commented Sep 13, 2026

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (0) 📘 Rule violations (0) 📎 Requirement gaps (0) 🎨 UX issues (0) 🔗 Cross-repo conflicts (0) 📜 Skill insights (0)

Grey Divider


Remediation recommended

1. Quoted names bypass skill checks ✓ Resolved 🐞 Bug ≡ Correctness
Description
duplicate_top_level_frontmatter_keys and parse_frontmatter preserve quotes around mapping keys,
so YAML keys such as name and "name" are treated as different strings. A quoted name that
conflicts with the skill directory therefore triggers the missing-name fallback instead of the
mismatch check, and combining quoted and unquoted forms also evades the new duplicate-key check.
Code

scripts/validate-openai-plugin.py[R54-55]

+        key = line.split(":", 1)[0].strip()
+        counts[key] = counts.get(key, 0) + 1
Evidence
The parser strips quotes only from values while retaining them in key, and the duplicate detector
likewise counts the raw text before the colon. The new fallback and mismatch check consult only the
exact unquoted name key, proving that "name": another-skill is interpreted as absent rather than
conflicting and that name plus "name" is not counted as a duplicate.

scripts/validate-openai-plugin.py[34-39]
scripts/validate-openai-plugin.py[46-56]
scripts/validate-openai-plugin.py[548-559]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Valid quoted YAML keys are not normalized, allowing conflicting or duplicate `name` fields to bypass the newly added validation.
## Fix Focus Areas
- scripts/validate-openai-plugin.py[34-39]
- scripts/validate-openai-plugin.py[46-56]
- scripts/validate-openai-plugin.py[548-559]
- scripts/validate-openai-plugin.test.py[245-265]
## Recommended Fix
Canonicalize supported quoted scalar keys before storing or counting them, or explicitly reject quoted keys as unsupported. Add tests showing that a quoted mismatching `name` is rejected and that mixed quoted/unquoted duplicate keys are reported.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

Tip of the day
💡 Did you know, you can group findings by type and pick your Finding display, from Minimal to Full

More tips ↗ | Customize Qodo ↗ | Qodo docs ↗

Grey Divider

Qodo Logo

Comment thread scripts/validate-openai-plugin.py Outdated

@conorbronsdon conorbronsdon left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

Codex review, with a GPT-5.6 Sol reviewer, at Conor's request.

Thanks, @sharadvc, for investigating the duplicate-identity report and adding validation. The proposed removal of name breaks an installation contract, so this needs a different approach before merge.

The Agent Skills specification requires name and requires it to match the skill directory. OpenAI's skill documentation also requires name and description; its submission errors distinguish skill_name_missing from duplicate identity within one plugin. Repeated required metadata in separate distribution artifacts is not itself duplicate skill identity.

An extracted 44-file package passes this PR's weakened local validator but fails the official skills-ref validator with a missing-name error. The quoted-key bypass reported by Qodo also reproduces.

Please retain one explicit name in each installable SKILL manifest, require and compare it to the directory, and focus duplicate-identity checks on sibling skills in the same plugin. Normalize quoted and unquoted YAML keys consistently so mixed-key duplicates cannot pass. Tests should reject a missing name, mismatched quoted names, and quoted/unquoted duplicates, and verify the extracted package against the external contract. The additional validation is useful work to preserve in that revision.

@conorbronsdon conorbronsdon changed the title fix(skills): drop redundant name frontmatter from generated copies fix: validate skill names and duplicate frontmatter keys Sep 16, 2026

@conorbronsdon conorbronsdon left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

Verified b3ff769: required names are retained, directory mismatches and duplicate identities are rejected, and unsupported key syntax fails validation. Local tests and CI pass. Independent Claude Sonnet 5, Muse Spark 1.3, and MiMo v2.5 reviews completed with no outstanding verified findings. The external reference-validator version-field limitation is reproduced on unchanged main and documented in the PR.

@conorbronsdon
conorbronsdon merged commit 9561a75 into conorbronsdon:main Sep 16, 2026
3 checks passed
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.

Duplicate name field in SKILL.md files

2 participants