From 8463c87dfc73b29489f83dbb8700657f20918d60 Mon Sep 17 00:00:00 2001 From: Defame1297 Date: Sat, 4 Jul 2026 11:10:32 +0000 Subject: [PATCH] feat(kyberforge): improve agent-audit skill with platform-accurate checks and description quality reference - Fix validate.sh: remove incorrect name==stem check for CC files (CC docs say filename need not match name field); keep check for Copilot CLI only - Fix validate.sh: plugin scope detection now checks both plugin.json and .claude-plugin/plugin.json - Fix validate.sh: Copilot cloud/IDE agents (.github/copilot/agents/) have name as optional; path-based guard added - Add validate.sh checks: Copilot body length >30,000 chars (SUGGESTION), Copilot-only fields in CC files (FAIL), subagent-unavailable tools in tools field (SUGGESTION) - Add references/description-quality.md as conditional escape hatch for borderline description findings - SKILL.md: name five audit dimensions in description; sharpen indirect-trigger phrasing - SKILL.md: label pair-mandate as kyberforge project convention, not platform requirement - SKILL.md: scope redundant name-match/body-empty checks to manual fallback only - SKILL.md: add conditional reference to description-quality.md; update provider-safety description for new check categories; fix plugin scope gotcha to mention .claude-plugin/plugin.json - SKILL.md: add INFO tier to result block template - Add source_keys frontmatter to references/README.md; update sources.md to add description-quality.md to contributing files Co-Authored-By: Claude Sonnet 4.6 Claude-Session: https://claude.ai/code/session_0147vXtL5sP6vorDdqXGJJU9 --- .../kyberforge/skills/agent-audit/README.md | 1 + .../kyberforge/skills/agent-audit/SKILL.md | 28 ++++--- .../skills/agent-audit/references/README.md | 5 ++ .../references/description-quality.md | 49 ++++++++++++ .../agent-audit/references/field-inventory.md | 4 + .../skills/agent-audit/references/sources.md | 10 +-- .../skills/agent-audit/scripts/validate.sh | 75 +++++++++++++++---- 7 files changed, 142 insertions(+), 30 deletions(-) create mode 100644 plugins/kyberforge/skills/agent-audit/references/description-quality.md diff --git a/plugins/kyberforge/skills/agent-audit/README.md b/plugins/kyberforge/skills/agent-audit/README.md index f701bc5..6316d5f 100644 --- a/plugins/kyberforge/skills/agent-audit/README.md +++ b/plugins/kyberforge/skills/agent-audit/README.md @@ -20,6 +20,7 @@ Pass the path to either agent file as the argument. |------|---------| | `SKILL.md` | Skill instructions for agents | | `references/README.md` | Directory documentation for references/ | +| `references/description-quality.md` | Qualitative guide for borderline description findings | | `references/field-inventory.md` | Authoritative list of valid CC and Copilot agent fields | | `references/sources.md` | Research provenance for skill content | | `scripts/README.md` | Directory documentation for scripts/ | diff --git a/plugins/kyberforge/skills/agent-audit/SKILL.md b/plugins/kyberforge/skills/agent-audit/SKILL.md index a26ea17..1823f17 100644 --- a/plugins/kyberforge/skills/agent-audit/SKILL.md +++ b/plugins/kyberforge/skills/agent-audit/SKILL.md @@ -4,11 +4,12 @@ description: > Use when the user wants to review an agent definition they wrote, says "audit this agent", "check if my agent follows best practices", "review my agent file", or wants to know if an agent pair is ready to ship — even if they don't use the word "audit". - Audits a Claude Code .md and Copilot .agent.md agent file pair — structural - validation via validate.sh plus qualitative checks on description and system prompt. - Produces a compact findings report (findings only, no PASS noise) with Why and Fix - per finding, in the same format as skill-audit. Do not use to fix agent files — use - /agent-author instead. Do not use to audit SKILL.md files — use /skill-audit instead. + Audits a Claude Code .md and Copilot .agent.md agent file pair across five dimensions: + structural validation, provider safety, description quality, body quality, and pair + consistency — plus provenance chain validation. Produces a compact findings report + (findings only, no PASS noise) with Why and Fix per finding. Do not use to fix agent + files — use /agent-author instead. Do not use to audit SKILL.md files — use + /skill-audit instead. allowed-tools: Bash Read metadata: category: factory @@ -22,8 +23,8 @@ metadata: ## Gotchas -- The unit of authoring is always a pair (CC `.md` + Copilot `.agent.md`). A missing counterpart is always a FAIL, not a warning. -- Plugin scope is detected by the presence of `plugin.json` in the directory tree — not by the file path pattern. Walk up, don't guess. +- The unit of authoring in this project is always a pair (CC `.md` + Copilot `.agent.md`). A missing counterpart is a FAIL under the kyberforge project convention — neither the CC nor the Copilot platform itself requires a counterpart file. Label such findings as project convention violations, not platform spec failures. +- Plugin scope is detected by the presence of `plugin.json` or `.claude-plugin/plugin.json` in the directory tree — not by the file path pattern. Walk up both paths at each level, don't guess. - `references/field-inventory.md` must exist for `validate.sh` to run. The script exits with an error if it is missing. - Do not output findings while auditing — gather internally, surface in Step 3 report. @@ -34,11 +35,11 @@ bash scripts/validate.sh bash scripts/validate-provenance.sh ``` -The script accepts either the CC file or the Copilot file. It detects provider from extension, derives the counterpart, and runs all structural checks. Note FAILs for the `### Structure` and `### Provider safety` report dimensions. Findings about missing fields, bad name format, empty body, or missing frontmatter → `### Structure`. Findings about CC-only fields in a Copilot file or plugin-silently-ignored fields in a CC file → `### Provider safety`. +The script accepts either the CC file or the Copilot file. It detects provider from extension, derives the counterpart, and runs all structural checks. Note FAILs and SUGGESTIONs for the `### Structure` and `### Provider safety` report dimensions. Findings about missing fields, bad name format, empty body, or missing frontmatter → `### Structure`. Findings about CC-only fields in a Copilot file, Copilot-only fields in a CC file, plugin-silently-ignored fields, body length, or subagent-unavailable tools → `### Provider safety`. `validate-provenance.sh` validates the provenance chain between the agent pair's `source_keys` and the plugin-scoped `agents/sources.md`. It exits 0 silently for non-plugin-scope agents and when no provenance data exists. Note FAILs from this script for the `### Provenance` dimension — surface them verbatim with Why and Fix. -If the scripts cannot run (Bash denied, python3 unavailable), perform checks manually: required fields present (`name`, `description`, non-empty body), `name` is kebab-case, `name` matches filename stem, no `FILL IN:` placeholders, no CC-only fields in Copilot file. +If the scripts cannot run (Bash denied, python3 unavailable), perform checks manually: required fields present (`name`, `description`, non-empty body), `name` is kebab-case, Copilot CLI `.agent.md` `name` must match filename stem (CC files are exempt — the CC platform does not require name to match filename), no `FILL IN:` placeholders, no CC-only fields in Copilot file, no Copilot-only fields in CC file (read `references/field-inventory.md` for the authoritative field lists). ## Step 2 — Qualitative checks @@ -49,13 +50,15 @@ Read both agent files. Work through each dimension internally. Collect findings - Specificity: is the trigger condition stated precisely? — SUGGESTION if vague - `Use proactively` in a Copilot description: CC-specific phrasing, has no effect in Copilot — SUGGESTION to remove +If a description finding is borderline, read `references/description-quality.md`. + **Body:** - Direct role instruction: system prompt opens with `You are a [role]. When invoked, [action].` — SUGGESTION if absent - One job per agent: system prompt describes a single bounded task — SUGGESTION if scope appears unbounded **Pair consistency (cross-file):** -- `name` field matches between CC and Copilot files — FAIL if mismatch -- Both system prompt bodies non-empty — FAIL if either is empty +- Both files exist — FAIL if counterpart is missing (kyberforge project convention; not a platform requirement from either CC or Copilot — label as such) +- The following checks are covered automatically by `validate.sh`; apply them manually only when the script cannot run: `name` field matches between CC and Copilot files — FAIL if mismatch; both system prompt bodies non-empty — FAIL if either is empty ## Step 3 — Report @@ -81,8 +84,11 @@ Close with: ## Result PASS +PASS · P info PASS (N suggestions) +PASS (N suggestions) · P info FAIL (N fails · M suggestions) +FAIL (N fails · M suggestions) · P info Run /agent-author to address findings. ``` diff --git a/plugins/kyberforge/skills/agent-audit/references/README.md b/plugins/kyberforge/skills/agent-audit/references/README.md index d32bf39..acb1683 100644 --- a/plugins/kyberforge/skills/agent-audit/references/README.md +++ b/plugins/kyberforge/skills/agent-audit/references/README.md @@ -1,3 +1,7 @@ +--- +source_keys: [] +--- + # references/ Additional documentation agents load on demand. @@ -6,5 +10,6 @@ Additional documentation agents load on demand. | File | Purpose | |------|---------| +| `description-quality.md` | Qualitative guide for borderline description findings — action-verb rules, specificity criteria, proactive-use caveat, length limits. | | `field-inventory.md` | Canonical list of valid CC and Copilot agent definition fields. Load when the script needs authoritative field lists for structural validation. | | `sources.md` | Research provenance records for skill content. Load only when tracing the origin of a specific rule or field constraint. | diff --git a/plugins/kyberforge/skills/agent-audit/references/description-quality.md b/plugins/kyberforge/skills/agent-audit/references/description-quality.md new file mode 100644 index 0000000..17f387d --- /dev/null +++ b/plugins/kyberforge/skills/agent-audit/references/description-quality.md @@ -0,0 +1,49 @@ +--- +source_keys: + - context7-websites-code-claude + - claude-code-plugins-docs + - claude-code-subagents-docs + - context7-github-en-copilot + - github-custom-agents-configuration +--- + +# Agent Description Quality Reference + +Load this file when a description finding is borderline and you need to make a precise call. + +## Action-verb opening + +The description must open with an imperative or present-tense verb that describes what the agent does ("Reviews...", "Audits...", "Generates...", "Analyzes..."). Avoid: +- Noun phrases: "An agent that..." — no verb +- "This agent..." or "Use this when..." — passive framing +- "Helps with..." — too vague to be a clear verb + +**Borderline call:** "Validates and reviews..." is acceptable — two verbs is fine if both are specific. "Assists in reviewing..." is not — "assists" is vague filler. + +## Specificity of trigger condition + +The description must state what specifically triggers the agent. Generic phrasing fails: +- Too vague: "when the user needs help with agents" +- Acceptable: "when the user says 'audit this agent', 'check if my agent follows best practices', or wants to know if an agent pair is ready to ship" + +Include indirect triggers: "even if they don't use the word 'audit'" or "even if the user doesn't phrase it as a review request". If the agent should activate on a recognisable user goal (not just literal keyword matches), name that goal. + +**Borderline call:** If the description covers direct triggers but omits common indirect phrasings that a user would plausibly use, mark as SUGGESTION (not FAIL) — the agent still activates, just less reliably. + +## `Use proactively` + +For CC files: including "Use proactively" signals the CC runtime to offer the agent unprompted when conditions are met. This is CC-specific — use it when the agent should activate without an explicit user request. + +For Copilot files: this phrase has no effect. Use `user-invocable: false` / `disable-model-invocation: true` for equivalent Copilot behavior. Flag `Use proactively` in a Copilot description as a SUGGESTION (not FAIL) — it causes no harm, just has no effect. + +## Length and hard limits + +- CC agent descriptions: no documented character limit, but keep under 500 characters to avoid truncation in UI contexts. +- Copilot agent descriptions: no separate documented limit, but the overall 30,000-character body limit applies to the full file. +- Skill descriptions (SKILL.md): hard 1024-character limit enforced by the platform. + +## Do not use when + +Include a "Do not use when..." clause only if a near-miss agent or skill exists that could steal activations. Omitting it is not a finding. Including it is correct when there is a real confusion risk (e.g., `/agent-audit` vs `/skill-audit`). + +**Borderline call:** If the "Do not use when" clause is present but the exclusion described is already obvious from context, mark as SUGGESTION to tighten or remove — not FAIL. diff --git a/plugins/kyberforge/skills/agent-audit/references/field-inventory.md b/plugins/kyberforge/skills/agent-audit/references/field-inventory.md index c0e215a..047995d 100644 --- a/plugins/kyberforge/skills/agent-audit/references/field-inventory.md +++ b/plugins/kyberforge/skills/agent-audit/references/field-inventory.md @@ -22,3 +22,7 @@ hooks mcpServers permissionMode ## copilot-fields name description tools target model disable-model-invocation user-invocable mcp-servers metadata + +## copilot-only-fields + +target disable-model-invocation user-invocable mcp-servers metadata diff --git a/plugins/kyberforge/skills/agent-audit/references/sources.md b/plugins/kyberforge/skills/agent-audit/references/sources.md index 95add20..3428f5d 100644 --- a/plugins/kyberforge/skills/agent-audit/references/sources.md +++ b/plugins/kyberforge/skills/agent-audit/references/sources.md @@ -14,7 +14,7 @@ source_keys: - **URL:** context7:/websites/code_claude - **Research doc:** plugins/kyberforge/docs/research/docs/claude-code-plugins/sources.md - **Description:** Official Claude Code documentation site indexed by Context7 — plugin manifest schema, subagent definition types, marketplace JSON format, agent markdown file format -- **Contributing files:** SKILL.md, references/field-inventory.md +- **Contributing files:** SKILL.md, references/field-inventory.md, references/description-quality.md - **Status:** `extracted` ## claude-code-plugins-docs @@ -22,7 +22,7 @@ source_keys: - **URL:** https://code.claude.com/docs/en/plugins - **Research doc:** plugins/kyberforge/docs/research/docs/claude-code-plugins/sources.md - **Description:** Official Claude Code plugin authoring guide — plugin structure, manifest fields, loading methods, skill namespacing, agent activation, marketplace submission -- **Contributing files:** SKILL.md, references/field-inventory.md +- **Contributing files:** SKILL.md, references/field-inventory.md, references/description-quality.md - **Status:** `extracted` ## claude-code-subagents-docs @@ -30,7 +30,7 @@ source_keys: - **URL:** https://code.claude.com/docs/en/sub-agents - **Research doc:** plugins/kyberforge/docs/research/docs/claude-code-plugins/sources.md - **Description:** Official Claude Code subagent reference — definition format, all frontmatter fields, scope priority, built-in agents, CLI flags, environment variables, known limitations -- **Contributing files:** SKILL.md, references/field-inventory.md +- **Contributing files:** SKILL.md, references/field-inventory.md, references/description-quality.md - **Status:** `extracted` ## context7-github-en-copilot @@ -38,7 +38,7 @@ source_keys: - **URL:** context7:/websites/github_en_copilot - **Research doc:** plugins/kyberforge/docs/research/docs/github-copilot-plugins/sources.md - **Description:** Official GitHub Copilot documentation indexed by Context7; covers CLI plugins, custom agents, SDK, and marketplace -- **Contributing files:** SKILL.md, references/field-inventory.md +- **Contributing files:** SKILL.md, references/field-inventory.md, references/description-quality.md - **Status:** `extracted` ## github-custom-agents-configuration @@ -46,7 +46,7 @@ source_keys: - **URL:** https://docs.github.com/en/copilot/reference/custom-agents-configuration - **Research doc:** plugins/kyberforge/docs/research/docs/github-copilot-plugins/sources.md - **Description:** Reference for cloud and IDE custom agent definition format — frontmatter fields, tool aliases, MCP server config, secrets interpolation, scoping hierarchy -- **Contributing files:** SKILL.md, references/field-inventory.md +- **Contributing files:** SKILL.md, references/field-inventory.md, references/description-quality.md - **Status:** `extracted` ## github-cli-plugin-reference diff --git a/plugins/kyberforge/skills/agent-audit/scripts/validate.sh b/plugins/kyberforge/skills/agent-audit/scripts/validate.sh index 706ab48..a2205df 100755 --- a/plugins/kyberforge/skills/agent-audit/scripts/validate.sh +++ b/plugins/kyberforge/skills/agent-audit/scripts/validate.sh @@ -11,7 +11,7 @@ Arguments: agent-file Path to either the Claude Code .md or Copilot .agent.md agent file. Exit codes: - 0 All checks passed + 0 All checks passed (may include SUGGESTIONs) 1 One or more checks failed 2 Script error (unrecognized file extension or missing field-inventory.md) EOF @@ -72,13 +72,23 @@ def parse_section_tokens(content, section_name): return set() cc_only_fields = parse_section_tokens(inv_content, 'claude-code-only-fields') +copilot_only_fields = parse_section_tokens(inv_content, 'copilot-only-fields') plugin_ignored_fields = parse_section_tokens(inv_content, 'plugin-silently-ignored-fields') +# Tools the runtime withholds from subagents regardless of the tools field +SUBAGENT_UNAVAILABLE_TOOLS = { + 'AskUserQuestion', 'EnterPlanMode', 'ExitPlanMode', 'ScheduleWakeup', 'WaitForMcpServers', +} + +# Copilot body length limit (chars) — content beyond this is silently truncated +COPILOT_BODY_LIMIT = 30000 + # --- Detect scope --- def detect_scope(start_dir): current = os.path.abspath(start_dir) while True: - if os.path.isfile(os.path.join(current, 'plugin.json')): + if (os.path.isfile(os.path.join(current, 'plugin.json')) or + os.path.isfile(os.path.join(current, '.claude-plugin', 'plugin.json'))): return 'plugin', current if os.path.isdir(os.path.join(current, '.git')): return 'project', current @@ -116,12 +126,16 @@ else: # user # --- Helpers --- failed = False +suggestions = [] def fail(msg): global failed failed = True print(f"FAIL {msg}") +def suggest(msg): + suggestions.append(msg) + PLACEHOLDER_RE = re.compile(r'(? COPILOT_BODY_LIMIT: + suggest(f"body exceeds {COPILOT_BODY_LIMIT:,} characters ({len(body):,} chars) — content beyond the limit is silently truncated by the Copilot runtime — {local_fname}") # CC-only fields in Copilot file if file_provider == 'copilot': @@ -189,6 +220,13 @@ def check_file(fpath, file_provider, is_plugin_scope): if key in cc_only_fields: fail(f"CC-only field '{key}' present in Copilot file — {local_fname}") + # Copilot-only fields in CC file + if file_provider == 'claude-code': + fm_keys = get_frontmatter_keys(fm) + for key in sorted(fm_keys): + if key in copilot_only_fields: + fail(f"Copilot-only field '{key}' present in CC file — {local_fname}") + # Silently-ignored fields in plugin-scope CC file if file_provider == 'claude-code' and is_plugin_scope: fm_keys = get_frontmatter_keys(fm) @@ -196,6 +234,12 @@ def check_file(fpath, file_provider, is_plugin_scope): if key in plugin_ignored_fields: fail(f"plugin-silently-ignored field '{key}' present in plugin-scope CC file — {local_fname}") + # Subagent-unavailable tools listed in tools field + tools = extract_tools_list(fm) + unavailable = tools & SUBAGENT_UNAVAILABLE_TOOLS + for tool in sorted(unavailable): + suggest(f"'{tool}' is listed in tools but is never available to subagents — the runtime withholds it regardless — {local_fname}") + # --- Check counterpart exists --- if not os.path.isfile(counterpart): fail(f"counterpart file not found: {counterpart}") @@ -206,5 +250,8 @@ is_plugin = (scope == 'plugin') check_file(agent_file, provider, is_plugin) check_file(counterpart, counterpart_provider, is_plugin) +for s in suggestions: + print(f"SUGGESTION {s}") + sys.exit(1 if failed else 0) PYTHON