fix(skills): safely serialize skill frontmatter#934
Conversation
📝 WalkthroughWalkthroughSkill loading now records malformed frontmatter diagnostics while retaining valid skills. Diagnostics flow through extension messages into webview state and appear in the Skills settings UI with localized guidance and source locations. ChangesSkill diagnostics discovery
Webview propagation
Settings display
Estimated code review effort: 3 (Moderate) | ~25 minutes Sequence Diagram(s)sequenceDiagram
participant SkillsManager
participant skillsMessageHandler
participant ExtensionStateContext
participant SkillsSettings
SkillsManager->>skillsMessageHandler: provide skills and diagnostics
skillsMessageHandler->>ExtensionStateContext: send skills message
ExtensionStateContext->>ExtensionStateContext: update diagnostic state
ExtensionStateContext->>SkillsSettings: expose skillDiagnostics
SkillsSettings->>SkillsSettings: render localized warning details
Suggested labels: Suggested reviewers: 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
🧹 Nitpick comments (1)
src/services/skills/SkillsManager.ts (1)
115-152: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winSurface schema and validation errors as diagnostics.
Currently, if a
SKILL.mdis valid YAML but fails schema validation (e.g., missing required fields, name mismatch, or invalid description length), it is skipped and only logged to the console. Since the diagnostics UI pipeline is now in place, consider recording these validation errors asSkillDiagnostics as well to give users actionable feedback instead of letting the skill silently disappear.💡 Proposed refactor to record validation diagnostics
const { data: frontmatter } = parsed // Validate required fields (only name and description for now) if (!frontmatter.name || typeof frontmatter.name !== "string") { + this.recordDiagnostic(skillMdPath, source, `Missing required 'name' field in frontmatter`) console.error(`Skill at ${skillDir} is missing required 'name' field`) return } if (!frontmatter.description || typeof frontmatter.description !== "string") { + this.recordDiagnostic(skillMdPath, source, `Missing required 'description' field in frontmatter`) console.error(`Skill at ${skillDir} is missing required 'description' field`) return } // Validate that frontmatter name matches the skill name (directory name or symlink name) // Per the Agent Skills spec: "name field must match the parent directory name" const effectiveSkillName = skillName || path.basename(skillDir) if (frontmatter.name !== effectiveSkillName) { + this.recordDiagnostic(skillMdPath, source, `Skill name "${frontmatter.name}" doesn't match directory "${effectiveSkillName}"`) console.error(`Skill name "${frontmatter.name}" doesn't match directory "${effectiveSkillName}"`) return } // Validate skill name per agentskills.io spec using shared validation const nameValidation = validateSkillNameShared(effectiveSkillName) if (!nameValidation.valid) { const errorMessage = this.getSkillNameErrorMessage(effectiveSkillName, nameValidation.error!) + this.recordDiagnostic(skillMdPath, source, `Skill name "${effectiveSkillName}" is invalid: ${errorMessage}`) console.error(`Skill name "${effectiveSkillName}" is invalid: ${errorMessage}`) return } // Description constraints: // - 1-1024 chars // - non-empty (after trimming) const description = frontmatter.description.trim() if (description.length < 1 || description.length > 1024) { + this.recordDiagnostic(skillMdPath, source, `Invalid description length: must be 1-1024 characters (got ${description.length})`) console.error( `Skill "${effectiveSkillName}" has an invalid description length: must be 1-1024 characters (got ${description.length})`, ) return }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/services/skills/SkillsManager.ts` around lines 115 - 152, Update the SKILL.md validation flow in SkillsManager to create and record a SkillDiagnostic for every schema validation failure before returning, including missing name, missing description, name mismatch, invalid name, and invalid description length. Preserve the existing console logging and skill-skipping behavior, and route each diagnostic through the existing diagnostics pipeline rather than only logging it.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Nitpick comments:
In `@src/services/skills/SkillsManager.ts`:
- Around line 115-152: Update the SKILL.md validation flow in SkillsManager to
create and record a SkillDiagnostic for every schema validation failure before
returning, including missing name, missing description, name mismatch, invalid
name, and invalid description length. Preserve the existing console logging and
skill-skipping behavior, and route each diagnostic through the existing
diagnostics pipeline rather than only logging it.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: 382fe9b7-e5a9-4a40-954d-674903cdde2c
📒 Files selected for processing (11)
packages/types/src/skills.tspackages/types/src/vscode-extension-host.tssrc/core/webview/__tests__/skillsMessageHandler.spec.tssrc/core/webview/skillsMessageHandler.tssrc/services/skills/SkillsManager.tssrc/services/skills/__tests__/SkillsManager.spec.tssrc/shared/skills.tswebview-ui/src/components/settings/SkillsSettings.tsxwebview-ui/src/components/settings/__tests__/SkillsSettings.spec.tsxwebview-ui/src/context/ExtensionStateContext.tsxwebview-ui/src/i18n/locales/en/settings.json
Summary
Root cause and user impact
Skill creation interpolated description text directly into double-quoted YAML frontmatter. Descriptions containing unescaped double quotes could therefore produce invalid
SKILL.mdfiles, causing frontmatter parsing to fail even when the requirednamefield was present. The parsing failure was then obscured by misleading or absent diagnostics, leaving affected skills unavailable without explaining the actual malformed YAML.This change uses safe YAML serialization for generated frontmatter and preserves actionable parse diagnostics so users can identify and correct malformed skill files.
Testing and validation
01KXSJBKY4H2SA0KV63NCNQ210completed with no findings.Fixes #859
Summary by CodeRabbit
New Features
Bug Fixes