diff --git a/docs/adr/0016-apm-agent-primitive-drops-provider-specific-fields.md b/docs/adr/0016-apm-agent-primitive-drops-provider-specific-fields.md index bf53a5a..af4e0e2 100644 --- a/docs/adr/0016-apm-agent-primitive-drops-provider-specific-fields.md +++ b/docs/adr/0016-apm-agent-primitive-drops-provider-specific-fields.md @@ -86,5 +86,7 @@ place. lists from `references/field-inventory.md` rather than hardcoding them, with a `source_keys` provenance chain — survives and is reused. Only the *content shape* changes for plugin scope: `field-inventory.md` shifts from two side-by-side CC-only/Copilot-only blocklists to one - vendor-neutral allowlist (`name`/`description`/`model`) for plugin-scope agents, while + vendor-neutral allowlist (`name`/`description`/`model`/`source_keys` — the last for provenance + tracking, validated separately by `validate-provenance.sh` against `sources.md`, not a + provider-specific field) for plugin-scope agents, while continuing to serve its original two-blocklist role for project/user-scope validation. diff --git a/plugins/kyberforge/skills/agent-audit/README.md b/plugins/kyberforge/skills/agent-audit/README.md index f74140d..6d9faa1 100644 --- a/plugins/kyberforge/skills/agent-audit/README.md +++ b/plugins/kyberforge/skills/agent-audit/README.md @@ -7,7 +7,9 @@ plugin/APM scope, or a Claude Code and Copilot file pair at project/user scope. At **plugin/APM scope**, accepts the single `.apm/agents/.agent.md` file — there is no counterpart. Structural checks via `validate.sh` hard-`FAIL` any frontmatter field outside the -vendor-neutral allowlist (`name`, `description`, `model` — see ADR-0016), since `apm compile` +vendor-neutral allowlist (`name`, `description`, `model`, `source_keys` — the last for +provenance tracking, checked separately by `validate-provenance.sh` against `sources.md`; see +ADR-0016), since `apm compile` copies frontmatter verbatim to both harnesses and an unsafe field can't be silently dropped for just one of them. diff --git a/plugins/kyberforge/skills/agent-audit/SKILL.md b/plugins/kyberforge/skills/agent-audit/SKILL.md index 67225a8..47db4ea 100644 --- a/plugins/kyberforge/skills/agent-audit/SKILL.md +++ b/plugins/kyberforge/skills/agent-audit/SKILL.md @@ -44,13 +44,13 @@ The script accepts either the CC file, the Copilot file, or (at plugin/APM scope At **project/user scope** it derives the counterpart and runs the existing pair-based checks. Note FAILs and SUGGESTIONs for the `### Structure` and `### Provider safety` report dimensions. Findings about missing fields, bad name format, empty body, or missing frontmatter → `### Structure`. Findings about CC-only fields in a Copilot file, Copilot-only fields in a CC file, body length, or subagent-unavailable tools → `### Provider safety`. A missing counterpart file → `### Pair consistency`. -At **plugin/APM scope** there is no counterpart — the script instead checks the single file's frontmatter against the `apm-agent-allowlist` in `references/field-inventory.md` (`name`, `description`, `model` — nothing else). Findings about missing fields, bad name format, name/filename-stem mismatch, empty body, or missing frontmatter → `### Structure`, same as project/user scope. Findings about any field outside the allowlist (e.g. `tools`, or any Claude-only/Copilot-only field carried over from a hand-edit) and body length → `### Provider safety` — but the dimension's meaning shifts here: it is no longer a CC-vs-Copilot field-leakage check, it's a vendor-neutral-field-allowlist check, since `apm compile` verbatim-copies this file's frontmatter to every target and there is no per-target integrator to reconcile a CC-only or Copilot-only field (ADR-0016). `### Pair consistency` never applies at this scope — the script never emits a missing-counterpart FAIL here, because there is nothing to pair by design. +At **plugin/APM scope** there is no counterpart — the script instead checks the single file's frontmatter against the `apm-agent-allowlist` in `references/field-inventory.md` (`name`, `description`, `model`, `source_keys` — nothing else; `source_keys` is provenance metadata, not a provider-specific field, and is validated separately by `validate-provenance.sh` against `sources.md`). Findings about missing fields, bad name format, name/filename-stem mismatch, empty body, or missing frontmatter → `### Structure`, same as project/user scope. Findings about any field outside the allowlist (e.g. `tools`, or any Claude-only/Copilot-only field carried over from a hand-edit) and body length → `### Provider safety` — but the dimension's meaning shifts here: it is no longer a CC-vs-Copilot field-leakage check, it's a vendor-neutral-field-allowlist check, since `apm compile` verbatim-copies this file's frontmatter to every target and there is no per-target integrator to reconcile a CC-only or Copilot-only field (ADR-0016). `### Pair consistency` never applies at this scope — the script never emits a missing-counterpart FAIL here, because there is nothing to pair by design. `vale-wrap.sh` ships inside this skill's own `scripts/` — resolve it relative to this skill's directory the same way `scripts/validate.sh` is resolved above, so the invocation works whether this skill is running from this repo or from an installed plugin cache. Pass no `--config`: handed none, the wrapper loads its own sibling `assets/vale/.vale.ini`, located from the script's path rather than from the cwd. Adding an explicit relative `--config` breaks exactly the case the self-location covers — a resolved script path plus an unresolved config path yields `E100 Runtime error ... does not exist`, exit 2, which the fallback below then misreads as "vale unavailable". At project/user scope, run it against both files of the pair (not just the one passed in); at plugin/APM scope, run it against the single file. `Kyberforge` applies to all of these files via the `**/agents/*.md` glob; `KyberforgeCopilot` applies to any `*.agent.md` file — including the plugin/APM-scope file, which already has that extension — via the `**/*.agent.md` glob, since its one rule (`Use proactively`) flags CC-specific phrasing that's meaningless in a vendor-neutral or Copilot description. Every Vale alert is a `FAIL` — all rules are graded `error` — so report each one in the `### Description` / `### Body` dimensions citing its rule ID (e.g. `KyberforgeCopilot.ProactivePhrase`). Skip and fall back to Step 2 judgment if the `vale` binary is unavailable. If Vale reports `0 files` scanned, treat the pass as NOT RUN — not as clean — and fall back to full Step 2 judgment for the dimensions it would have covered. `validate-provenance.sh` operates at plugin/APM scope only — it walks up from the agent file's directory the same way `validate.sh` does (nearest ancestor `apm.yml` with a top-level `type:` field; skip a `type:`-less marketplace-only `apm.yml`; stop at `.git` or the filesystem root) and exits 0 silently if that walk doesn't land on a package root, or when no provenance data exists. When it does apply, it validates the chain between the single file's own `source_keys` and the package-scoped `sources.md` (package root — see ADR-0010). Note FAILs from this script for the `### Provenance` dimension — surface them verbatim with Why and Fix. -If the scripts cannot run (Bash denied, python3 unavailable), perform checks manually. At project/user scope: counterpart file exists, required fields present (`name`, `description`, non-empty body), `name` is kebab-case, Copilot CLI `.agent.md` `name` must match filename stem (CC files are exempt — the CC platform does not require name to match filename), no `FILL IN:` placeholders, no CC-only fields in Copilot file, no Copilot-only fields in CC file (read `references/field-inventory.md` for the authoritative field lists). At plugin/APM scope: required fields present (`name`, `description`, non-empty body), `name` is kebab-case and matches the filename stem, no `FILL IN:` placeholders, no frontmatter field outside `name`/`description`/`model` (read the `apm-agent-allowlist` section of `references/field-inventory.md`). +If the scripts cannot run (Bash denied, python3 unavailable), perform checks manually. At project/user scope: counterpart file exists, required fields present (`name`, `description`, non-empty body), `name` is kebab-case, Copilot CLI `.agent.md` `name` must match filename stem (CC files are exempt — the CC platform does not require name to match filename), no `FILL IN:` placeholders, no CC-only fields in Copilot file, no Copilot-only fields in CC file (read `references/field-inventory.md` for the authoritative field lists). At plugin/APM scope: required fields present (`name`, `description`, non-empty body), `name` is kebab-case and matches the filename stem, no `FILL IN:` placeholders, no frontmatter field outside `name`/`description`/`model`/`source_keys` (read the `apm-agent-allowlist` section of `references/field-inventory.md`; `source_keys` carries provenance metadata, checked separately by `validate-provenance.sh` against `sources.md`). ## Step 2 — Qualitative checks diff --git a/plugins/kyberforge/skills/agent-author/SKILL.md b/plugins/kyberforge/skills/agent-author/SKILL.md index 3ba89ee..fa9b4bd 100644 --- a/plugins/kyberforge/skills/agent-author/SKILL.md +++ b/plugins/kyberforge/skills/agent-author/SKILL.md @@ -90,7 +90,7 @@ The script is file-by-file no-op — it skips any file that already exists. ### Step 2 — Fill in the agent file(s) -**At plugin/APM scope**, there is exactly one file: `/.apm/agents/.agent.md`. Frontmatter carries ONLY `name`, `description`, and optionally `model` — never `tools` or the other Claude-only fields listed in Gotchas (ADR-0016). Fill in `name`, `description`, `model`, and the system prompt body per the guidance below; the rest of this step's field-by-field guidance (tools, maxTurns, effort, memory, isolation, disallowedTools, skills, color, initialPrompt, background) is project/user scope only. Skip Step 3 and go to Step 4. +**At plugin/APM scope**, there is exactly one file: `/.apm/agents/.agent.md`. Frontmatter carries ONLY `name`, `description`, optionally `model`, and optionally `source_keys` (provenance metadata, not a runtime field — see the template) — never `tools` or the other Claude-only fields listed in Gotchas (ADR-0016). Fill in `name`, `description`, `model`, and the system prompt body per the guidance below; the rest of this step's field-by-field guidance (tools, maxTurns, effort, memory, isolation, disallowedTools, skills, color, initialPrompt, background) is project/user scope only. Skip Step 3 and go to Step 4. **At project/user scope**, continue below to fill in both provider files — this step covers the Claude Code file (`.md`); Step 3 covers the Copilot file. diff --git a/plugins/kyberforge/skills/agent-author/assets/README.md b/plugins/kyberforge/skills/agent-author/assets/README.md index f910298..5791841 100644 --- a/plugins/kyberforge/skills/agent-author/assets/README.md +++ b/plugins/kyberforge/skills/agent-author/assets/README.md @@ -6,4 +6,4 @@ Annotated agent definition templates copied by `scripts/new-agent.sh` when scaff - **`claude-code.md`** — Claude Code agent definition template (project/user scope). Includes all supported frontmatter fields (required and optional) with inline guidance comments and `FILL IN:` placeholders. - **`copilot.agent.md`** — Copilot CLI agent definition template (CLI format, project/user scope). Excludes cloud/IDE-only fields (`target`, `user-invocable`, `disable-model-invocation`, `mcp-servers`) and Claude Code-only fields. Uses Copilot tool aliases (`execute`, `read`, `edit`, `search`, `agent`, `web`). -- **`apm-agent.md`** — Vendor-neutral APM agent definition template (plugin/APM scope). Only `name`, `description`, and optional `model` in frontmatter — no `tools` and no Claude-only fields, since `apm compile` copies frontmatter verbatim to both the Claude Code and Copilot CLI targets with no per-target integrator (ADR-0016). +- **`apm-agent.md`** — Vendor-neutral APM agent definition template (plugin/APM scope). Only `name`, `description`, optional `model`, and optional `source_keys` (provenance metadata, not a runtime field) in frontmatter — no `tools` and no Claude-only fields, since `apm compile` copies frontmatter verbatim to both the Claude Code and Copilot CLI targets with no per-target integrator (ADR-0016). diff --git a/plugins/kyberforge/skills/agent-author/assets/templates/apm-agent.md b/plugins/kyberforge/skills/agent-author/assets/templates/apm-agent.md index 599c9e5..a56d197 100644 --- a/plugins/kyberforge/skills/agent-author/assets/templates/apm-agent.md +++ b/plugins/kyberforge/skills/agent-author/assets/templates/apm-agent.md @@ -7,7 +7,8 @@ incompatible vocabularies, and Claude-only fields (isolation, maxTurns, effort, memory, permissionMode) have no Copilot equivalent. A value correct for one harness is guaranteed wrong on the other, so this scope carries - ONLY the three fields below — full stop (see ADR-0016). + ONLY the fields below — full stop (see ADR-0016). `source_keys` is + provenance metadata, not a runtime field, and is exempt from that rule. Do NOT add: tools, isolation, maxTurns, effort, memory, permissionMode, disallowedTools, skills, color, initialPrompt, background, hooks, or diff --git a/plugins/kyberforge/skills/agent-author/references/deployment-modes.md b/plugins/kyberforge/skills/agent-author/references/deployment-modes.md index 826d2d0..aefeb91 100644 --- a/plugins/kyberforge/skills/agent-author/references/deployment-modes.md +++ b/plugins/kyberforge/skills/agent-author/references/deployment-modes.md @@ -24,7 +24,7 @@ When the same agent `name` appears at multiple scopes, **user scope wins over pr ## Plugin scope restrictions -Plugin/APM agents (`.apm/agents/.agent.md`) carry only `name`, `description`, and optionally `model` in frontmatter — full stop (see ADR-0016). `apm compile` copies this frontmatter verbatim to both the Claude Code and Copilot CLI compile targets with no per-target integrator: Claude's `tools:` (space-separated string) and Copilot's `tools:` (alias list) are incompatible vocabularies, and Claude-only fields have no Copilot equivalent, so any harness-specific value is guaranteed wrong on at least one target. +Plugin/APM agents (`.apm/agents/.agent.md`) carry only `name`, `description`, optionally `model`, and optionally `source_keys` (provenance metadata, not a runtime field — silently ignored by both harnesses) in frontmatter — full stop (see ADR-0016). `apm compile` copies this frontmatter verbatim to both the Claude Code and Copilot CLI compile targets with no per-target integrator: Claude's `tools:` (space-separated string) and Copilot's `tools:` (alias list) are incompatible vocabularies, and Claude-only fields have no Copilot equivalent, so any harness-specific value is guaranteed wrong on at least one target. This makes the old "silently ignored at plugin scope" framing moot. It's not that `hooks`, `mcpServers`, `permissionMode`, `tools`, `isolation`, `maxTurns`, `effort`, `memory`, `disallowedTools`, `skills`, `color`, `initialPrompt`, or `background` are merely ignored at this scope — they are never written to the file at all. Copy the agent to `.claude/agents/` (project scope) or `~/.claude/agents/` (user scope) to use any of them.