feat(kyberforge): enforce the ADR-0020 context contract for skills and agents
Skill name+description pairs are preloaded into every session, costing ~6,200 tokens across 39 skills before any skill is invoked. The authoring rules mandated that growth: skill-author:104 and description-quality.md:21 both required padding, while skill-author:102 (the deflating rule) had no FAIL condition behind it. Gates (blocking, no baseline file): - description 250 chars SUGGESTION / 400 FAIL, measured on the folded YAML value - body-only 600 words SUGGESTION / 900 FAIL, independent of the unchanged whole-file 2770-word / 500-line spec backstop - every boundary-clause routing target must resolve to a real skill or agent; catches skill-improve, neuledge-context and gitea-labels - agents take the description gates but deliberately no body gate; a test pins that absence Vale: DescriptionOpener widened to ^This\b, new CompositionNote rule banning architecture notes from descriptions. 10 hits, 0 false positives. Kyberforge's own four skills retrofitted: descriptions 3,364 -> 938 chars (-72%), bodies 8,306 -> 2,487 words (-70%), all via the apm-workflow dispatch pattern. Fixes the skill-improve dangling route and the agent-author misroute to manual review. Also fixes a pre-existing false positive where any line-initial 'read ' was flagged as interactive input, which had already caused two scripts to be rewritten around it. Refs: ADR-0020
This commit is contained in:
@@ -4,14 +4,52 @@ source_keys: []
|
||||
|
||||
# references/
|
||||
|
||||
## create.md
|
||||
|
||||
The create flow, loaded from SKILL.md Step 1 when no agent file exists at the target path.
|
||||
Covers: prerequisites, the scaffold script and its scope walk-up, what to fill in at every scope,
|
||||
and populating or deleting the package-root `sources.md`.
|
||||
|
||||
## improve.md
|
||||
|
||||
The improve flow, loaded from SKILL.md Step 1 when a file exists and at least one improvement
|
||||
signal is present. Covers: signal verification, partial-pair recovery, root-cause grouping,
|
||||
generalizing rather than patching, delegation over growth, and the ADR-0020 retrofit rule.
|
||||
|
||||
## contract.md
|
||||
|
||||
The description and body contract, loaded from SKILL.md Step 3 before any description is written
|
||||
or any body restructured. Covers: the three-part description shape, banned description content,
|
||||
boundary-target resolution, the 250/400 length tiers, the body role-instruction pattern, the
|
||||
delegation rule that replaces a body word gate, and the invocation axis.
|
||||
|
||||
## plugin-scope.md
|
||||
|
||||
Field rules and the pre-audit checklist for the single vendor-neutral `.apm/agents/<name>.agent.md`
|
||||
file. Loaded from SKILL.md Step 2 when the scaffold resolves plugin/APM scope.
|
||||
|
||||
## project-user-scope.md
|
||||
|
||||
Field rules and the pre-audit checklist for the Claude Code `.md` + Copilot `.agent.md` pair,
|
||||
including the two distinct Copilot formats. Loaded from SKILL.md Step 2 when the scaffold resolves
|
||||
project or user scope.
|
||||
|
||||
## deployment-modes.md
|
||||
|
||||
Agent scope hierarchy, precedence rules, and per-scope restrictions. Covers: which frontmatter fields a plugin/APM-scope agent may carry and the allowlist-vs-denylist shape rule that decides it (deferring to `agent-audit`'s `references/field-inventory.md` for the list itself), scoped identifiers for plugin subdirectory agents, cache isolation behaviour, and Copilot CLI path conventions. Loaded conditionally from SKILL.md when the destination is a plugin directory.
|
||||
Scope hierarchy and precedence, scoped identifiers for plugin subdirectory agents, cache isolation
|
||||
behaviour, and Copilot CLI path conventions. Loaded from SKILL.md Step 2 when precedence, paths or
|
||||
cache isolation matter to the run.
|
||||
|
||||
## scripts.md
|
||||
|
||||
Conventions for the `new-agent.sh` scaffold script and any future scripts added to this skill. Covers: what scripts should and should not do, file placement, error handling, template variable conventions, and the no-interactive-prompts rule.
|
||||
Conventions for the `new-agent.sh` scaffold script, the templates it copies, and any future script
|
||||
in this skill. Loaded from `create.md` Step 1 when the script or a template has to change. Covers:
|
||||
the no-interactive-prompts rule, structured output, idempotency, template variables, file
|
||||
placement, error messages, and the no-restated-field-roster rule that `tests/new-agent.bats`
|
||||
enforces.
|
||||
|
||||
## sources.md
|
||||
|
||||
Research provenance record for this skill. Lists the upstream research sources (claude-code-plugins and github-copilot-plugins research docs) that informed SKILL.md, the templates, and the deployment-modes reference. Used by `skill-audit` to validate the provenance chain.
|
||||
Research provenance record for this skill. Lists the upstream research sources
|
||||
(claude-code-plugins and github-copilot-plugins research docs) that informed SKILL.md and the
|
||||
reference files. Used by `skill-audit` to validate the provenance chain.
|
||||
|
||||
117
plugins/kyberforge/skills/agent-author/references/contract.md
Normal file
117
plugins/kyberforge/skills/agent-author/references/contract.md
Normal file
@@ -0,0 +1,117 @@
|
||||
---
|
||||
source_keys:
|
||||
- claude-code-subagents-docs
|
||||
- github-custom-agents-configuration
|
||||
---
|
||||
|
||||
# The agent description and body contract
|
||||
|
||||
House contract, set by ADR-0020. The counts and the boundary targets are enforced by
|
||||
`agent-audit`'s `scripts/validate.sh`; the prose patterns by the Vale styles it bundles; the
|
||||
judgment calls by its reference files.
|
||||
|
||||
## Why the budget exists
|
||||
|
||||
An agent's `name` and `description` is loaded into every session's context at startup, whether or
|
||||
not the agent is ever delegated to — the same cost a skill's description carries, so agents take
|
||||
the same numbers. The body is different: it is not loaded into the caller's conversation at all,
|
||||
it *becomes the system prompt of a fresh context* when the agent runs. That is why the body has no
|
||||
word gate here and a skill body has one.
|
||||
|
||||
## Description
|
||||
|
||||
A description carries exactly three things:
|
||||
|
||||
1. **Trigger clause** — when to delegate, imperative: "Use when …", never "This agent …". Describe
|
||||
the user's intent and the triggering condition, not the agent's internal mechanics.
|
||||
2. **At most one capability clause** — what it does, one clause, no enumeration. Be specific
|
||||
("reviews a diff for injected credentials", not "helps with security").
|
||||
3. **Boundary clause** — form: `Not <thing> -> <name>.` Add one only where a near-miss agent or
|
||||
skill could steal delegations.
|
||||
|
||||
Banned from a description; move it to the body or to `README.md`:
|
||||
|
||||
- Capability enumeration or feature lists
|
||||
- Per-scope emission mechanics — which files the author skill writes at which scope changes no
|
||||
delegation decision
|
||||
- Output-format detail ("Produces a compact findings report with Why and Fix per finding")
|
||||
- Composition or architecture notes ("composes X rather than duplicating Y", "cross-cutting")
|
||||
- Implementation detail ("Self-validates via a bundled deterministic script")
|
||||
- Restating the same trigger twice in two registers — a verb list, then the same verbs re-quoted
|
||||
as user phrasings. This is a FAIL, not a suggestion.
|
||||
|
||||
**Do not open with an action verb.** "Reviews…", "Analyzes…", "Generates…" was the old house rule
|
||||
and ADR-0020 deleted it: the opener is `Use when`, matching every skill in this corpus, so one
|
||||
router reads one shape.
|
||||
|
||||
**"Use proactively" is conditional.** Add it only where the runtime should delegate without the
|
||||
user naming the agent — an agent invoked by name does not need it, and it costs activations
|
||||
elsewhere when added by reflex. The same conditional governs indirect triggers ("even if the user
|
||||
doesn't say X"): add one only where the user's natural phrasing genuinely omits the domain word.
|
||||
|
||||
**Boundary targets must resolve.** The name after the arrow is checked against real skills under
|
||||
`plugins/*/.apm/skills/<name>/` and real agents under `plugins/*/.apm/agents/<name>.agent.md`. A
|
||||
target that does not exist sends the router nowhere. Verify it before writing it — do not invent a
|
||||
plausible sibling.
|
||||
|
||||
**Length.** 250 characters SUGGESTION, 400 characters FAIL, counting the frontmatter value only
|
||||
with YAML folding resolved. Treat 250 as the target: the SUGGESTION tier is what moves the corpus
|
||||
average, the FAIL tier only stops outliers.
|
||||
|
||||
## Body
|
||||
|
||||
Write the body as a direct role instruction, addressed to the agent:
|
||||
|
||||
````markdown
|
||||
You are a <role>. When invoked, <primary action>.
|
||||
|
||||
## Inputs
|
||||
<what the agent is given: files, context, parameters>
|
||||
|
||||
## Process
|
||||
<ordered steps; be explicit where ordering matters>
|
||||
|
||||
## Output
|
||||
<what it produces: format, location, structure>
|
||||
````
|
||||
|
||||
One job per agent. An agent covering two jobs gets delegated to for the wrong one.
|
||||
|
||||
**Delegation discipline replaces the word gate.** A plugin/APM agent is a single file with no
|
||||
sibling `references/` directory: it cannot disclose progressively to itself, so its only way to
|
||||
stay short is to *invoke* rather than *restate*. A body that transcribes a procedure a skill it
|
||||
can invoke already owns is an `agent-audit` FAIL, and the fix is one line — "invoke `<skill>`".
|
||||
|
||||
- Restating: "To commit, check the message against Conventional Commits: type, scope,
|
||||
description; header under 100 chars; …"
|
||||
- Delegating: "Author commits with `git-commits`."
|
||||
|
||||
The same holds for a procedure another agent owns. What belongs in the body is what no invocable
|
||||
skill covers: the agent's role, its boundaries, the order it works in, and the format it returns.
|
||||
|
||||
**State a read-only boundary in prose, not only in frontmatter.** `disallowedTools` denies the
|
||||
tools it names and nothing else — never `Bash`, which an agent with no `tools` field inherits — so
|
||||
an agent fenced only in frontmatter can still write through a shell redirect.
|
||||
|
||||
## Invocation axis
|
||||
|
||||
Decide before writing the description whether the agent is model-delegated (the runtime picks it)
|
||||
or reached only by name (`@agent-<name>`).
|
||||
|
||||
Only Copilot's cloud/IDE format expresses that in frontmatter: `disable-model-invocation: true`
|
||||
requires explicit invocation, and `user-invocable: false` hides an agent from manual invocation.
|
||||
Both live in `.github/copilot/agents/<name>.md` and are inert in the CLI format. Claude Code has
|
||||
no equivalent field, and neither does the vendor-neutral plugin/APM file, so at those scopes a
|
||||
name-invoked agent still needs a description precise enough not to steal delegations — the
|
||||
boundary clause is doing that work.
|
||||
|
||||
## One gate, two measurements
|
||||
|
||||
| Gate | SUGGESTION | FAIL | Counts |
|
||||
|---|---|---|---|
|
||||
| description | 250 chars | 400 chars | the `description:` value only |
|
||||
| body (Copilot limit) | 30,000 chars | — | the body only; content past it is truncated silently |
|
||||
|
||||
The 30,000-character Copilot ceiling is a runtime truncation limit, not a quality target, and it
|
||||
applies to a plugin/APM file too — that file compiles into a real Copilot agent downstream. An
|
||||
agent body long enough to approach it has a delegation defect, not a length problem.
|
||||
93
plugins/kyberforge/skills/agent-author/references/create.md
Normal file
93
plugins/kyberforge/skills/agent-author/references/create.md
Normal file
@@ -0,0 +1,93 @@
|
||||
---
|
||||
source_keys:
|
||||
- context7-websites-code-claude
|
||||
- claude-code-subagents-docs
|
||||
- github-plugins-creating
|
||||
---
|
||||
|
||||
# Creating a new agent
|
||||
|
||||
Return to `SKILL.md` Step 4 once Step 3 below is done — validation, the version bump and commit
|
||||
verification are shared with the improve flow and are not repeated here.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
Before touching the filesystem, confirm you have:
|
||||
|
||||
- [ ] Agent name (kebab-case, e.g. `code-reviewer`)
|
||||
- [ ] Root directory — a path inside a package for plugin/APM scope, a project root, or `~` for
|
||||
user scope
|
||||
- [ ] Agent purpose — one sentence describing the task this agent handles
|
||||
- [ ] Trigger condition — when should the runtime delegate to this agent?
|
||||
|
||||
If any are missing, stop and ask before proceeding.
|
||||
|
||||
`agent-audit` runs the validation in `SKILL.md` Step 4. It ships with the kyberforge plugin and
|
||||
is co-installed with this skill; if it is unavailable, stop and ask the user to install
|
||||
kyberforge before continuing.
|
||||
|
||||
Design for one job per agent. An agent covering two jobs is delegated to for the wrong one.
|
||||
|
||||
## Step 1 — Scaffold
|
||||
|
||||
```bash
|
||||
bash scripts/new-agent.sh <name> <root>
|
||||
```
|
||||
|
||||
Examples:
|
||||
|
||||
```bash
|
||||
bash scripts/new-agent.sh code-reviewer packages/my-package/ # plugin/APM scope if packages/my-package/apm.yml has a type: field
|
||||
bash scripts/new-agent.sh deploy-assistant .
|
||||
bash scripts/new-agent.sh security-reviewer ~
|
||||
```
|
||||
|
||||
The script resolves scope itself and prints which one it used and every path it wrote — read that
|
||||
output rather than predicting it. It walks up from `<root>` for the nearest ancestor `apm.yml`
|
||||
carrying a top-level `type:` field (`instructions`/`skill`/`hybrid`/`prompts`), which marks a
|
||||
package root and means plugin/APM scope. An `apm.yml` with no `type:` is a marketplace-only
|
||||
manifest: the walk skips it and keeps going. With no such manifest found, `<root>` being exactly
|
||||
`~` (checked directly, no walk-up) is user scope and anything else is project scope. A bare
|
||||
`plugin.json` no longer signals plugin scope — that path was replaced outright, not made
|
||||
dual-mode, and falls through to project scope.
|
||||
|
||||
The script is file-by-file no-op: it skips any file that already exists, so re-running it to
|
||||
complete a partial pair is safe.
|
||||
|
||||
If the script or a template under `assets/templates/` has to change to support this agent — a new
|
||||
scope, a new scaffolded field, different output — read `references/scripts.md` first. Its
|
||||
conventions are asserted by `tests/new-agent.bats`, and an edit that ignores them fails the suite.
|
||||
|
||||
## Step 2 — Fill in the file(s)
|
||||
|
||||
Take the scope the script reported and read the matching reference — `SKILL.md` Step 2 has the
|
||||
table. That file carries the field rules and the pre-audit checklist for this scope; the other one
|
||||
describes fields this run cannot use.
|
||||
|
||||
Every scaffolded file, at every scope:
|
||||
|
||||
1. Replace each `FILL IN:` placeholder.
|
||||
2. Delete every `<!-- ... -->` template comment from the frontmatter. `apm compile` copies plugin
|
||||
frontmatter verbatim and HTML comments are not valid YAML, so a leftover comment breaks the
|
||||
file downstream on both harnesses.
|
||||
3. Write the `description` against `references/contract.md` and the system prompt body against its
|
||||
Body section.
|
||||
|
||||
## Step 3 — Populate or delete `sources.md`
|
||||
|
||||
Plugin/APM scope only — skip at project and user scope, which have no package root to hold the
|
||||
file.
|
||||
|
||||
The scaffold writes a commented `sources.md` skeleton at the package root, alongside `apm.yml` and
|
||||
not inside `.apm/agents/`, so that tooling scanning that directory for agent definitions does not
|
||||
treat it as an agent missing its frontmatter (ADR-0010).
|
||||
|
||||
If a research `sources.md` is present in the conversation context, filter it to entries with
|
||||
`` `extracted` `` status, work out which agent file each one contributed to, and fill in the
|
||||
skeleton following the commented format already in the file. Paths in `Contributing files:` are
|
||||
relative to the package root. Each slug must match an H2 heading and must also appear in the
|
||||
`source_keys` list of every file named under its `Contributing files:`.
|
||||
|
||||
If no research sources are in context, delete `sources.md`.
|
||||
|
||||
Then return to `SKILL.md` Step 4.
|
||||
@@ -22,13 +22,14 @@ Agent definitions deploy at three scopes and behave differently at each. The sco
|
||||
|
||||
When the same agent `name` appears at multiple scopes, **user scope wins over project scope wins over plugin scope** in Claude Code. In Copilot CLI, repo-level agents override enterprise and org-level; home-directory (user) agents override repo-level on name collision.
|
||||
|
||||
## Plugin scope restrictions
|
||||
## Which fields exist where
|
||||
|
||||
Plugin/APM agents (`.apm/agents/<name>.agent.md`) carry only the fields in the `apm-agent-allowlist` section of `agent-audit`'s `references/field-inventory.md`. That section is the authoritative list — `agent-audit`'s `validate.sh` reads it from there as data, and it changes — so consult it rather than any restatement of it. `apm compile` copies this frontmatter verbatim to both the Claude Code and Copilot CLI compile targets with no per-target integrator, so a harness-specific value is guaranteed wrong on at least one target (ADR-0016).
|
||||
|
||||
**The rule is about a field's shape, not a fixed roster.** `tools` is an **allowlist** whose vocabulary differs per harness — Claude Code names its own tools, Copilot CLI uses aliases (`execute`/`read`/`edit`/`search`/`agent`/`web`) — so under verbatim copy one value is wrong on one target. It stays out. `disallowedTools` is a **denylist**, and denying by name has no such conflict: a name the other harness does not recognise denies nothing, so the worst case is that the fence is absent there, never that a capability is wrongly granted. That asymmetry is why the denylist is admitted where the allowlist is not (ADR-0016's 2026-08-14 amendment). Claude Code honours it for plugin subagents — `docs/research/docs/claude-code-plugins/agent-definition.md:99` names the three fields plugin agents silently ignore (`hooks`, `mcpServers`, `permissionMode`) and `disallowedTools` is not among them. It is a partial fence: it denies only the tools it names, not `Bash`, which a plugin-scope agent with no `tools` inherits — so state read-only intent in the body too.
|
||||
|
||||
This makes the old "silently ignored at plugin scope" framing moot for the excluded fields. It's not that `hooks`, `mcpServers`, `permissionMode`, `tools`, `isolation`, `maxTurns`, `effort`, `memory`, `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.
|
||||
Field rules are per scope and live with the scope: `references/plugin-scope.md` for the single
|
||||
vendor-neutral file, `references/project-user-scope.md` for the Claude Code / Copilot pair. Read
|
||||
one, not both. The short version is that plugin/APM frontmatter is an allowlist read from
|
||||
`agent-audit`'s `references/field-inventory.md`, narrow because `apm compile` copies frontmatter
|
||||
verbatim to every target (ADR-0016), while project and user scope carry the full per-provider
|
||||
field sets.
|
||||
|
||||
## Scoped identifiers (Claude Code plugin agents only)
|
||||
|
||||
|
||||
76
plugins/kyberforge/skills/agent-author/references/improve.md
Normal file
76
plugins/kyberforge/skills/agent-author/references/improve.md
Normal file
@@ -0,0 +1,76 @@
|
||||
---
|
||||
source_keys:
|
||||
- claude-code-subagents-docs
|
||||
---
|
||||
|
||||
# Improving an existing agent
|
||||
|
||||
Return to `SKILL.md` Step 4 once Step 4 below is done — validation, the version bump and commit
|
||||
verification are shared with the create flow and are not repeated here.
|
||||
|
||||
## Step 1 — Verify inputs
|
||||
|
||||
Confirm the agent file (or, at project and user scope, the pair) exists and that at least one
|
||||
improvement signal is present in the conversation or in a referenced file.
|
||||
|
||||
If no signals are present, stop: "This skill applies existing signals to an agent. For a blind
|
||||
review, run `agent-audit` instead."
|
||||
|
||||
`agent-audit` runs the validation in `SKILL.md` Step 4 and is co-installed with this skill; if
|
||||
it is unavailable, stop and ask the user to install the kyberforge plugin before continuing.
|
||||
|
||||
**Partial pair — project and user scope only.** If one provider file exists and the other does
|
||||
not, scaffold the missing one with `bash scripts/new-agent.sh <name> <root>` (file-by-file no-op)
|
||||
and continue. Plugin/APM scope is a single file and has no partial state.
|
||||
|
||||
## Step 2 — Gather and group signals
|
||||
|
||||
Read the current file(s), then collect every signal from the conversation and from any path the
|
||||
user referenced.
|
||||
|
||||
Group signals by **root cause**, not by symptom. Patching per symptom is the default failure mode:
|
||||
three complaints often trace to one missing instruction. Ask: "What single gap in this agent
|
||||
causes this cluster?" One root cause, one fix.
|
||||
|
||||
```text
|
||||
Example:
|
||||
- User feedback: the agent keeps trying to push to the remote
|
||||
- Session context: no scope boundary in the system prompt
|
||||
→ Root cause: the system prompt has no git scope constraint → fix: add an explicit boundary
|
||||
```
|
||||
|
||||
## Step 3 — Announce planned changes
|
||||
|
||||
Before editing, state which root causes were identified, what evidence supports each, and which
|
||||
files will change. Then proceed — edits are reversible via git, so no approval checkpoint is
|
||||
needed.
|
||||
|
||||
## Step 4 — Apply changes
|
||||
|
||||
Edit whichever file the signals point to.
|
||||
|
||||
**Generalize, do not patch.** Fix the underlying gap, not the one example that failed. A fix
|
||||
scoped to the cases you have seen overfits and performs worse on new input.
|
||||
|
||||
**Delegate rather than grow.** An agent body has no word ceiling, but a body that restates a
|
||||
procedure a skill it can invoke already owns is an `agent-audit` FAIL. When a signal reports a
|
||||
missing procedure, check first whether an installed skill owns it and name that skill instead of
|
||||
transcribing it. See `references/contract.md`.
|
||||
|
||||
**Explain the why.** Reasoning-based instructions outperform rigid directives. A rule written in
|
||||
all caps (ALWAYS/NEVER) is usually better reframed as why the behaviour matters, so the agent can
|
||||
apply judgment at the edges.
|
||||
|
||||
**Retrofit before extending.** Any agent predating ADR-0020 has to meet the description contract
|
||||
before any other edit lands — the gates are hot and carry no baseline file, so a one-line fix to a
|
||||
non-compliant agent cannot be committed until its description meets `references/contract.md`.
|
||||
Treat that retrofit as part of the same change, not a follow-up.
|
||||
|
||||
**Re-check the scope rules.** Read the reference for the resolved scope (`SKILL.md` Step 2) and
|
||||
confirm the edit introduced no field that scope forbids, and dropped no `disallowedTools` fence
|
||||
that was already there.
|
||||
|
||||
If the edit adds or removes research-sourced content, update `source_keys` in the edited file and
|
||||
the matching `sources.md` entry — the create flow's Step 3 has the rules.
|
||||
|
||||
Then return to `SKILL.md` Step 4.
|
||||
@@ -0,0 +1,67 @@
|
||||
---
|
||||
source_keys:
|
||||
- context7-websites-code-claude
|
||||
- claude-code-plugins-docs
|
||||
---
|
||||
|
||||
# Plugin/APM scope — the single vendor-neutral file
|
||||
|
||||
One file, no counterpart: `<package-root>/.apm/agents/<name>.agent.md`. `apm compile` emits it to
|
||||
both the Claude Code and the Copilot CLI target. The `.agent.md` extension here is convention, not
|
||||
a Copilot marker — the file is vendor-neutral.
|
||||
|
||||
## Frontmatter
|
||||
|
||||
The permitted keys are the `apm-agent-allowlist` section of `agent-audit`'s
|
||||
`references/field-inventory.md`. Read them from there as data — that section is the single source
|
||||
of truth, `agent-audit`'s `validate.sh` parses it at load time, and it changes. Any restatement of
|
||||
the roster, here or in a template or in script output, goes stale one step further out than the
|
||||
list itself.
|
||||
|
||||
- `name` — kebab-case, must equal the filename stem, unique within the scope.
|
||||
- `description` — write it against `references/contract.md`.
|
||||
- Everything else — check the allowlist section before adding a key. A key outside it fails the
|
||||
audit.
|
||||
|
||||
**Why the list is narrow.** `apm compile` copies frontmatter verbatim to every target with no
|
||||
per-target integrator, so a harness-specific value is wrong on at least one of them (ADR-0016).
|
||||
The rule is about a field's *shape*, not a fixed roster:
|
||||
|
||||
- `tools` is an **allowlist** whose vocabulary differs per harness — Claude Code names its own
|
||||
tools, Copilot CLI uses aliases (`execute`/`read`/`edit`/`search`/`agent`/`web`) — so one value
|
||||
is wrong on one target. It stays out. Omitting it means inherit-all-tools on both, which is
|
||||
never wrong.
|
||||
- `disallowedTools` is a **denylist**, and denying by name cannot fail that way: a name the other
|
||||
harness does not recognise denies nothing, so the worst case is a missing fence, never a wrongly
|
||||
granted capability. That asymmetry is the whole exception (ADR-0016's 2026-08-14 amendment).
|
||||
Claude Code honours it for plugin subagents; the three fields plugin agents do silently ignore
|
||||
are `hooks`, `mcpServers` and `permissionMode`, and this is not one of them. Copilot's handling
|
||||
of the key is unconfirmed, which ADR-0016 accepts as a stated risk.
|
||||
- The Claude-only knobs (`isolation`, `maxTurns`, `effort`, `memory`, `permissionMode`, `skills`,
|
||||
`color`, `initialPrompt`, `background`, `hooks`, `mcpServers`) have no Copilot equivalent and
|
||||
are never written to this file at all. "Silently ignored at plugin scope" is the wrong framing:
|
||||
they are absent, not tolerated. To use any of them, copy the agent to `.claude/agents/`
|
||||
(project scope) or `~/.claude/agents/` (user scope).
|
||||
|
||||
Write `disallowedTools` on every read-only plugin-scope agent — and say the agent is read-only in
|
||||
the body as well, because the fence does not cover the inherited `Bash` tool.
|
||||
|
||||
`source_keys` is provenance metadata, not a runtime field: both harnesses ignore it. Add it only
|
||||
when research sources informed the agent, with slugs matching H2 headings in the package root's
|
||||
`sources.md`.
|
||||
|
||||
## Body
|
||||
|
||||
Follow the Body section of `references/contract.md`: role instruction, one job, and delegation
|
||||
to installed skills instead of transcribed procedure.
|
||||
|
||||
## Before invoking `agent-audit`
|
||||
|
||||
- [ ] `name` kebab-case, matching the filename stem, unique in scope
|
||||
- [ ] `description` written to `references/contract.md`
|
||||
- [ ] Every frontmatter key present in the `apm-agent-allowlist` section — in particular no `tools`
|
||||
- [ ] No `FILL IN:` placeholder and no `<!-- ... -->` template comment anywhere in the file
|
||||
- [ ] System prompt body non-empty, and a read-only agent says so in prose as well as in
|
||||
`disallowedTools`
|
||||
|
||||
Then return to the flow reference you came from.
|
||||
@@ -0,0 +1,106 @@
|
||||
---
|
||||
source_keys:
|
||||
- claude-code-subagents-docs
|
||||
- context7-github-en-copilot
|
||||
- github-custom-agents-configuration
|
||||
- github-cli-plugin-reference
|
||||
---
|
||||
|
||||
# Project and user scope — the Claude Code / Copilot pair
|
||||
|
||||
Two files per agent, written in one pass and kept in step: a Claude Code `.md` and a Copilot CLI
|
||||
`.agent.md`. The system prompt body is the same in both — the agent's task does not change with
|
||||
the provider. The frontmatter is not.
|
||||
|
||||
| Scope | Claude Code | Copilot CLI |
|
||||
|---|---|---|
|
||||
| Project | `.claude/agents/<name>.md` | `.github/agents/<name>.agent.md` |
|
||||
| User | `~/.claude/agents/<name>.md` | `~/.copilot/agents/<name>.agent.md` |
|
||||
|
||||
## Claude Code file
|
||||
|
||||
**`name`** — lowercase letters and hyphens only, unique within the scope. Claude Code discards a
|
||||
duplicate silently.
|
||||
|
||||
**`description`** — write it against `references/contract.md`. It is the primary signal for
|
||||
autonomous delegation.
|
||||
|
||||
**`tools`** — an allowlist; omit it to inherit every tool from the parent. Use `Agent(type1,type2)`
|
||||
to restrict which subagent types this agent may spawn, and omit `Agent` entirely to stop it
|
||||
spawning any. Five tools reach no subagent whatever this field says — `AskUserQuestion`,
|
||||
`EnterPlanMode`, `ExitPlanMode`, `ScheduleWakeup` and `WaitForMcpServers` — so listing one buys
|
||||
nothing. The single exception is `ExitPlanMode`, available when the parent session runs
|
||||
`permissionMode: plan`.
|
||||
|
||||
**`disallowedTools`** — a denylist, applied before `tools` and taking precedence over it. Supports
|
||||
`mcp__<server>`, `mcp__<server>__*` and `mcp__*` globs. Both a YAML list and a delimited string
|
||||
are accepted; this repo writes the comma-separated string form (`disallowedTools: Edit, Write,
|
||||
NotebookEdit`) — match it.
|
||||
|
||||
**`model`** — set it when the agent needs a different capability tier (`haiku` for fast lookups,
|
||||
`opus` for deep reasoning). Resolution order is `CLAUDE_CODE_SUBAGENT_MODEL` → the per-invocation
|
||||
parameter → this field → the main session model, so the frontmatter value is a low-priority
|
||||
default rather than a guarantee.
|
||||
|
||||
Optional fields worth considering, none of which exist at plugin/APM scope:
|
||||
|
||||
- `maxTurns` — cap agentic turns on a bounded task, to stop a runaway
|
||||
- `effort` — `low` for a single lookup, `high` or above for multi-file analysis; omit to inherit
|
||||
- `memory` — `user`, `project` or `local`; only when cross-session state is genuinely needed
|
||||
- `isolation: worktree` — only when the agent modifies files and needs an isolated copy
|
||||
- `skills` — skill names preloaded at agent startup; unrelated to the `source_keys` metadata field
|
||||
- `color` — the UI tile colour (`red`, `blue`, `green`, `yellow`, `purple`, `orange`, `pink`,
|
||||
`cyan`)
|
||||
- `background` — `true` forces background execution
|
||||
- `initialPrompt` — auto-submitted as the first turn when the agent activates as the main session
|
||||
thread; set it only for a main-thread agent, never for a subagent
|
||||
|
||||
`hooks`, `mcpServers` and `permissionMode` are honoured at these two scopes and nowhere else — a
|
||||
plugin agent carrying them is ignored silently.
|
||||
|
||||
A subdirectory under `agents/` does not affect the agent's name at these scopes; it does at plugin
|
||||
scope, which is one reason `references/deployment-modes.md` recommends keeping agents flat.
|
||||
|
||||
## Copilot file
|
||||
|
||||
Two Copilot formats exist, with different paths and different field sets. Pick one:
|
||||
|
||||
**CLI format** — what the scaffold writes.
|
||||
|
||||
- Path: `.github/agents/<name>.agent.md` (project) or `~/.copilot/agents/<name>.agent.md` (user)
|
||||
- The `.agent.md` extension is mandatory: Copilot CLI does not pick up a plain `.md` file in
|
||||
`agents/`, and fails silently rather than reporting it
|
||||
- Fields: `name` (required, must equal the filename stem), `description` (required), `tools`
|
||||
(optional)
|
||||
- `tools` uses Copilot aliases, not Claude tool names: `execute` (shell), `read`, `edit`,
|
||||
`search`, `agent`, `web`; MCP tools as `server-name/tool-name` or `server-name/*`
|
||||
|
||||
**Cloud/IDE format** — for Copilot Chat in VS Code or on GitHub.com.
|
||||
|
||||
- Path: `.github/copilot/agents/<name>.md` — a plain `.md`, in a different directory
|
||||
- Adds `target` (`vscode`, `github-copilot`, or omit for both), `user-invocable`,
|
||||
`disable-model-invocation` and `mcp-servers` (processed by the cloud runtime, ignored in VS
|
||||
Code). These four are inert in the CLI format — do not write them there
|
||||
- This is the only format that can express the invocation axis in frontmatter; see the Invocation
|
||||
axis section of `references/contract.md`
|
||||
|
||||
Both formats truncate a body past **30,000 characters** silently.
|
||||
|
||||
Copilot has no `permissionMode`, `maxTurns`, `isolation`, `memory`, `effort`, `hooks` or
|
||||
`mcpServers`. Never let those cross over from the Claude Code file.
|
||||
|
||||
## Before invoking `agent-audit`
|
||||
|
||||
Both files:
|
||||
|
||||
- [ ] `name` present and kebab-case; `description` written to `references/contract.md`
|
||||
- [ ] System prompt body present, non-empty and equivalent across the pair
|
||||
- [ ] No `FILL IN:` placeholder and no `<!-- ... -->` template comment left
|
||||
|
||||
Copilot file only:
|
||||
|
||||
- [ ] Extension is `.agent.md` (CLI format), and `name` matches the filename stem
|
||||
- [ ] No Claude Code-only field present
|
||||
- [ ] Body under 30,000 characters
|
||||
|
||||
Then return to the flow reference you came from.
|
||||
@@ -19,7 +19,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/deployment-modes.md
|
||||
- **Contributing files:** SKILL.md, references/create.md, references/deployment-modes.md, references/plugin-scope.md
|
||||
- **Status:** `extracted`
|
||||
|
||||
## claude-code-plugins-docs
|
||||
@@ -27,7 +27,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/deployment-modes.md
|
||||
- **Contributing files:** SKILL.md, references/deployment-modes.md, references/plugin-scope.md
|
||||
- **Status:** `extracted`
|
||||
|
||||
## claude-code-subagents-docs
|
||||
@@ -35,7 +35,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/deployment-modes.md
|
||||
- **Contributing files:** SKILL.md, references/create.md, references/improve.md, references/contract.md, references/deployment-modes.md, references/project-user-scope.md
|
||||
- **Status:** `extracted`
|
||||
|
||||
## context7-github-en-copilot
|
||||
@@ -43,7 +43,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/deployment-modes.md
|
||||
- **Contributing files:** references/deployment-modes.md, references/project-user-scope.md
|
||||
- **Status:** `extracted`
|
||||
|
||||
## github-custom-agents-configuration
|
||||
@@ -51,7 +51,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/deployment-modes.md
|
||||
- **Contributing files:** references/contract.md, references/deployment-modes.md, references/project-user-scope.md
|
||||
- **Status:** `extracted`
|
||||
|
||||
## github-cli-plugin-reference
|
||||
@@ -59,7 +59,7 @@ source_keys:
|
||||
- **URL:** https://docs.github.com/en/copilot/reference/copilot-cli-reference/cli-plugin-reference
|
||||
- **Research doc:** plugins/kyberforge/docs/research/docs/github-copilot-plugins/sources.md
|
||||
- **Description:** Full CLI plugin reference — plugin.json schema, marketplace.json schema, all CLI commands and flags, install specification formats, loading precedence, env vars, LSP config
|
||||
- **Contributing files:** SKILL.md, references/deployment-modes.md
|
||||
- **Contributing files:** references/deployment-modes.md, references/project-user-scope.md
|
||||
- **Status:** `extracted`
|
||||
|
||||
## github-plugins-creating
|
||||
@@ -67,7 +67,7 @@ source_keys:
|
||||
- **URL:** https://docs.github.com/en/copilot/how-tos/copilot-cli/customize-copilot/plugins-creating
|
||||
- **Research doc:** plugins/kyberforge/docs/research/docs/github-copilot-plugins/sources.md
|
||||
- **Description:** How-to for creating Copilot CLI plugins — plugin structure, agent and skill authoring, hooks format, MCP config, development lifecycle
|
||||
- **Contributing files:** SKILL.md
|
||||
- **Contributing files:** references/create.md
|
||||
- **Status:** `extracted`
|
||||
|
||||
## github-plugins-finding-installing
|
||||
|
||||
Reference in New Issue
Block a user