From fc305ba7d9c5284ea8011e2afe81b63cee285a28 Mon Sep 17 00:00:00 2001 From: Defame1297 Date: Tue, 1 Sep 2026 12:38:22 +0000 Subject: [PATCH] fix(kyberforge): correct the routing-tier contract and make agent-audit rubrics conditional MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Five documents told authors that a prose-form dangling routing target blocks. The gate reports it as a SUGGESTION and exits 0. Verified on fixtures: `-> name` and `/name` are blocking ERRORs, the prose form is SUGGESTION-tier unless a second resolving target in the same sentence corroborates it. ADR-0020 and gates.md were right; contract.md, retrofit.md, description-quality.md, finding-criteria.md and agent-author's contract.md were wrong — and they are what an author and an auditor actually read. The whole 39-skill corpus was retrofitted against them. skill-audit was also self-contradictory: it imports validate.sh's SUGGESTIONs into the Structure dimension verbatim while its own rubric grades the same target a FAIL, so one target got reported twice at two tiers. The script owns the grade; the rubric now says so. The YAML-fold trap that broke gitea-labels-milestones (#100) was warned about only in retrofit.md, reachable only from the improve flow when a budget is exceeded. It is now in both contract.md files, which SKILL.md mandates on the create flow too. agent-audit loaded both rubrics unconditionally on every run — 3,323 words for a clean audit against skill-audit's 1,636. dac9cad fixed exactly this in skill-audit and edited agent-audit in the same commit without applying it. Same treatment: the criteria move to a new finding-criteria.md and load per dimension. Clean run now 2,083 words, a 37% cut. Routing: apm-workflow's description shed dependency installation while still owning the flow, and apm-install's boundary did not exclude it, so "install my apm dependencies" matched the CLI-binary skill with no route back. Fixed on both sides. forge regains two of the three phrasings the retrofit deleted. forge Step 1 called grill-with-docs unconditionally — a skill in plugins/bin, which kyberforge does not declare as a dependency. It resolves here only because the walk-up sweeps sibling plugins; a standalone install dead-ends. Step 1 now names the cross-plugin dependency and gives an inline fallback. Declaring it properly in apm.yml remains the better fix. Also: both audit SKILL.md files now grade exit 2 as "did not run, dimension unverified" rather than as findings; skill-audit's README row described content that moved, which its own finding-criteria.md grades a FAIL; and body-discipline.md's `git show :plugins/...` command is fenced, since an installed plugin cache has no repo and file-structure.md makes a bare repo path a FAIL. Refs: #100, #101, #125 ADR: 0020 --- .../.apm/skills/agent-audit/README.md | 5 +- .../.apm/skills/agent-audit/SKILL.md | 8 +- .../skills/agent-audit/references/README.md | 5 +- .../references/body-and-delegation.md | 24 +---- .../references/description-quality.md | 49 +--------- .../references/finding-criteria.md | 98 +++++++++++++++++++ .../skills/agent-audit/references/sources.md | 10 +- .../agent-author/references/contract.md | 21 +++- .../.apm/skills/apm-install/SKILL.md | 3 +- .../.apm/skills/apm-workflow/SKILL.md | 7 +- plugins/kyberforge/.apm/skills/forge/SKILL.md | 11 ++- .../.apm/skills/skill-audit/README.md | 2 +- .../.apm/skills/skill-audit/SKILL.md | 4 +- .../skill-audit/references/body-discipline.md | 13 ++- .../references/description-quality.md | 7 +- .../references/finding-criteria.md | 10 +- .../skill-author/references/contract.md | 24 ++++- .../skill-author/references/retrofit.md | 25 +++-- .../kyberforge/skills/agent-audit/README.md | 5 +- .../kyberforge/skills/agent-audit/SKILL.md | 8 +- .../skills/agent-audit/references/README.md | 5 +- .../references/body-and-delegation.md | 24 +---- .../references/description-quality.md | 49 +--------- .../references/finding-criteria.md | 98 +++++++++++++++++++ .../skills/agent-audit/references/sources.md | 10 +- .../agent-author/references/contract.md | 21 +++- .../kyberforge/skills/apm-install/SKILL.md | 3 +- .../kyberforge/skills/apm-workflow/SKILL.md | 7 +- plugins/kyberforge/skills/forge/SKILL.md | 11 ++- .../kyberforge/skills/skill-audit/README.md | 2 +- .../kyberforge/skills/skill-audit/SKILL.md | 4 +- .../skill-audit/references/body-discipline.md | 13 ++- .../references/description-quality.md | 7 +- .../references/finding-criteria.md | 10 +- .../skill-author/references/contract.md | 24 ++++- .../skill-author/references/retrofit.md | 25 +++-- 36 files changed, 424 insertions(+), 228 deletions(-) create mode 100644 plugins/kyberforge/.apm/skills/agent-audit/references/finding-criteria.md create mode 100644 plugins/kyberforge/skills/agent-audit/references/finding-criteria.md diff --git a/plugins/kyberforge/.apm/skills/agent-audit/README.md b/plugins/kyberforge/.apm/skills/agent-audit/README.md index d25374f..3face54 100644 --- a/plugins/kyberforge/.apm/skills/agent-audit/README.md +++ b/plugins/kyberforge/.apm/skills/agent-audit/README.md @@ -57,8 +57,9 @@ Pass the path to either agent file as the argument. | `assets/vale/styles/Kyberforge/VagueWording.yml` | Flags vague capability wording ("helps with", "utilize", "assists with", "used for") in descriptions | | `assets/vale/styles/KyberforgeCopilot/ProactivePhrase.yml` | Flags CC-specific "Use proactively" phrasing with no effect in Copilot descriptions | | `references/README.md` | Directory documentation for references/ | -| `references/description-quality.md` | Rubric for the description dimension — three-part shape, the 250/400-character budget, the hand-invoked contract, and the internal-mechanics FAIL | -| `references/body-and-delegation.md` | Rubric for the body, delegation and comment-discipline dimensions — the delegation FAIL and why agents take no body word gate | +| `references/finding-criteria.md` | Every dimension's FAIL and SUGGESTION criteria — the one Step 3 file read on every run; it decides which rubrics below are worth loading | +| `references/description-quality.md` | Rubric for the description dimension — why the description is the expensive part, the hand-invoked contract, the three-part shape, indirect triggers, and near-miss exclusions | +| `references/body-and-delegation.md` | Rubric for the body, delegation and comment-discipline dimensions — the core test, the delegation FAIL, why agents take no body word gate, and what an agent body is for | | `references/scope-plugin-apm.md` | Scope contract for a single vendor-neutral APM agent file — allowlist, dimension routing, and the dimensions that do not apply | | `references/scope-project-user.md` | Scope contract for a CC / Copilot pair — counterpart derivation, provider field rules, pair consistency | | `references/validation-scripts.md` | Loaded only when a Step 1 script fails or cannot run — scope-detection walk-up, manual fallback checks, known script failures | diff --git a/plugins/kyberforge/.apm/skills/agent-audit/SKILL.md b/plugins/kyberforge/.apm/skills/agent-audit/SKILL.md index 5086802..19abac3 100644 --- a/plugins/kyberforge/.apm/skills/agent-audit/SKILL.md +++ b/plugins/kyberforge/.apm/skills/agent-audit/SKILL.md @@ -37,7 +37,7 @@ bash scripts/vale-wrap.sh [] If a validation script fails or cannot run — Bash denied, `python3` or `vale` absent, `references/field-inventory.md` missing — read `references/validation-scripts.md`; what these scripts measure is not reproducible by reading. -`validate-provenance.sh` prints nothing on success and runs at plugin/APM scope only, exiting 0 silently elsewhere. Its FAIL findings become a separate `### Provenance` dimension, and it emits Why and Fix itself — surface those verbatim. +`validate-provenance.sh` prints nothing on success, so read its exit code before you read its silence. **0** is a genuine pass, including the silent exit 0 at project or user scope, where plugin-scope provenance does not apply. **1** means real findings: its FAILs and INFOs become a separate `### Provenance` dimension, and it emits Why and Fix itself — surface those verbatim. **2** means the check never ran — a bad argument or a missing dependency, reason on stderr, no findings and often no stdout at all. On a 2, report `### Provenance` as unverified and quote the stderr reason; never grade it as a clean pass. `validate.sh` uses the same 2 tier. `vale-wrap.sh` applies the bundled `Kyberforge` style as a prefilter. Pass no `--config`; the wrapper locates its own. At project/user scope pass both files of the pair, not only the one you were handed. Every rule is graded `error`, so every alert is a FAIL. Report each one citing its rule ID, filed under the dimension it belongs to, and do not re-derive it by judgment: @@ -57,14 +57,14 @@ Read the agent file end to end, and at project/user scope its counterpart too. A ## Step 3 — Qualitative audit -Load a dimension's rubric before judging that dimension. +Read `references/finding-criteria.md` first — every dimension's FAIL and SUGGESTION criteria. Load the rubric below only for a dimension the criteria put in play: one carrying a candidate finding, or one where the criterion alone does not settle the call. -| Dimension | Read | +| Dimension | Rubric | |---|---| | description | `references/description-quality.md` | | body, delegation, comment-discipline | `references/body-and-delegation.md` | -Cite file and line number for every finding. +Each rubric is the reasoning behind its criteria, not a second copy of them. Cite file and line number for every finding. ## Step 4 — Report diff --git a/plugins/kyberforge/.apm/skills/agent-audit/references/README.md b/plugins/kyberforge/.apm/skills/agent-audit/references/README.md index 58bda01..6ae112e 100644 --- a/plugins/kyberforge/.apm/skills/agent-audit/references/README.md +++ b/plugins/kyberforge/.apm/skills/agent-audit/references/README.md @@ -10,8 +10,9 @@ Additional documentation agents load on demand. | File | Purpose | |------|---------| -| `description-quality.md` | Rubric for the description dimension — three-part shape, the 250/400-character budget, the hand-invoked contract, and the internal-mechanics FAIL. | -| `body-and-delegation.md` | Rubric for the body, delegation and comment-discipline dimensions — the delegation FAIL, why agents take no body word gate, and what an agent body is for. | +| `finding-criteria.md` | Every dimension's FAIL and SUGGESTION criteria — the one Step 3 file read on every run; it decides which rubrics below are worth loading. | +| `description-quality.md` | Rubric for the description dimension — why the description is the expensive part, the hand-invoked contract, the three-part shape, indirect triggers, and near-miss exclusions. | +| `body-and-delegation.md` | Rubric for the body, delegation and comment-discipline dimensions — the core test, the delegation FAIL, why agents take no body word gate, and what an agent body is for. | | `scope-plugin-apm.md` | Contract for a single vendor-neutral `.apm/agents/.agent.md` file — allowlist, dimension routing, and the dimensions that do not apply. | | `scope-project-user.md` | Contract for a Claude Code / Copilot file pair — counterpart derivation, provider field rules, and pair consistency. | | `validation-scripts.md` | Loaded only when a Step 1 script fails or cannot run — scope-detection walk-up, manual fallback checks, and known script failures. | diff --git a/plugins/kyberforge/.apm/skills/agent-audit/references/body-and-delegation.md b/plugins/kyberforge/.apm/skills/agent-audit/references/body-and-delegation.md index ef9e598..325bed6 100644 --- a/plugins/kyberforge/.apm/skills/agent-audit/references/body-and-delegation.md +++ b/plugins/kyberforge/.apm/skills/agent-audit/references/body-and-delegation.md @@ -98,24 +98,8 @@ to a shipped file. At plugin/APM scope the stakes are higher than tidiness: `apm frontmatter verbatim to every target, `` is not valid YAML, and `validate.sh` FAILs a frontmatter block that still contains one. -## Auditing guidance +## Where the criteria live -Flag as FAIL if: - -- The body restates a procedure owned by a skill the agent can invoke — Fix: invoke `` - instead -- A sentence answers "no" to the core test — it is padding -- A decision point presents a menu of options with no default -- An instruction repeats content already in the description -- Frontmatter comments are template scaffolding rather than instruction, or are HTML comments at - plugin/APM scope -- A prescriptive sequence is used where flexibility is fine, or the reverse - -Flag as SUGGESTION if: - -- The body does not open with a direct role instruction -- The body specifies no error handling — nothing tells the agent what to do with malformed, - missing or contradictory input -- The job the agent describes is unbounded, or bounded only implicitly -- A rationale is missing from a rule the agent is expected to enforce — present but unexplained -- Comments are useful but verbose enough to bury the field they annotate +Every FAIL and SUGGESTION criterion for these dimensions is in `references/finding-criteria.md`, +which Step 3 reads on every run. This file is the reasoning behind them, loaded only when that file +puts the body, delegation or comment-discipline dimension in play. diff --git a/plugins/kyberforge/.apm/skills/agent-audit/references/description-quality.md b/plugins/kyberforge/.apm/skills/agent-audit/references/description-quality.md index d3863af..eac9c27 100644 --- a/plugins/kyberforge/.apm/skills/agent-audit/references/description-quality.md +++ b/plugins/kyberforge/.apm/skills/agent-audit/references/description-quality.md @@ -82,49 +82,8 @@ description: > dispatched and safety-gated. Not conversational git help -> git-workflow. ``` -## Auditing guidance +## Where the criteria live -Flag as FAIL if: - -- **Over 400 characters.** Measured on the folded YAML value, not the raw source lines. - `validate.sh` reports the number; do not re-derive it, but do point the Fix at what to cut. Agent - descriptions have no platform-documented ceiling of their own — unlike a skill's 1,024-character - spec limit, the 400-character house ceiling is the only hard limit there is, so do not go looking - for a backstop behind it. -- **Internal mechanics appear in the description.** Any of: - - capability enumeration or a feature list; - - output-format detail ("Produces a compact findings report with Why and Fix per finding"); - - composition or architecture notes ("composes X rather than duplicating Y", "a cross-cutting - shared agent", "the human-facing entry point", "replaces the old flat invocation"); - - implementation detail ("self-validates via a bundled deterministic script"). - - None of it can change a routing decision and all of it is preloaded. - `Kyberforge.CompositionNote` catches the common phrasings deterministically; the rest is - judgment. This is the rule that deflates a description, so apply it before reaching for length. -- **The same trigger stated twice in two registers** — a verb list, then the same verbs re-quoted - as user phrasings, usually in the same order. One register, whichever routes better. -- **Descriptive rather than imperative phrasing** (`This agent ...`, `This is the ...`). - `Kyberforge.DescriptionOpener` catches any opener matching `^This`. There is no action-verb rule - here and never was a defensible one: an `Orchestrates ...` or `Audits ...` opener is a catalogue - entry, not a trigger. -- **Vague capabilities** ("helps with agents" where "audits an agent definition pair" was - available). `Kyberforge.VagueWording` catches the known filler; imprecision outside that list is - judgment. -- **A boundary clause naming a target that does not resolve** to a real skill directory or agent - file in the authoring source. `validate.sh` resolves this for agent files at both scopes and - reports each unresolved target itself — take its verdict rather than re-resolving the name by - hand, because a hand-walk over a different universe can contradict it. What is left to you is - semantic and the script cannot reach it: whether a target that *does* resolve is the right - sibling to exclude, and whether a clause naming no target at all ("examine the files manually") - should have named one. -- **`Use proactively` in a Copilot or vendor-neutral description.** - `KyberforgeCopilot.ProactivePhrase` catches it. The phrase steers the Claude Code runtime and - does nothing anywhere else, so in a `.agent.md` it is preloaded text that buys no behaviour. -- **Trigger-list, boundary or indirect-trigger content on a hand-invoked agent** — see Step 0. - -Flag as SUGGESTION if: - -- **Over 250 characters** but at or under 400. This tier is what moves the corpus average; the FAIL - tier only stops outliers. Report it rather than treating a 399-character description as clean. -- A near-miss exclusion is present but targets a weak near-miss. -- An indirect trigger is present and warranted but could name the omitted phrasing more precisely. +Every FAIL and SUGGESTION criterion for this dimension is in `references/finding-criteria.md`, +which Step 3 reads on every run. This file is the reasoning behind them, loaded only when that file +puts the description dimension in play. diff --git a/plugins/kyberforge/.apm/skills/agent-audit/references/finding-criteria.md b/plugins/kyberforge/.apm/skills/agent-audit/references/finding-criteria.md new file mode 100644 index 0000000..91e431a --- /dev/null +++ b/plugins/kyberforge/.apm/skills/agent-audit/references/finding-criteria.md @@ -0,0 +1,98 @@ +--- +source_keys: + - context7-websites-code-claude + - claude-code-plugins-docs + - claude-code-subagents-docs + - context7-github-en-copilot + - github-custom-agents-configuration +--- + +# Finding Criteria + +Every FAIL and SUGGESTION criterion, for every qualitative dimension, and nothing else. The +reasoning each criterion stands on, its worked examples and its house rules stay in that +dimension's rubric, which Step 3 loads only for a dimension this file puts in play. + +Two rules on using it: + +- A criterion that plainly applies is a finding. Write it up citing file and line. +- A criterion that might apply, or whose call the wording here does not settle, is a reason to load + that dimension's rubric — never a reason to drop the candidate. This file decides which rubrics + to read; it does not settle a close call on its own. + +## description — `references/description-quality.md` + +Flag as FAIL if: + +- **Over 400 characters.** Measured on the folded YAML value, not the raw source lines. + `validate.sh` reports the number; do not re-derive it, but do point the Fix at what to cut. Agent + descriptions have no platform-documented ceiling of their own, so 400 is the only hard limit + there is — do not go looking for a backstop behind it. +- **Internal mechanics appear in the description.** Any of: + - capability enumeration or a feature list; + - output-format detail ("Produces a compact findings report with Why and Fix per finding"); + - composition or architecture notes ("composes X rather than duplicating Y", "a cross-cutting + shared agent", "the human-facing entry point", "replaces the old flat invocation"); + - implementation detail ("self-validates via a bundled deterministic script"). + + None of it can change a routing decision and all of it is preloaded. + `Kyberforge.CompositionNote` catches the common phrasings deterministically; the rest is + judgment. This is the rule that deflates a description, so apply it before reaching for length. +- **The same trigger stated twice in two registers** — a verb list, then the same verbs re-quoted + as user phrasings, usually in the same order. One register, whichever routes better. +- **Descriptive rather than imperative phrasing** (`This agent ...`, `This is the ...`). + `Kyberforge.DescriptionOpener` catches any opener matching `^This`. +- **Vague capabilities** ("helps with agents" where "audits an agent definition pair" was + available). `Kyberforge.VagueWording` catches the known filler; imprecision outside that list is + judgment. +- **`Use proactively` in a Copilot or vendor-neutral description.** + `KyberforgeCopilot.ProactivePhrase` catches it. The phrase steers the Claude Code runtime and + does nothing anywhere else, so in a `.agent.md` it is preloaded text that buys no behaviour. +- **Trigger-list, boundary or indirect-trigger content on a hand-invoked agent** — see Step 0 of + `references/description-quality.md`. + +Flag as SUGGESTION if: + +- **Over 250 characters** but at or under 400. This tier is what moves the corpus average; the FAIL + tier only stops outliers. Report it rather than treating a 399-character description as clean. +- A near-miss exclusion is present but targets a weak near-miss. +- An indirect trigger is present and warranted but could name the omitted phrasing more precisely. + +**An unresolved boundary target is not graded here.** `validate.sh` resolves boundary targets for +agent files at both scopes and tiers the verdict itself — route notation (`/name`, an arrow form) +is an ERROR, the bare prose form a SUGGESTION unless a second target in the same sentence resolves. +Step 1 has already filed it under `### Structure` at that tier. Take the script's verdict rather +than re-resolving the name by hand, and do not re-grade it under description: a hand-walk over a +different universe can contradict the script, and re-grading puts one target in the report twice. +What is left to judgment is semantic and the script cannot reach it: whether a target that *does* +resolve is the right sibling to exclude, and whether a clause naming no target at all ("examine the +files manually") should have named one. + +## body, delegation and comment-discipline — `references/body-and-delegation.md` + +Flag as FAIL if: + +- The body restates a procedure owned by a skill the agent can invoke — Fix: invoke `` + instead +- A sentence answers "no" to the core test — it is padding +- A decision point presents a menu of options with no default +- An instruction repeats content already in the description +- Frontmatter comments are template scaffolding rather than instruction, or are HTML comments at + plugin/APM scope +- A prescriptive sequence is used where flexibility is fine, or the reverse + +Flag as SUGGESTION if: + +- The body does not open with a direct role instruction +- The body specifies no error handling — nothing tells the agent what to do with malformed, + missing or contradictory input +- The job the agent describes is unbounded, or bounded only implicitly +- A rationale is missing from a rule the agent is expected to enforce — present but unexplained +- Comments are useful but verbose enough to bury the field they annotate + +**Never report an agent body as too long on a word count.** ADR-0020 gates a skill body at +600/900 words and deliberately gates an agent body at nothing, because an agent body *becomes* the +system prompt of a fresh context rather than competing with a live conversation. There is no number +to cite. The one length signal that applies is the Copilot runtime's 30,000-character body limit, +which `validate.sh` already reports as a SUGGESTION. Length is judged through the delegation FAIL +above instead. diff --git a/plugins/kyberforge/.apm/skills/agent-audit/references/sources.md b/plugins/kyberforge/.apm/skills/agent-audit/references/sources.md index 748c4f8..7fcca6f 100644 --- a/plugins/kyberforge/.apm/skills/agent-audit/references/sources.md +++ b/plugins/kyberforge/.apm/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, references/description-quality.md, references/body-and-delegation.md, references/scope-project-user.md +- **Contributing files:** SKILL.md, references/finding-criteria.md, references/field-inventory.md, references/description-quality.md, references/body-and-delegation.md, references/scope-project-user.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, references/body-and-delegation.md, references/scope-plugin-apm.md, references/validation-scripts.md +- **Contributing files:** SKILL.md, references/finding-criteria.md, references/field-inventory.md, references/body-and-delegation.md, references/scope-plugin-apm.md, references/validation-scripts.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, references/description-quality.md, references/body-and-delegation.md, references/scope-plugin-apm.md, references/scope-project-user.md, references/validation-scripts.md +- **Contributing files:** SKILL.md, references/finding-criteria.md, references/field-inventory.md, references/description-quality.md, references/body-and-delegation.md, references/scope-plugin-apm.md, references/scope-project-user.md, references/validation-scripts.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, references/description-quality.md, references/body-and-delegation.md, references/scope-project-user.md +- **Contributing files:** SKILL.md, references/finding-criteria.md, references/field-inventory.md, references/description-quality.md, references/body-and-delegation.md, references/scope-project-user.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, references/description-quality.md, references/body-and-delegation.md, references/scope-plugin-apm.md, references/scope-project-user.md, references/validation-scripts.md +- **Contributing files:** SKILL.md, references/finding-criteria.md, references/field-inventory.md, references/description-quality.md, references/body-and-delegation.md, references/scope-plugin-apm.md, references/scope-project-user.md, references/validation-scripts.md - **Status:** `extracted` ## github-cli-plugin-reference diff --git a/plugins/kyberforge/.apm/skills/agent-author/references/contract.md b/plugins/kyberforge/.apm/skills/agent-author/references/contract.md index 50f6397..cea9336 100644 --- a/plugins/kyberforge/.apm/skills/agent-author/references/contract.md +++ b/plugins/kyberforge/.apm/skills/agent-author/references/contract.md @@ -61,14 +61,29 @@ word for word. Indirect triggers ("even if the user doesn't say X") take a similar conditional at every scope: add one only where the user's natural phrasing genuinely omits the domain word. -**Boundary targets must resolve.** Both forms are checked — the arrow and the prose form ("do not -use for X, use `y` instead") — so a typo dangles either way. Targets resolve against a universe +**Boundary targets must resolve, and the notation decides how hard the gate bites.** Route +notation — `/name`, or any arrow form (`-> name`, `` -> `name` ``) — is checked +unconditionally: an unresolved target there is a blocking ERROR. The prose form ("do not use +for X, use `y` instead") is only a SUGGESTION by default, because a bare hyphenated word in a +boundary clause is as likely to be a tool, a file format or an English compound as a route. It +is promoted to a blocking ERROR only when a second target in the same sentence *does* resolve, +which corroborates that the name was meant as a route. So a typo does **not** dangle equally +either way — write the arrow when you want the target checked. Targets resolve against a universe built by walking up **from the agent file itself**: the nearest ancestor holding `plugins/*/.apm/{skills,agents}` (or, failing that, the nearest ancestor holding `.git`) contributes every skill and agent under `/plugins/*/`, plus the agent's own apm package and the packages that package declares in `apm.yml` under `dependencies.apm`. A sibling plugin in the same monorepo therefore resolves; a skill in an unrelated repo does not. A target outside that universe sends the -router nowhere. Verify it before writing it — do not invent a plausible sibling. +router nowhere — a blocking failure in arrow or `/name` form, and in prose form only a SUGGESTION +nobody is forced to act on, which is the worse outcome because it ships. Verify it before writing +it — do not invent a plausible sibling. + +**Never let a hyphenated routing target wrap across lines in a folded `>` scalar.** YAML folding +replaces the newline with a space, so `gitea-labels-` at the end of one line and `milestones` at +the start of the next fold into `gitea-labels- milestones`. The gate then reads the target as +`gitea-labels`, finds no such skill, and reports it dangling — nothing in the source lines looks +wrong. Reflow so the whole name sits on one line. The same applies to any backticked skill or +agent name anywhere in a description. That universe is the apm marketplace and stops there. A **host built-in is not a routing target**: `/compact`, `/clear` and `/init` are Claude Code slash commands with no counterpart in Copilot CLI diff --git a/plugins/kyberforge/.apm/skills/apm-install/SKILL.md b/plugins/kyberforge/.apm/skills/apm-install/SKILL.md index 9b249ea..054d161 100644 --- a/plugins/kyberforge/.apm/skills/apm-install/SKILL.md +++ b/plugins/kyberforge/.apm/skills/apm-install/SKILL.md @@ -3,7 +3,8 @@ name: apm-install description: > Use when installing, pinning, or upgrading the apm (Agent Package Manager) CLI itself, or installing and managing an agent runtime apm drives. Not - authoring, publishing, or auditing apm packages -> `apm-workflow`. + authoring, publishing, auditing, or dependency installation for an apm + package -> `apm-workflow`. metadata: category: apm source_keys: diff --git a/plugins/kyberforge/.apm/skills/apm-workflow/SKILL.md b/plugins/kyberforge/.apm/skills/apm-workflow/SKILL.md index 2cc3d55..cd258b4 100644 --- a/plugins/kyberforge/.apm/skills/apm-workflow/SKILL.md +++ b/plugins/kyberforge/.apm/skills/apm-workflow/SKILL.md @@ -1,10 +1,9 @@ --- name: apm-workflow description: > - Use when managing an apm package, its apm.yml manifest, or an apm - marketplace — authoring through publishing — even when the user does not say - "apm", e.g. "set up the package manifest". Not the apm binary or an agent - runtime -> `apm-install`. + Use when authoring, installing, or publishing an apm package, its apm.yml and + the dependencies it declares, or an apm marketplace — even when the user does + not say "apm". Not the apm binary or an agent runtime -> `apm-install`. metadata: category: apm source_keys: diff --git a/plugins/kyberforge/.apm/skills/forge/SKILL.md b/plugins/kyberforge/.apm/skills/forge/SKILL.md index e3dabd2..860e9db 100644 --- a/plugins/kyberforge/.apm/skills/forge/SKILL.md +++ b/plugins/kyberforge/.apm/skills/forge/SKILL.md @@ -2,10 +2,11 @@ name: forge description: > Use when the user wants to build or improve something but has not yet named - the artifact type — skill, agent, plugin, or marketplace entry; "a skill for - the gitea plugin, or an agent?". Routes to the matching author skill. Do not - use when the type is already named — invoke `skill-author`, `agent-author` - or `apm-workflow` directly. + the artifact type — skill, agent, plugin, or marketplace entry; "not sure if + this should be a skill or a plugin", "I have an idea but don't know where it + belongs". Routes to the matching author skill. Do not use when the type is + already named — invoke `skill-author`, `agent-author` or `apm-workflow` + directly. metadata: category: factory source_keys: @@ -23,6 +24,8 @@ metadata: Call `grill-with-docs` unless a grill session has already run and is available in the context. +`grill-with-docs` ships in a sibling plugin that kyberforge does not declare as an apm dependency, so it resolves in the authoring monorepo but can be absent where kyberforge is installed alone. If it does not resolve, grill inline yourself rather than skipping the step: what problem the artifact solves, who invokes it and how, what it must refuse, and which existing skill or plugin already owns part of the job. Say which path you took. + Grilling regularly overturns the artifact type assumed at the start, or splits one idea into several artifacts, so it runs before classification rather than confirming it. Run it inline in the current conversation — grilling is interactive and a subagent cannot hold the back-and-forth. ## Step 2 — Classify and dispatch diff --git a/plugins/kyberforge/.apm/skills/skill-audit/README.md b/plugins/kyberforge/.apm/skills/skill-audit/README.md index dfc5400..277c836 100644 --- a/plugins/kyberforge/.apm/skills/skill-audit/README.md +++ b/plugins/kyberforge/.apm/skills/skill-audit/README.md @@ -36,7 +36,7 @@ Provide the path to the skill directory to audit when invoking. | `assets/vale/styles/Kyberforge/SentenceOpenerThereIs.yml` | Vale rule — flags body sentences starting with "There is"/"There are" | | `assets/vale/styles/Kyberforge/VagueWording.yml` | Vale rule — flags known filler wording (e.g. "helps with", "utilize") | | `references/finding-criteria.md` | Every dimension's FAIL and SUGGESTION criteria — the one Step 3 file loaded on every run; it decides which rubrics below are worth loading | -| `references/description-quality.md` | Rubric for the description dimension — three-part shape, the 250/400-character budget, the hand-invoked (`disable-model-invocation`) contract, and the internal-mechanics FAIL | +| `references/description-quality.md` | Rubric for the description dimension — why the description is the expensive part, the hand-invoked (`disable-model-invocation`) contract, the three-part shape, when an indirect trigger is warranted, near-miss exclusions, and a before/after pair | | `references/body-discipline.md` | Rubric for the body-discipline dimension — the core test, the 600/900 body-only budget against the 2,770-word whole-file backstop, the mandatory-dispatch rule, and the Gotchas constraints | | `references/patterns.md` | Rubric for the patterns dimension — which instruction construct fits which job, and how each is correctly formed | | `references/file-structure.md` | Rubric for the file-structure and internal-consistency dimensions — permitted directories, cross-plugin path rules and their two structural exemptions, README drift | diff --git a/plugins/kyberforge/.apm/skills/skill-audit/SKILL.md b/plugins/kyberforge/.apm/skills/skill-audit/SKILL.md index 0c86feb..1a66612 100644 --- a/plugins/kyberforge/.apm/skills/skill-audit/SKILL.md +++ b/plugins/kyberforge/.apm/skills/skill-audit/SKILL.md @@ -33,11 +33,11 @@ bash scripts/validate-provenance.sh bash scripts/vale-wrap.sh /SKILL.md ``` -`validate.sh` findings become the `### Structure` dimension — its FAILs and its SUGGESTIONs both. +`validate.sh` findings become the `### Structure` dimension — its FAILs and its SUGGESTIONs both, at the tier the script assigned. Report each once; never re-grade one under another dimension. Unresolved boundary targets are where this bites, because their tier turns on notation. If any of the three cannot run, or exits non-zero for a reason other than findings, read `references/validation-scripts.md` — it carries the manual fallback and the misleading exit codes. Ordinary content FAILs are the expected outcome here and need no fallback. -`validate-provenance.sh` prints nothing on success. Its FAIL and INFO findings become a separate `### Provenance` dimension, and it emits Why and Fix itself — surface those verbatim. +`validate-provenance.sh` prints nothing on success, so read its exit code before you read its silence. **0** is a genuine pass. **1** means real findings: its FAILs and INFOs become a separate `### Provenance` dimension, and it emits Why and Fix itself — surface those verbatim. **2** means the check never ran — a usage or environment error, reason on stderr, no findings and often no stdout at all. On a 2, report `### Provenance` as unverified and quote the stderr reason. Never grade an exit 2 as a clean pass: empty stdout there means nothing was checked, not that nothing was wrong. `vale-wrap.sh` applies the bundled `Kyberforge` style as a prefilter. Pass no `--config`; the wrapper locates its own. Every rule is graded `error`, so every alert is a FAIL. Report each one citing its rule ID, filed under the dimension it belongs to, and do not re-derive it by judgment: diff --git a/plugins/kyberforge/.apm/skills/skill-audit/references/body-discipline.md b/plugins/kyberforge/.apm/skills/skill-audit/references/body-discipline.md index 1157d83..31f28c6 100644 --- a/plugins/kyberforge/.apm/skills/skill-audit/references/body-discipline.md +++ b/plugins/kyberforge/.apm/skills/skill-audit/references/body-discipline.md @@ -135,9 +135,16 @@ Constraints: Worked negative example — **`git-commits` v0.1.2 at commit `5e23250`, a fixed pre-retrofit snapshot, not the current file.** The live skill is v0.1.3 and matches none of the citations below; they are quoted as they stood before the ADR-0020 retrofit, and are not to be refreshed against -`HEAD`. Read the snapshot with -`git show 5e23250:plugins/git/.apm/skills/git-commits/SKILL.md`. That body carried -twelve Gotchas, four of which restated content already below them or already in the description: +`HEAD`. The snapshot is reachable only from a checkout of the authoring repo — an installed plugin +cache holds no git history and no such path — so read the citations below as quoted rather than +going to look for the file. From a checkout: + +```text +git show 5e23250:/.apm/skills/git-commits/SKILL.md +``` + +That body carried twelve Gotchas, four of which restated content already below them or already in +the description: | Gotcha | Restates | |---|---| diff --git a/plugins/kyberforge/.apm/skills/skill-audit/references/description-quality.md b/plugins/kyberforge/.apm/skills/skill-audit/references/description-quality.md index 579426c..ef027f8 100644 --- a/plugins/kyberforge/.apm/skills/skill-audit/references/description-quality.md +++ b/plugins/kyberforge/.apm/skills/skill-audit/references/description-quality.md @@ -40,8 +40,11 @@ A model-invoked description carries exactly three things: the agent is deciding whether to act, not reading a catalogue entry. 2. **At most one capability clause.** What it does, in one clause. Never an enumeration. 3. **Boundary clause.** Compressed form: `Not -> .` The target must resolve to - a real skill directory or agent file in the authoring source; `validate.sh` checks that - deterministically and a dangling target already surfaces as a Structure FAIL. + a real skill directory or agent file in the authoring source. `validate.sh` checks that + deterministically and grades it by notation: an unresolved `/name` or arrow target is an ERROR + and reaches the report as a Structure FAIL, while an unresolved prose-form target ("use `y` + instead") is only a SUGGESTION unless a second target in the same sentence resolves. Take the + script's tier as given and report it once, under Structure. Everything else belongs in the body or in `README.md`. diff --git a/plugins/kyberforge/.apm/skills/skill-audit/references/finding-criteria.md b/plugins/kyberforge/.apm/skills/skill-audit/references/finding-criteria.md index 73d41c0..05eb85d 100644 --- a/plugins/kyberforge/.apm/skills/skill-audit/references/finding-criteria.md +++ b/plugins/kyberforge/.apm/skills/skill-audit/references/finding-criteria.md @@ -42,8 +42,6 @@ Flag as FAIL if: - **Vague capabilities** ("helps with APIs" where "parses and validates OpenAPI specs" was available). `Kyberforge.VagueWording` catches the known filler; imprecision outside that list is judgment. -- **A boundary clause naming a target that does not resolve** to a real skill directory or agent - file in the authoring source. `validate.sh` reports the unresolved name. - **Trigger-list, boundary or indirect-trigger content on a hand-invoked skill** — see Step 0 of `references/description-quality.md`. - **Over 1024 characters** — the agentskills.io specification ceiling, unchanged and independent @@ -56,6 +54,14 @@ Flag as SUGGESTION if: - A near-miss exclusion is present but targets a weak near-miss. - An indirect trigger is present and warranted but could name the omitted phrasing more precisely. +**An unresolved boundary target is not graded here.** `validate.sh` owns that call and tiers it by +notation — `/name` or an arrow form is an ERROR, the bare prose form a SUGGESTION unless a second +target in the same sentence resolves — and Step 1 has already filed it under `### Structure` at that +tier. Re-grading it as a description FAIL puts one target in the report twice at two tiers. What is +left to judgment here is semantic and the script cannot reach it: whether a target that *does* +resolve is the right sibling to exclude, and whether a clause naming no target at all ("examine the +files manually") should have named one. + ## body-discipline — `references/body-discipline.md` Flag as FAIL if: diff --git a/plugins/kyberforge/.apm/skills/skill-author/references/contract.md b/plugins/kyberforge/.apm/skills/skill-author/references/contract.md index faf0479..e6795bf 100644 --- a/plugins/kyberforge/.apm/skills/skill-author/references/contract.md +++ b/plugins/kyberforge/.apm/skills/skill-author/references/contract.md @@ -47,15 +47,22 @@ explicitly" only where the user's natural phrasing genuinely omits the domain wo for `git-commits`, where the user says "commit". Adding one everywhere is what inflated this corpus, and it was deleted as a blanket rule. -**Boundary targets must resolve.** Both forms are checked — the arrow and the prose form ("do not -use for X, use `y` instead") — so a typo dangles either way. Targets resolve against a universe -built by walking up **from the SKILL.md itself**: the nearest ancestor holding +**Boundary targets must resolve, and the notation decides how hard the gate bites.** Route +notation — `/name`, or any arrow form (`-> name`, `` -> `name` ``) — is checked +unconditionally: an unresolved target there is a blocking ERROR. The prose form ("do not use +for X, use `y` instead") is only a SUGGESTION by default, because a bare hyphenated word in a +boundary clause is as likely to be a tool, a file format or an English compound as a route. It +is promoted to a blocking ERROR only when a second target in the same sentence *does* resolve, +which corroborates that the name was meant as a route. So a typo does **not** dangle equally +either way — write the arrow when you want the target checked. Targets resolve against a universe built by walking up **from the SKILL.md +itself**: the nearest ancestor holding `plugins/*/.apm/{skills,agents}` (or, failing that, the nearest ancestor holding `.git`) contributes every skill and agent under `/plugins/*/`, plus the skill's own apm package and the packages that package declares in `apm.yml` under `dependencies.apm`. A sibling plugin in the same monorepo therefore resolves; a skill in an unrelated repo does not. A boundary clause naming a target -outside that universe sends the router nowhere and fails the audit. Check the target exists before -writing it — do not invent a plausible sibling name. +outside that universe sends the router nowhere — a blocking failure in arrow or `/name` form, and +in prose form a SUGGESTION nobody is forced to act on, which is the worse outcome because it ships. +Check the target exists before writing it — do not invent a plausible sibling name. That universe is the apm marketplace and stops there. A **host built-in is not a routing target**: `/compact`, `/clear` and `/init` are Claude Code slash commands with no counterpart in Copilot CLI @@ -68,6 +75,13 @@ checked by nothing and the gate emits a SUGGESTION naming both. Split instead of `Not -> first-skill. Not -> second-skill.`, never `Not -> first-skill or second-skill`. +**Never let a hyphenated routing target wrap across lines in a folded `>` scalar.** YAML folding +replaces the newline with a space, so `gitea-labels-` at the end of one line and `milestones` at +the start of the next fold into `gitea-labels- milestones`. The gate then reads the target as +`gitea-labels`, finds no such skill, and reports it dangling — this is what broke +`gitea-labels-milestones`, and nothing in the source lines looks wrong. Reflow so the whole name +sits on one line. The same applies to any backticked skill or agent name anywhere in a description. + **Length.** 250 characters SUGGESTION, 400 characters FAIL, counting the frontmatter value only with YAML folding resolved. The agentskills.io 1,024-character spec limit is unchanged and sits above both. The SUGGESTION tier is the one that moves the average; treat 250 as the target and 400 diff --git a/plugins/kyberforge/.apm/skills/skill-author/references/retrofit.md b/plugins/kyberforge/.apm/skills/skill-author/references/retrofit.md index 6cec846..37fa55d 100644 --- a/plugins/kyberforge/.apm/skills/skill-author/references/retrofit.md +++ b/plugins/kyberforge/.apm/skills/skill-author/references/retrofit.md @@ -122,14 +122,19 @@ milestone), that's gitea-labels-milestones directly. Do not use for pull request or for local git branch/commit work (use gitea-branches or git-branches). ``` -After, 240 characters: +After, the 290 characters that shipped: ```text -Use when reading or writing Gitea issues — list, read, create, comment on, label, close, or -search — even when the user does not say "Gitea". Not pull requests -> `gitea-prs`. Not label or -milestone definitions -> `gitea-labels-milestones`. +Use when reading or writing Gitea issues — "create an issue", "what issues are open", "close +issue #N", "comment on issue #N", "search issues for X" — even when the user does not say +"Gitea". Not pull requests -> `gitea-prs`. Not label or milestone definitions -> +`gitea-labels-milestones`. ``` +The retrofit kept the quoted-phrasing register and dropped the verb list, not the other way round. +Either register is admissible — what is banned is carrying both. Choose whichever routes better +for the skill in hand; here the quoted user phrasings do, because they are how people actually ask. + What came out, and why: | Removed | Why | @@ -139,7 +144,7 @@ What came out, and why: | `Composes gitea-labels-milestones for all label inference/resolution and milestone lookup` | A composition note. It changes no routing decision and belongs in `README.md`. | | The parenthetical `(create/edit/delete a label, create/close a milestone)` | Capability enumeration inside a boundary clause. The boundary needs the target, not its feature list. | | The `gitea-branches` / `git-branches` boundary | Dropped entirely. Neither was ever going to win an issue request, so the clause defended against nothing — an invented boundary costs characters and buys no routing accuracy. | -| `Do not use for pull requests (use gitea-prs)` prose form | Kept, but rewritten as `Not pull requests -> \`gitea-prs\`.` The rewrite buys characters and one uniform shape for the router — not safety. Both forms are parsed **and** target-checked, so a typo in the prose form dangles exactly as an arrow typo does. | +| `Do not use for pull requests (use gitea-prs)` prose form | Kept, but rewritten as `Not pull requests -> \`gitea-prs\`.` The rewrite buys characters, one uniform shape for the router, **and** a stricter check: an unresolved arrow target is a blocking ERROR, while an unresolved prose target is only a SUGGESTION unless another target in the same sentence resolves. The prose form does not dangle as loudly. | What stayed: one trigger clause, one capability clause, the indirect trigger (genuinely warranted here — people say "create an issue", not "create a Gitea issue"), and the boundary clauses. @@ -153,7 +158,9 @@ a skill that was never going to compete, not a second real one. **Never let a hyphenated routing target wrap across lines in a folded `>` scalar.** YAML folding replaces the newline with a space, so `gitea-labels-` at the end of one line and `milestones` at -the start of the next fold into `gitea-labels- milestones`. `validate.sh` then reads the target as -`gitea-labels`, finds no such skill, and reports a dangling boundary target — the live finding on -`gitea-issues` today. Reflow the line so the whole name sits on one of them. The same applies to -any backticked skill or agent name in a description. +the start of the next fold into `gitea-labels- milestones`. The gate then reads the target as +`gitea-labels`, finds no such skill, and reports a dangling boundary target. This is not +hypothetical — it is how `gitea-labels-milestones` broke (issue #100). It is fixed: the corpus +carries no dangling target today, and the repo's test suite pins that set as empty, so a +reintroduction fails the suite rather than joining a backlog. Reflow the line so the whole name +sits on one of them. The same applies to any backticked skill or agent name in a description. diff --git a/plugins/kyberforge/skills/agent-audit/README.md b/plugins/kyberforge/skills/agent-audit/README.md index d25374f..3face54 100644 --- a/plugins/kyberforge/skills/agent-audit/README.md +++ b/plugins/kyberforge/skills/agent-audit/README.md @@ -57,8 +57,9 @@ Pass the path to either agent file as the argument. | `assets/vale/styles/Kyberforge/VagueWording.yml` | Flags vague capability wording ("helps with", "utilize", "assists with", "used for") in descriptions | | `assets/vale/styles/KyberforgeCopilot/ProactivePhrase.yml` | Flags CC-specific "Use proactively" phrasing with no effect in Copilot descriptions | | `references/README.md` | Directory documentation for references/ | -| `references/description-quality.md` | Rubric for the description dimension — three-part shape, the 250/400-character budget, the hand-invoked contract, and the internal-mechanics FAIL | -| `references/body-and-delegation.md` | Rubric for the body, delegation and comment-discipline dimensions — the delegation FAIL and why agents take no body word gate | +| `references/finding-criteria.md` | Every dimension's FAIL and SUGGESTION criteria — the one Step 3 file read on every run; it decides which rubrics below are worth loading | +| `references/description-quality.md` | Rubric for the description dimension — why the description is the expensive part, the hand-invoked contract, the three-part shape, indirect triggers, and near-miss exclusions | +| `references/body-and-delegation.md` | Rubric for the body, delegation and comment-discipline dimensions — the core test, the delegation FAIL, why agents take no body word gate, and what an agent body is for | | `references/scope-plugin-apm.md` | Scope contract for a single vendor-neutral APM agent file — allowlist, dimension routing, and the dimensions that do not apply | | `references/scope-project-user.md` | Scope contract for a CC / Copilot pair — counterpart derivation, provider field rules, pair consistency | | `references/validation-scripts.md` | Loaded only when a Step 1 script fails or cannot run — scope-detection walk-up, manual fallback checks, known script failures | diff --git a/plugins/kyberforge/skills/agent-audit/SKILL.md b/plugins/kyberforge/skills/agent-audit/SKILL.md index 5086802..19abac3 100644 --- a/plugins/kyberforge/skills/agent-audit/SKILL.md +++ b/plugins/kyberforge/skills/agent-audit/SKILL.md @@ -37,7 +37,7 @@ bash scripts/vale-wrap.sh [] If a validation script fails or cannot run — Bash denied, `python3` or `vale` absent, `references/field-inventory.md` missing — read `references/validation-scripts.md`; what these scripts measure is not reproducible by reading. -`validate-provenance.sh` prints nothing on success and runs at plugin/APM scope only, exiting 0 silently elsewhere. Its FAIL findings become a separate `### Provenance` dimension, and it emits Why and Fix itself — surface those verbatim. +`validate-provenance.sh` prints nothing on success, so read its exit code before you read its silence. **0** is a genuine pass, including the silent exit 0 at project or user scope, where plugin-scope provenance does not apply. **1** means real findings: its FAILs and INFOs become a separate `### Provenance` dimension, and it emits Why and Fix itself — surface those verbatim. **2** means the check never ran — a bad argument or a missing dependency, reason on stderr, no findings and often no stdout at all. On a 2, report `### Provenance` as unverified and quote the stderr reason; never grade it as a clean pass. `validate.sh` uses the same 2 tier. `vale-wrap.sh` applies the bundled `Kyberforge` style as a prefilter. Pass no `--config`; the wrapper locates its own. At project/user scope pass both files of the pair, not only the one you were handed. Every rule is graded `error`, so every alert is a FAIL. Report each one citing its rule ID, filed under the dimension it belongs to, and do not re-derive it by judgment: @@ -57,14 +57,14 @@ Read the agent file end to end, and at project/user scope its counterpart too. A ## Step 3 — Qualitative audit -Load a dimension's rubric before judging that dimension. +Read `references/finding-criteria.md` first — every dimension's FAIL and SUGGESTION criteria. Load the rubric below only for a dimension the criteria put in play: one carrying a candidate finding, or one where the criterion alone does not settle the call. -| Dimension | Read | +| Dimension | Rubric | |---|---| | description | `references/description-quality.md` | | body, delegation, comment-discipline | `references/body-and-delegation.md` | -Cite file and line number for every finding. +Each rubric is the reasoning behind its criteria, not a second copy of them. Cite file and line number for every finding. ## Step 4 — Report diff --git a/plugins/kyberforge/skills/agent-audit/references/README.md b/plugins/kyberforge/skills/agent-audit/references/README.md index 58bda01..6ae112e 100644 --- a/plugins/kyberforge/skills/agent-audit/references/README.md +++ b/plugins/kyberforge/skills/agent-audit/references/README.md @@ -10,8 +10,9 @@ Additional documentation agents load on demand. | File | Purpose | |------|---------| -| `description-quality.md` | Rubric for the description dimension — three-part shape, the 250/400-character budget, the hand-invoked contract, and the internal-mechanics FAIL. | -| `body-and-delegation.md` | Rubric for the body, delegation and comment-discipline dimensions — the delegation FAIL, why agents take no body word gate, and what an agent body is for. | +| `finding-criteria.md` | Every dimension's FAIL and SUGGESTION criteria — the one Step 3 file read on every run; it decides which rubrics below are worth loading. | +| `description-quality.md` | Rubric for the description dimension — why the description is the expensive part, the hand-invoked contract, the three-part shape, indirect triggers, and near-miss exclusions. | +| `body-and-delegation.md` | Rubric for the body, delegation and comment-discipline dimensions — the core test, the delegation FAIL, why agents take no body word gate, and what an agent body is for. | | `scope-plugin-apm.md` | Contract for a single vendor-neutral `.apm/agents/.agent.md` file — allowlist, dimension routing, and the dimensions that do not apply. | | `scope-project-user.md` | Contract for a Claude Code / Copilot file pair — counterpart derivation, provider field rules, and pair consistency. | | `validation-scripts.md` | Loaded only when a Step 1 script fails or cannot run — scope-detection walk-up, manual fallback checks, and known script failures. | diff --git a/plugins/kyberforge/skills/agent-audit/references/body-and-delegation.md b/plugins/kyberforge/skills/agent-audit/references/body-and-delegation.md index ef9e598..325bed6 100644 --- a/plugins/kyberforge/skills/agent-audit/references/body-and-delegation.md +++ b/plugins/kyberforge/skills/agent-audit/references/body-and-delegation.md @@ -98,24 +98,8 @@ to a shipped file. At plugin/APM scope the stakes are higher than tidiness: `apm frontmatter verbatim to every target, `` is not valid YAML, and `validate.sh` FAILs a frontmatter block that still contains one. -## Auditing guidance +## Where the criteria live -Flag as FAIL if: - -- The body restates a procedure owned by a skill the agent can invoke — Fix: invoke `` - instead -- A sentence answers "no" to the core test — it is padding -- A decision point presents a menu of options with no default -- An instruction repeats content already in the description -- Frontmatter comments are template scaffolding rather than instruction, or are HTML comments at - plugin/APM scope -- A prescriptive sequence is used where flexibility is fine, or the reverse - -Flag as SUGGESTION if: - -- The body does not open with a direct role instruction -- The body specifies no error handling — nothing tells the agent what to do with malformed, - missing or contradictory input -- The job the agent describes is unbounded, or bounded only implicitly -- A rationale is missing from a rule the agent is expected to enforce — present but unexplained -- Comments are useful but verbose enough to bury the field they annotate +Every FAIL and SUGGESTION criterion for these dimensions is in `references/finding-criteria.md`, +which Step 3 reads on every run. This file is the reasoning behind them, loaded only when that file +puts the body, delegation or comment-discipline dimension in play. diff --git a/plugins/kyberforge/skills/agent-audit/references/description-quality.md b/plugins/kyberforge/skills/agent-audit/references/description-quality.md index d3863af..eac9c27 100644 --- a/plugins/kyberforge/skills/agent-audit/references/description-quality.md +++ b/plugins/kyberforge/skills/agent-audit/references/description-quality.md @@ -82,49 +82,8 @@ description: > dispatched and safety-gated. Not conversational git help -> git-workflow. ``` -## Auditing guidance +## Where the criteria live -Flag as FAIL if: - -- **Over 400 characters.** Measured on the folded YAML value, not the raw source lines. - `validate.sh` reports the number; do not re-derive it, but do point the Fix at what to cut. Agent - descriptions have no platform-documented ceiling of their own — unlike a skill's 1,024-character - spec limit, the 400-character house ceiling is the only hard limit there is, so do not go looking - for a backstop behind it. -- **Internal mechanics appear in the description.** Any of: - - capability enumeration or a feature list; - - output-format detail ("Produces a compact findings report with Why and Fix per finding"); - - composition or architecture notes ("composes X rather than duplicating Y", "a cross-cutting - shared agent", "the human-facing entry point", "replaces the old flat invocation"); - - implementation detail ("self-validates via a bundled deterministic script"). - - None of it can change a routing decision and all of it is preloaded. - `Kyberforge.CompositionNote` catches the common phrasings deterministically; the rest is - judgment. This is the rule that deflates a description, so apply it before reaching for length. -- **The same trigger stated twice in two registers** — a verb list, then the same verbs re-quoted - as user phrasings, usually in the same order. One register, whichever routes better. -- **Descriptive rather than imperative phrasing** (`This agent ...`, `This is the ...`). - `Kyberforge.DescriptionOpener` catches any opener matching `^This`. There is no action-verb rule - here and never was a defensible one: an `Orchestrates ...` or `Audits ...` opener is a catalogue - entry, not a trigger. -- **Vague capabilities** ("helps with agents" where "audits an agent definition pair" was - available). `Kyberforge.VagueWording` catches the known filler; imprecision outside that list is - judgment. -- **A boundary clause naming a target that does not resolve** to a real skill directory or agent - file in the authoring source. `validate.sh` resolves this for agent files at both scopes and - reports each unresolved target itself — take its verdict rather than re-resolving the name by - hand, because a hand-walk over a different universe can contradict it. What is left to you is - semantic and the script cannot reach it: whether a target that *does* resolve is the right - sibling to exclude, and whether a clause naming no target at all ("examine the files manually") - should have named one. -- **`Use proactively` in a Copilot or vendor-neutral description.** - `KyberforgeCopilot.ProactivePhrase` catches it. The phrase steers the Claude Code runtime and - does nothing anywhere else, so in a `.agent.md` it is preloaded text that buys no behaviour. -- **Trigger-list, boundary or indirect-trigger content on a hand-invoked agent** — see Step 0. - -Flag as SUGGESTION if: - -- **Over 250 characters** but at or under 400. This tier is what moves the corpus average; the FAIL - tier only stops outliers. Report it rather than treating a 399-character description as clean. -- A near-miss exclusion is present but targets a weak near-miss. -- An indirect trigger is present and warranted but could name the omitted phrasing more precisely. +Every FAIL and SUGGESTION criterion for this dimension is in `references/finding-criteria.md`, +which Step 3 reads on every run. This file is the reasoning behind them, loaded only when that file +puts the description dimension in play. diff --git a/plugins/kyberforge/skills/agent-audit/references/finding-criteria.md b/plugins/kyberforge/skills/agent-audit/references/finding-criteria.md new file mode 100644 index 0000000..91e431a --- /dev/null +++ b/plugins/kyberforge/skills/agent-audit/references/finding-criteria.md @@ -0,0 +1,98 @@ +--- +source_keys: + - context7-websites-code-claude + - claude-code-plugins-docs + - claude-code-subagents-docs + - context7-github-en-copilot + - github-custom-agents-configuration +--- + +# Finding Criteria + +Every FAIL and SUGGESTION criterion, for every qualitative dimension, and nothing else. The +reasoning each criterion stands on, its worked examples and its house rules stay in that +dimension's rubric, which Step 3 loads only for a dimension this file puts in play. + +Two rules on using it: + +- A criterion that plainly applies is a finding. Write it up citing file and line. +- A criterion that might apply, or whose call the wording here does not settle, is a reason to load + that dimension's rubric — never a reason to drop the candidate. This file decides which rubrics + to read; it does not settle a close call on its own. + +## description — `references/description-quality.md` + +Flag as FAIL if: + +- **Over 400 characters.** Measured on the folded YAML value, not the raw source lines. + `validate.sh` reports the number; do not re-derive it, but do point the Fix at what to cut. Agent + descriptions have no platform-documented ceiling of their own, so 400 is the only hard limit + there is — do not go looking for a backstop behind it. +- **Internal mechanics appear in the description.** Any of: + - capability enumeration or a feature list; + - output-format detail ("Produces a compact findings report with Why and Fix per finding"); + - composition or architecture notes ("composes X rather than duplicating Y", "a cross-cutting + shared agent", "the human-facing entry point", "replaces the old flat invocation"); + - implementation detail ("self-validates via a bundled deterministic script"). + + None of it can change a routing decision and all of it is preloaded. + `Kyberforge.CompositionNote` catches the common phrasings deterministically; the rest is + judgment. This is the rule that deflates a description, so apply it before reaching for length. +- **The same trigger stated twice in two registers** — a verb list, then the same verbs re-quoted + as user phrasings, usually in the same order. One register, whichever routes better. +- **Descriptive rather than imperative phrasing** (`This agent ...`, `This is the ...`). + `Kyberforge.DescriptionOpener` catches any opener matching `^This`. +- **Vague capabilities** ("helps with agents" where "audits an agent definition pair" was + available). `Kyberforge.VagueWording` catches the known filler; imprecision outside that list is + judgment. +- **`Use proactively` in a Copilot or vendor-neutral description.** + `KyberforgeCopilot.ProactivePhrase` catches it. The phrase steers the Claude Code runtime and + does nothing anywhere else, so in a `.agent.md` it is preloaded text that buys no behaviour. +- **Trigger-list, boundary or indirect-trigger content on a hand-invoked agent** — see Step 0 of + `references/description-quality.md`. + +Flag as SUGGESTION if: + +- **Over 250 characters** but at or under 400. This tier is what moves the corpus average; the FAIL + tier only stops outliers. Report it rather than treating a 399-character description as clean. +- A near-miss exclusion is present but targets a weak near-miss. +- An indirect trigger is present and warranted but could name the omitted phrasing more precisely. + +**An unresolved boundary target is not graded here.** `validate.sh` resolves boundary targets for +agent files at both scopes and tiers the verdict itself — route notation (`/name`, an arrow form) +is an ERROR, the bare prose form a SUGGESTION unless a second target in the same sentence resolves. +Step 1 has already filed it under `### Structure` at that tier. Take the script's verdict rather +than re-resolving the name by hand, and do not re-grade it under description: a hand-walk over a +different universe can contradict the script, and re-grading puts one target in the report twice. +What is left to judgment is semantic and the script cannot reach it: whether a target that *does* +resolve is the right sibling to exclude, and whether a clause naming no target at all ("examine the +files manually") should have named one. + +## body, delegation and comment-discipline — `references/body-and-delegation.md` + +Flag as FAIL if: + +- The body restates a procedure owned by a skill the agent can invoke — Fix: invoke `` + instead +- A sentence answers "no" to the core test — it is padding +- A decision point presents a menu of options with no default +- An instruction repeats content already in the description +- Frontmatter comments are template scaffolding rather than instruction, or are HTML comments at + plugin/APM scope +- A prescriptive sequence is used where flexibility is fine, or the reverse + +Flag as SUGGESTION if: + +- The body does not open with a direct role instruction +- The body specifies no error handling — nothing tells the agent what to do with malformed, + missing or contradictory input +- The job the agent describes is unbounded, or bounded only implicitly +- A rationale is missing from a rule the agent is expected to enforce — present but unexplained +- Comments are useful but verbose enough to bury the field they annotate + +**Never report an agent body as too long on a word count.** ADR-0020 gates a skill body at +600/900 words and deliberately gates an agent body at nothing, because an agent body *becomes* the +system prompt of a fresh context rather than competing with a live conversation. There is no number +to cite. The one length signal that applies is the Copilot runtime's 30,000-character body limit, +which `validate.sh` already reports as a SUGGESTION. Length is judged through the delegation FAIL +above instead. diff --git a/plugins/kyberforge/skills/agent-audit/references/sources.md b/plugins/kyberforge/skills/agent-audit/references/sources.md index 748c4f8..7fcca6f 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, references/description-quality.md, references/body-and-delegation.md, references/scope-project-user.md +- **Contributing files:** SKILL.md, references/finding-criteria.md, references/field-inventory.md, references/description-quality.md, references/body-and-delegation.md, references/scope-project-user.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, references/body-and-delegation.md, references/scope-plugin-apm.md, references/validation-scripts.md +- **Contributing files:** SKILL.md, references/finding-criteria.md, references/field-inventory.md, references/body-and-delegation.md, references/scope-plugin-apm.md, references/validation-scripts.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, references/description-quality.md, references/body-and-delegation.md, references/scope-plugin-apm.md, references/scope-project-user.md, references/validation-scripts.md +- **Contributing files:** SKILL.md, references/finding-criteria.md, references/field-inventory.md, references/description-quality.md, references/body-and-delegation.md, references/scope-plugin-apm.md, references/scope-project-user.md, references/validation-scripts.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, references/description-quality.md, references/body-and-delegation.md, references/scope-project-user.md +- **Contributing files:** SKILL.md, references/finding-criteria.md, references/field-inventory.md, references/description-quality.md, references/body-and-delegation.md, references/scope-project-user.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, references/description-quality.md, references/body-and-delegation.md, references/scope-plugin-apm.md, references/scope-project-user.md, references/validation-scripts.md +- **Contributing files:** SKILL.md, references/finding-criteria.md, references/field-inventory.md, references/description-quality.md, references/body-and-delegation.md, references/scope-plugin-apm.md, references/scope-project-user.md, references/validation-scripts.md - **Status:** `extracted` ## github-cli-plugin-reference diff --git a/plugins/kyberforge/skills/agent-author/references/contract.md b/plugins/kyberforge/skills/agent-author/references/contract.md index 50f6397..cea9336 100644 --- a/plugins/kyberforge/skills/agent-author/references/contract.md +++ b/plugins/kyberforge/skills/agent-author/references/contract.md @@ -61,14 +61,29 @@ word for word. Indirect triggers ("even if the user doesn't say X") take a similar conditional at every scope: add one only where the user's natural phrasing genuinely omits the domain word. -**Boundary targets must resolve.** Both forms are checked — the arrow and the prose form ("do not -use for X, use `y` instead") — so a typo dangles either way. Targets resolve against a universe +**Boundary targets must resolve, and the notation decides how hard the gate bites.** Route +notation — `/name`, or any arrow form (`-> name`, `` -> `name` ``) — is checked +unconditionally: an unresolved target there is a blocking ERROR. The prose form ("do not use +for X, use `y` instead") is only a SUGGESTION by default, because a bare hyphenated word in a +boundary clause is as likely to be a tool, a file format or an English compound as a route. It +is promoted to a blocking ERROR only when a second target in the same sentence *does* resolve, +which corroborates that the name was meant as a route. So a typo does **not** dangle equally +either way — write the arrow when you want the target checked. Targets resolve against a universe built by walking up **from the agent file itself**: the nearest ancestor holding `plugins/*/.apm/{skills,agents}` (or, failing that, the nearest ancestor holding `.git`) contributes every skill and agent under `/plugins/*/`, plus the agent's own apm package and the packages that package declares in `apm.yml` under `dependencies.apm`. A sibling plugin in the same monorepo therefore resolves; a skill in an unrelated repo does not. A target outside that universe sends the -router nowhere. Verify it before writing it — do not invent a plausible sibling. +router nowhere — a blocking failure in arrow or `/name` form, and in prose form only a SUGGESTION +nobody is forced to act on, which is the worse outcome because it ships. Verify it before writing +it — do not invent a plausible sibling. + +**Never let a hyphenated routing target wrap across lines in a folded `>` scalar.** YAML folding +replaces the newline with a space, so `gitea-labels-` at the end of one line and `milestones` at +the start of the next fold into `gitea-labels- milestones`. The gate then reads the target as +`gitea-labels`, finds no such skill, and reports it dangling — nothing in the source lines looks +wrong. Reflow so the whole name sits on one line. The same applies to any backticked skill or +agent name anywhere in a description. That universe is the apm marketplace and stops there. A **host built-in is not a routing target**: `/compact`, `/clear` and `/init` are Claude Code slash commands with no counterpart in Copilot CLI diff --git a/plugins/kyberforge/skills/apm-install/SKILL.md b/plugins/kyberforge/skills/apm-install/SKILL.md index 9b249ea..054d161 100644 --- a/plugins/kyberforge/skills/apm-install/SKILL.md +++ b/plugins/kyberforge/skills/apm-install/SKILL.md @@ -3,7 +3,8 @@ name: apm-install description: > Use when installing, pinning, or upgrading the apm (Agent Package Manager) CLI itself, or installing and managing an agent runtime apm drives. Not - authoring, publishing, or auditing apm packages -> `apm-workflow`. + authoring, publishing, auditing, or dependency installation for an apm + package -> `apm-workflow`. metadata: category: apm source_keys: diff --git a/plugins/kyberforge/skills/apm-workflow/SKILL.md b/plugins/kyberforge/skills/apm-workflow/SKILL.md index 2cc3d55..cd258b4 100644 --- a/plugins/kyberforge/skills/apm-workflow/SKILL.md +++ b/plugins/kyberforge/skills/apm-workflow/SKILL.md @@ -1,10 +1,9 @@ --- name: apm-workflow description: > - Use when managing an apm package, its apm.yml manifest, or an apm - marketplace — authoring through publishing — even when the user does not say - "apm", e.g. "set up the package manifest". Not the apm binary or an agent - runtime -> `apm-install`. + Use when authoring, installing, or publishing an apm package, its apm.yml and + the dependencies it declares, or an apm marketplace — even when the user does + not say "apm". Not the apm binary or an agent runtime -> `apm-install`. metadata: category: apm source_keys: diff --git a/plugins/kyberforge/skills/forge/SKILL.md b/plugins/kyberforge/skills/forge/SKILL.md index e3dabd2..860e9db 100644 --- a/plugins/kyberforge/skills/forge/SKILL.md +++ b/plugins/kyberforge/skills/forge/SKILL.md @@ -2,10 +2,11 @@ name: forge description: > Use when the user wants to build or improve something but has not yet named - the artifact type — skill, agent, plugin, or marketplace entry; "a skill for - the gitea plugin, or an agent?". Routes to the matching author skill. Do not - use when the type is already named — invoke `skill-author`, `agent-author` - or `apm-workflow` directly. + the artifact type — skill, agent, plugin, or marketplace entry; "not sure if + this should be a skill or a plugin", "I have an idea but don't know where it + belongs". Routes to the matching author skill. Do not use when the type is + already named — invoke `skill-author`, `agent-author` or `apm-workflow` + directly. metadata: category: factory source_keys: @@ -23,6 +24,8 @@ metadata: Call `grill-with-docs` unless a grill session has already run and is available in the context. +`grill-with-docs` ships in a sibling plugin that kyberforge does not declare as an apm dependency, so it resolves in the authoring monorepo but can be absent where kyberforge is installed alone. If it does not resolve, grill inline yourself rather than skipping the step: what problem the artifact solves, who invokes it and how, what it must refuse, and which existing skill or plugin already owns part of the job. Say which path you took. + Grilling regularly overturns the artifact type assumed at the start, or splits one idea into several artifacts, so it runs before classification rather than confirming it. Run it inline in the current conversation — grilling is interactive and a subagent cannot hold the back-and-forth. ## Step 2 — Classify and dispatch diff --git a/plugins/kyberforge/skills/skill-audit/README.md b/plugins/kyberforge/skills/skill-audit/README.md index dfc5400..277c836 100644 --- a/plugins/kyberforge/skills/skill-audit/README.md +++ b/plugins/kyberforge/skills/skill-audit/README.md @@ -36,7 +36,7 @@ Provide the path to the skill directory to audit when invoking. | `assets/vale/styles/Kyberforge/SentenceOpenerThereIs.yml` | Vale rule — flags body sentences starting with "There is"/"There are" | | `assets/vale/styles/Kyberforge/VagueWording.yml` | Vale rule — flags known filler wording (e.g. "helps with", "utilize") | | `references/finding-criteria.md` | Every dimension's FAIL and SUGGESTION criteria — the one Step 3 file loaded on every run; it decides which rubrics below are worth loading | -| `references/description-quality.md` | Rubric for the description dimension — three-part shape, the 250/400-character budget, the hand-invoked (`disable-model-invocation`) contract, and the internal-mechanics FAIL | +| `references/description-quality.md` | Rubric for the description dimension — why the description is the expensive part, the hand-invoked (`disable-model-invocation`) contract, the three-part shape, when an indirect trigger is warranted, near-miss exclusions, and a before/after pair | | `references/body-discipline.md` | Rubric for the body-discipline dimension — the core test, the 600/900 body-only budget against the 2,770-word whole-file backstop, the mandatory-dispatch rule, and the Gotchas constraints | | `references/patterns.md` | Rubric for the patterns dimension — which instruction construct fits which job, and how each is correctly formed | | `references/file-structure.md` | Rubric for the file-structure and internal-consistency dimensions — permitted directories, cross-plugin path rules and their two structural exemptions, README drift | diff --git a/plugins/kyberforge/skills/skill-audit/SKILL.md b/plugins/kyberforge/skills/skill-audit/SKILL.md index 0c86feb..1a66612 100644 --- a/plugins/kyberforge/skills/skill-audit/SKILL.md +++ b/plugins/kyberforge/skills/skill-audit/SKILL.md @@ -33,11 +33,11 @@ bash scripts/validate-provenance.sh bash scripts/vale-wrap.sh /SKILL.md ``` -`validate.sh` findings become the `### Structure` dimension — its FAILs and its SUGGESTIONs both. +`validate.sh` findings become the `### Structure` dimension — its FAILs and its SUGGESTIONs both, at the tier the script assigned. Report each once; never re-grade one under another dimension. Unresolved boundary targets are where this bites, because their tier turns on notation. If any of the three cannot run, or exits non-zero for a reason other than findings, read `references/validation-scripts.md` — it carries the manual fallback and the misleading exit codes. Ordinary content FAILs are the expected outcome here and need no fallback. -`validate-provenance.sh` prints nothing on success. Its FAIL and INFO findings become a separate `### Provenance` dimension, and it emits Why and Fix itself — surface those verbatim. +`validate-provenance.sh` prints nothing on success, so read its exit code before you read its silence. **0** is a genuine pass. **1** means real findings: its FAILs and INFOs become a separate `### Provenance` dimension, and it emits Why and Fix itself — surface those verbatim. **2** means the check never ran — a usage or environment error, reason on stderr, no findings and often no stdout at all. On a 2, report `### Provenance` as unverified and quote the stderr reason. Never grade an exit 2 as a clean pass: empty stdout there means nothing was checked, not that nothing was wrong. `vale-wrap.sh` applies the bundled `Kyberforge` style as a prefilter. Pass no `--config`; the wrapper locates its own. Every rule is graded `error`, so every alert is a FAIL. Report each one citing its rule ID, filed under the dimension it belongs to, and do not re-derive it by judgment: diff --git a/plugins/kyberforge/skills/skill-audit/references/body-discipline.md b/plugins/kyberforge/skills/skill-audit/references/body-discipline.md index 1157d83..31f28c6 100644 --- a/plugins/kyberforge/skills/skill-audit/references/body-discipline.md +++ b/plugins/kyberforge/skills/skill-audit/references/body-discipline.md @@ -135,9 +135,16 @@ Constraints: Worked negative example — **`git-commits` v0.1.2 at commit `5e23250`, a fixed pre-retrofit snapshot, not the current file.** The live skill is v0.1.3 and matches none of the citations below; they are quoted as they stood before the ADR-0020 retrofit, and are not to be refreshed against -`HEAD`. Read the snapshot with -`git show 5e23250:plugins/git/.apm/skills/git-commits/SKILL.md`. That body carried -twelve Gotchas, four of which restated content already below them or already in the description: +`HEAD`. The snapshot is reachable only from a checkout of the authoring repo — an installed plugin +cache holds no git history and no such path — so read the citations below as quoted rather than +going to look for the file. From a checkout: + +```text +git show 5e23250:/.apm/skills/git-commits/SKILL.md +``` + +That body carried twelve Gotchas, four of which restated content already below them or already in +the description: | Gotcha | Restates | |---|---| diff --git a/plugins/kyberforge/skills/skill-audit/references/description-quality.md b/plugins/kyberforge/skills/skill-audit/references/description-quality.md index 579426c..ef027f8 100644 --- a/plugins/kyberforge/skills/skill-audit/references/description-quality.md +++ b/plugins/kyberforge/skills/skill-audit/references/description-quality.md @@ -40,8 +40,11 @@ A model-invoked description carries exactly three things: the agent is deciding whether to act, not reading a catalogue entry. 2. **At most one capability clause.** What it does, in one clause. Never an enumeration. 3. **Boundary clause.** Compressed form: `Not -> .` The target must resolve to - a real skill directory or agent file in the authoring source; `validate.sh` checks that - deterministically and a dangling target already surfaces as a Structure FAIL. + a real skill directory or agent file in the authoring source. `validate.sh` checks that + deterministically and grades it by notation: an unresolved `/name` or arrow target is an ERROR + and reaches the report as a Structure FAIL, while an unresolved prose-form target ("use `y` + instead") is only a SUGGESTION unless a second target in the same sentence resolves. Take the + script's tier as given and report it once, under Structure. Everything else belongs in the body or in `README.md`. diff --git a/plugins/kyberforge/skills/skill-audit/references/finding-criteria.md b/plugins/kyberforge/skills/skill-audit/references/finding-criteria.md index 73d41c0..05eb85d 100644 --- a/plugins/kyberforge/skills/skill-audit/references/finding-criteria.md +++ b/plugins/kyberforge/skills/skill-audit/references/finding-criteria.md @@ -42,8 +42,6 @@ Flag as FAIL if: - **Vague capabilities** ("helps with APIs" where "parses and validates OpenAPI specs" was available). `Kyberforge.VagueWording` catches the known filler; imprecision outside that list is judgment. -- **A boundary clause naming a target that does not resolve** to a real skill directory or agent - file in the authoring source. `validate.sh` reports the unresolved name. - **Trigger-list, boundary or indirect-trigger content on a hand-invoked skill** — see Step 0 of `references/description-quality.md`. - **Over 1024 characters** — the agentskills.io specification ceiling, unchanged and independent @@ -56,6 +54,14 @@ Flag as SUGGESTION if: - A near-miss exclusion is present but targets a weak near-miss. - An indirect trigger is present and warranted but could name the omitted phrasing more precisely. +**An unresolved boundary target is not graded here.** `validate.sh` owns that call and tiers it by +notation — `/name` or an arrow form is an ERROR, the bare prose form a SUGGESTION unless a second +target in the same sentence resolves — and Step 1 has already filed it under `### Structure` at that +tier. Re-grading it as a description FAIL puts one target in the report twice at two tiers. What is +left to judgment here is semantic and the script cannot reach it: whether a target that *does* +resolve is the right sibling to exclude, and whether a clause naming no target at all ("examine the +files manually") should have named one. + ## body-discipline — `references/body-discipline.md` Flag as FAIL if: diff --git a/plugins/kyberforge/skills/skill-author/references/contract.md b/plugins/kyberforge/skills/skill-author/references/contract.md index faf0479..e6795bf 100644 --- a/plugins/kyberforge/skills/skill-author/references/contract.md +++ b/plugins/kyberforge/skills/skill-author/references/contract.md @@ -47,15 +47,22 @@ explicitly" only where the user's natural phrasing genuinely omits the domain wo for `git-commits`, where the user says "commit". Adding one everywhere is what inflated this corpus, and it was deleted as a blanket rule. -**Boundary targets must resolve.** Both forms are checked — the arrow and the prose form ("do not -use for X, use `y` instead") — so a typo dangles either way. Targets resolve against a universe -built by walking up **from the SKILL.md itself**: the nearest ancestor holding +**Boundary targets must resolve, and the notation decides how hard the gate bites.** Route +notation — `/name`, or any arrow form (`-> name`, `` -> `name` ``) — is checked +unconditionally: an unresolved target there is a blocking ERROR. The prose form ("do not use +for X, use `y` instead") is only a SUGGESTION by default, because a bare hyphenated word in a +boundary clause is as likely to be a tool, a file format or an English compound as a route. It +is promoted to a blocking ERROR only when a second target in the same sentence *does* resolve, +which corroborates that the name was meant as a route. So a typo does **not** dangle equally +either way — write the arrow when you want the target checked. Targets resolve against a universe built by walking up **from the SKILL.md +itself**: the nearest ancestor holding `plugins/*/.apm/{skills,agents}` (or, failing that, the nearest ancestor holding `.git`) contributes every skill and agent under `/plugins/*/`, plus the skill's own apm package and the packages that package declares in `apm.yml` under `dependencies.apm`. A sibling plugin in the same monorepo therefore resolves; a skill in an unrelated repo does not. A boundary clause naming a target -outside that universe sends the router nowhere and fails the audit. Check the target exists before -writing it — do not invent a plausible sibling name. +outside that universe sends the router nowhere — a blocking failure in arrow or `/name` form, and +in prose form a SUGGESTION nobody is forced to act on, which is the worse outcome because it ships. +Check the target exists before writing it — do not invent a plausible sibling name. That universe is the apm marketplace and stops there. A **host built-in is not a routing target**: `/compact`, `/clear` and `/init` are Claude Code slash commands with no counterpart in Copilot CLI @@ -68,6 +75,13 @@ checked by nothing and the gate emits a SUGGESTION naming both. Split instead of `Not -> first-skill. Not -> second-skill.`, never `Not -> first-skill or second-skill`. +**Never let a hyphenated routing target wrap across lines in a folded `>` scalar.** YAML folding +replaces the newline with a space, so `gitea-labels-` at the end of one line and `milestones` at +the start of the next fold into `gitea-labels- milestones`. The gate then reads the target as +`gitea-labels`, finds no such skill, and reports it dangling — this is what broke +`gitea-labels-milestones`, and nothing in the source lines looks wrong. Reflow so the whole name +sits on one line. The same applies to any backticked skill or agent name anywhere in a description. + **Length.** 250 characters SUGGESTION, 400 characters FAIL, counting the frontmatter value only with YAML folding resolved. The agentskills.io 1,024-character spec limit is unchanged and sits above both. The SUGGESTION tier is the one that moves the average; treat 250 as the target and 400 diff --git a/plugins/kyberforge/skills/skill-author/references/retrofit.md b/plugins/kyberforge/skills/skill-author/references/retrofit.md index 6cec846..37fa55d 100644 --- a/plugins/kyberforge/skills/skill-author/references/retrofit.md +++ b/plugins/kyberforge/skills/skill-author/references/retrofit.md @@ -122,14 +122,19 @@ milestone), that's gitea-labels-milestones directly. Do not use for pull request or for local git branch/commit work (use gitea-branches or git-branches). ``` -After, 240 characters: +After, the 290 characters that shipped: ```text -Use when reading or writing Gitea issues — list, read, create, comment on, label, close, or -search — even when the user does not say "Gitea". Not pull requests -> `gitea-prs`. Not label or -milestone definitions -> `gitea-labels-milestones`. +Use when reading or writing Gitea issues — "create an issue", "what issues are open", "close +issue #N", "comment on issue #N", "search issues for X" — even when the user does not say +"Gitea". Not pull requests -> `gitea-prs`. Not label or milestone definitions -> +`gitea-labels-milestones`. ``` +The retrofit kept the quoted-phrasing register and dropped the verb list, not the other way round. +Either register is admissible — what is banned is carrying both. Choose whichever routes better +for the skill in hand; here the quoted user phrasings do, because they are how people actually ask. + What came out, and why: | Removed | Why | @@ -139,7 +144,7 @@ What came out, and why: | `Composes gitea-labels-milestones for all label inference/resolution and milestone lookup` | A composition note. It changes no routing decision and belongs in `README.md`. | | The parenthetical `(create/edit/delete a label, create/close a milestone)` | Capability enumeration inside a boundary clause. The boundary needs the target, not its feature list. | | The `gitea-branches` / `git-branches` boundary | Dropped entirely. Neither was ever going to win an issue request, so the clause defended against nothing — an invented boundary costs characters and buys no routing accuracy. | -| `Do not use for pull requests (use gitea-prs)` prose form | Kept, but rewritten as `Not pull requests -> \`gitea-prs\`.` The rewrite buys characters and one uniform shape for the router — not safety. Both forms are parsed **and** target-checked, so a typo in the prose form dangles exactly as an arrow typo does. | +| `Do not use for pull requests (use gitea-prs)` prose form | Kept, but rewritten as `Not pull requests -> \`gitea-prs\`.` The rewrite buys characters, one uniform shape for the router, **and** a stricter check: an unresolved arrow target is a blocking ERROR, while an unresolved prose target is only a SUGGESTION unless another target in the same sentence resolves. The prose form does not dangle as loudly. | What stayed: one trigger clause, one capability clause, the indirect trigger (genuinely warranted here — people say "create an issue", not "create a Gitea issue"), and the boundary clauses. @@ -153,7 +158,9 @@ a skill that was never going to compete, not a second real one. **Never let a hyphenated routing target wrap across lines in a folded `>` scalar.** YAML folding replaces the newline with a space, so `gitea-labels-` at the end of one line and `milestones` at -the start of the next fold into `gitea-labels- milestones`. `validate.sh` then reads the target as -`gitea-labels`, finds no such skill, and reports a dangling boundary target — the live finding on -`gitea-issues` today. Reflow the line so the whole name sits on one of them. The same applies to -any backticked skill or agent name in a description. +the start of the next fold into `gitea-labels- milestones`. The gate then reads the target as +`gitea-labels`, finds no such skill, and reports a dangling boundary target. This is not +hypothetical — it is how `gitea-labels-milestones` broke (issue #100). It is fixed: the corpus +carries no dangling target today, and the repo's test suite pins that set as empty, so a +reintroduction fails the suite rather than joining a backlog. Reflow the line so the whole name +sits on one of them. The same applies to any backticked skill or agent name in a description.