fix(skills): cap skill descriptions at harness limit (#643)
Some checks failed
CI / pr-title (push) Has been cancelled
CI / test (push) Has been cancelled
Release PR / release-pr (push) Has been cancelled
Release PR / publish-cli (push) Has been cancelled

This commit is contained in:
Trevin Chow
2026-04-21 21:56:15 -07:00
committed by GitHub
parent 5a26a8fbd3
commit 13f95ba639
3 changed files with 14 additions and 1 deletions

View File

@@ -86,6 +86,7 @@ When adding or modifying skills, verify compliance with the skill spec:
- [ ] `name:` present and matches directory name (lowercase-with-hyphens)
- [ ] `description:` present and describes **what it does and when to use it** (per official spec: "Explains code with diagrams. Use when exploring how code works.")
- [ ] `description:` is no longer than 1024 characters -- some coding harnesses reject longer skill descriptions. Enforced by `tests/frontmatter.test.ts`.
- [ ] `description:` value is quoted (single or double) if it contains colons -- unquoted colons break `js-yaml` strict parsing and crash `install --to opencode/codex`. Run `bun test tests/frontmatter.test.ts` to verify.
- [ ] `description:` value does not contain raw angle-bracket tokens like `<skill-name>`, `<tag>`, or `<placeholder>` -- Cowork's plugin validator parses descriptions as HTML and rejects unknown tags with a generic "Plugin validation failed" banner (see issue #602). Claude Code tolerates them, so the bug only surfaces downstream. Backtick-wrap the token (`` `<skill-name>` ``) or rephrase. Enforced by `tests/frontmatter.test.ts`.

View File

@@ -1,6 +1,6 @@
---
name: ce-proof
description: Create, share, view, comment on, edit, and run human-in-the-loop review loops over markdown documents via Proof the collaborative markdown editor and renderer at proofeditor.ai (also called "Proof editor"). Use this skill whenever the user wants to view or render a local markdown file in Proof for easier reading, share a markdown file to Proof to get a shareable URL, iterate on a Proof doc collaboratively, comment on or suggest edits in a Proof doc, HITL a spec/plan/draft for human review, sync a Proof doc back to local, or when given a proofeditor.ai URL. Common phrasings include "view this in proof", "render this markdown in proof", "open this md file in proof", "share it to proof", "share to proof editor", "iterate with proof", "HITL this doc". Upstream handoffs from ce-brainstorm / ce-ideate / ce-plan for human review also belong here. Match these intents even when the user doesn't name Proof, as long as they clearly want a rendered/shared markdown surface. Do NOT trigger on "proof" meaning evidence, a mathematical/logical proof, burden of proof, proof-of-concept, or a bare "proofread this" request where the model is expected to review text inline.
description: Create, share, view, comment on, edit, and run human-in-the-loop review loops over markdown documents via Proof, the collaborative markdown editor at proofeditor.ai ("Proof editor"). Use when the user wants to render or view a local markdown file in Proof, share markdown to get a URL, iterate collaboratively on a Proof doc, comment on or suggest edits in Proof, HITL a spec/plan/draft for human review, sync a Proof doc back to local, or work from a proofeditor.ai URL. Trigger on phrases like "view this in proof", "share to proof", "iterate with proof", or "HITL this doc", and on ce-brainstorm / ce-ideate / ce-plan handoffs for human review. Also match clear requests for a rendered/shared markdown review surface even if the user does not name Proof. Do not trigger on "proof" meaning evidence, math/logic proof, burden of proof, proof-of-concept, or bare "proofread this" requests where inline text review is expected.
allowed-tools:
- Bash
- Read

View File

@@ -58,6 +58,7 @@ function collectFrontmatterFiles(pluginRoot: string): [string, string][] {
}
describe("frontmatter YAML validity", () => {
const MAX_SKILL_DESCRIPTION_LENGTH = 1024
const pluginRoots = [
"plugins/compound-engineering",
"plugins/coding-tutor",
@@ -83,6 +84,17 @@ describe("frontmatter YAML validity", () => {
const bareTag = stripped.match(/<[A-Za-z][\w-]*>/)
expect(bareTag, `Backtick-wrap or rephrase: ${bareTag?.[0] ?? ""}`).toBeNull()
})
if (/^skills\/[^/]+\/SKILL\.md$/.test(rel)) {
test(`${pluginRoot}/${rel} skill description fits 1024-char harness limit`, () => {
const parsed = load(yaml) as Record<string, unknown> | null
const description = parsed && typeof parsed.description === "string" ? parsed.description : ""
expect(
[...description].length,
`Shorten description to ${MAX_SKILL_DESCRIPTION_LENGTH} chars or less`,
).toBeLessThanOrEqual(MAX_SKILL_DESCRIPTION_LENGTH)
})
}
}
}
})