fix(coding-agent): allow skill names to differ from directories

closes #4534
This commit is contained in:
Mario Zechner
2026-05-16 23:38:46 +02:00
parent d0fe8570e9
commit 5d31e70b8a
4 changed files with 8 additions and 12 deletions

View File

@@ -9,6 +9,7 @@
### Fixed
- Fixed skill diagnostics to stop warning when a skill name differs from its parent directory ([#4534](https://github.com/earendil-works/pi/issues/4534)).
- Fixed prompt template argument parsing to split unquoted multiline input on newlines ([#4553](https://github.com/earendil-works/pi/issues/4553)).
- Fixed `--resume` session listing to cap in-flight session metadata loads and avoid OOM on large session histories ([#4583](https://github.com/earendil-works/pi/issues/4583)).
- Fixed interactive error messages to render with trailing spacing so reload errors do not run into resource listings ([#4510](https://github.com/earendil-works/pi/issues/4510)).

View File

@@ -4,7 +4,7 @@
Skills are self-contained capability packages that the agent loads on-demand. A skill provides specialized workflows, setup instructions, helper scripts, and reference documentation for specific tasks.
Pi implements the [Agent Skills standard](https://agentskills.io/specification), warning about violations but remaining lenient.
Pi implements the [Agent Skills standard](https://agentskills.io/specification), warning about most violations but remaining lenient. Pi allows skill names to differ from their parent directory even though the standard disallows it; that rule is suboptimal for shared skill directories used across multiple agent harnesses.
## Table of Contents
@@ -140,7 +140,7 @@ Per the [Agent Skills specification](https://agentskills.io/specification#frontm
| Field | Required | Description |
|-------|----------|-------------|
| `name` | Yes | Max 64 chars. Lowercase a-z, 0-9, hyphens. Must match parent directory. |
| `name` | Yes | Max 64 chars. Lowercase a-z, 0-9, hyphens. Unlike the standard, Pi does not require this to match the parent directory because that standard requirement is suboptimal for shared skill directories. |
| `description` | Yes | Max 1024 chars. What the skill does and when to use it. |
| `license` | No | License name or reference to bundled file. |
| `compatibility` | No | Max 500 chars. Environment requirements. |
@@ -154,7 +154,7 @@ Per the [Agent Skills specification](https://agentskills.io/specification#frontm
- Lowercase letters, numbers, hyphens only
- No leading/trailing hyphens
- No consecutive hyphens
- Must match parent directory name
Pi does not require the name to match the parent directory. The Agent Skills standard does, but that requirement is suboptimal for shared skill directories used by multiple tools.
Valid: `pdf-processing`, `data-analysis`, `code-review`
Invalid: `PDF-Processing`, `-pdf`, `pdf--processing`
@@ -177,7 +177,6 @@ description: Helps with PDFs.
Pi validates skills against the Agent Skills standard. Most issues produce warnings but still load the skill:
- Name doesn't match parent directory
- Name exceeds 64 characters or contains invalid characters
- Name starts/ends with hyphen or has consecutive hyphens
- Description exceeds 1024 characters

View File

@@ -90,13 +90,9 @@ export interface LoadSkillsResult {
* Validate skill name per Agent Skills spec.
* Returns array of validation error messages (empty if valid).
*/
function validateName(name: string, parentDirName: string): string[] {
function validateName(name: string): string[] {
const errors: string[] = [];
if (name !== parentDirName) {
errors.push(`name "${name}" does not match parent directory "${parentDirName}"`);
}
if (name.length > MAX_NAME_LENGTH) {
errors.push(`name exceeds ${MAX_NAME_LENGTH} characters (${name.length})`);
}
@@ -301,7 +297,7 @@ function loadSkillFromFile(
const name = frontmatter.name || parentDirName;
// Validate name
const nameErrors = validateName(name, parentDirName);
const nameErrors = validateName(name);
for (const error of nameErrors) {
diagnostics.push({ type: "warning", message: error, path: filePath });
}

View File

@@ -41,7 +41,7 @@ describe("skills", () => {
expect(diagnostics).toHaveLength(0);
});
it("should warn when name doesn't match parent directory", () => {
it("should allow names that don't match parent directory", () => {
const { skills, diagnostics } = loadSkillsFromDir({
dir: join(fixturesDir, "name-mismatch"),
source: "test",
@@ -51,7 +51,7 @@ describe("skills", () => {
expect(skills[0].name).toBe("different-name");
expect(
diagnostics.some((d: ResourceDiagnostic) => d.message.includes("does not match parent directory")),
).toBe(true);
).toBe(false);
});
it("should warn when name contains invalid characters", () => {