diff --git a/AGENTS.md b/AGENTS.md index b06f0296..10194031 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -24,6 +24,7 @@ read README.md, then ask which module(s) to work on. Based on the answer, read t - Note: `npm run check` does not run tests. - NEVER run: `npm run dev`, `npm run build`, `npm test` - Only run specific tests if user instructs: `npm test -- test/specific.test.ts` +- Run tests from the package root, not the repo root. - When writing tests, run them, identify issues in either the test or implementation, and iterate until fixed. - NEVER commit unless user asks diff --git a/packages/coding-agent/CHANGELOG.md b/packages/coding-agent/CHANGELOG.md index 3dfd78f9..c21c6d44 100644 --- a/packages/coding-agent/CHANGELOG.md +++ b/packages/coding-agent/CHANGELOG.md @@ -8,6 +8,7 @@ ### Fixed +- Ignored unknown skill frontmatter fields when loading skills - Fixed `/reload` not picking up changes in global settings.json ([#1241](https://github.com/badlogic/pi-mono/issues/1241)) - Fixed Unix bash detection to fall back to PATH lookup when `/bin/bash` is unavailable, including Termux setups ([#1230](https://github.com/badlogic/pi-mono/pull/1230) by [@VaclavSynacek](https://github.com/VaclavSynacek)) diff --git a/packages/coding-agent/docs/skills.md b/packages/coding-agent/docs/skills.md index 588d5fc1..66b09fa1 100644 --- a/packages/coding-agent/docs/skills.md +++ b/packages/coding-agent/docs/skills.md @@ -176,7 +176,8 @@ Pi validates skills against the Agent Skills standard. Most issues produce warni - Name exceeds 64 characters or contains invalid characters - Name starts/ends with hyphen or has consecutive hyphens - Description exceeds 1024 characters -- Unknown frontmatter fields + +Unknown frontmatter fields are ignored. **Exception:** Skills with missing description are not loaded. diff --git a/packages/coding-agent/src/core/skills.ts b/packages/coding-agent/src/core/skills.ts index 8b25cc9c..2666d04b 100644 --- a/packages/coding-agent/src/core/skills.ts +++ b/packages/coding-agent/src/core/skills.ts @@ -5,20 +5,6 @@ import { CONFIG_DIR_NAME, getAgentDir } from "../config.js"; import { parseFrontmatter } from "../utils/frontmatter.js"; import type { ResourceDiagnostic } from "./diagnostics.js"; -/** - * Standard frontmatter fields per Agent Skills spec. - * See: https://agentskills.io/specification#frontmatter-required - */ -const ALLOWED_FRONTMATTER_FIELDS = new Set([ - "name", - "description", - "license", - "compatibility", - "metadata", - "allowed-tools", - "disable-model-invocation", -]); - /** Max name length per spec */ const MAX_NAME_LENGTH = 64; @@ -91,19 +77,6 @@ function validateDescription(description: string | undefined): string[] { return errors; } -/** - * Check for unknown frontmatter fields. - */ -function validateFrontmatterFields(keys: string[]): string[] { - const errors: string[] = []; - for (const key of keys) { - if (!ALLOWED_FRONTMATTER_FIELDS.has(key)) { - errors.push(`unknown frontmatter field "${key}"`); - } - } - return errors; -} - export interface LoadSkillsFromDirOptions { /** Directory to scan for skills */ dir: string; @@ -197,16 +170,9 @@ function loadSkillFromFile( try { const rawContent = readFileSync(filePath, "utf-8"); const { frontmatter } = parseFrontmatter(rawContent); - const allKeys = Object.keys(frontmatter); const skillDir = dirname(filePath); const parentDirName = basename(skillDir); - // Validate frontmatter fields - const fieldErrors = validateFrontmatterFields(allKeys); - for (const error of fieldErrors) { - diagnostics.push({ type: "warning", message: error, path: filePath }); - } - // Validate description const descErrors = validateDescription(frontmatter.description); for (const error of descErrors) { diff --git a/packages/coding-agent/test/skills.test.ts b/packages/coding-agent/test/skills.test.ts index c4979efd..b536ad40 100644 --- a/packages/coding-agent/test/skills.test.ts +++ b/packages/coding-agent/test/skills.test.ts @@ -65,19 +65,14 @@ describe("skills", () => { expect(diagnostics.some((d: ResourceDiagnostic) => d.message.includes("description is required"))).toBe(true); }); - it("should warn when unknown frontmatter fields are present", () => { + it("should ignore unknown frontmatter fields", () => { const { skills, diagnostics } = loadSkillsFromDir({ dir: join(fixturesDir, "unknown-field"), source: "test", }); expect(skills).toHaveLength(1); - expect( - diagnostics.some((d: ResourceDiagnostic) => d.message.includes('unknown frontmatter field "author"')), - ).toBe(true); - expect( - diagnostics.some((d: ResourceDiagnostic) => d.message.includes('unknown frontmatter field "version"')), - ).toBe(true); + expect(diagnostics).toHaveLength(0); }); it("should load nested skills recursively", () => {