fix(kyberforge): bridge apm content to Claude Code's flat plugin discovery
Claude Code's (and Copilot's) native plugin installer has zero awareness of .apm/ nesting -- it convention-scans only flat skills/, agents/, commands/, hooks.json at each plugin's root. Confirmed via strings on the installed claude binary and live installs of git@holocron/gitea@holocron/kyberforge@ holocron, all reporting Skills(0) Agents(0) Hooks(0) post ADR-0015's apm conversion. Root cause (apm_cli/core/plugin_manifest.py): apm's plugin.json compiler deliberately strips skills/agents/commands keys, assuming the host already auto-discovers those convention directories -- it has no model of .apm/ being host-visible at all. Separately, apm's own bundle exporter (apm_cli/bundle/plugin_exporter.py, behind `apm pack --format plugin`) implements the correct .apm/ -> flat mapping, but only ever targeted build/<name>-<version>/, a path nothing in marketplace.json's source: points at. scripts/sync-plugin-content.sh wraps that bundle exporter and copies its agents/, skills/, commands/, instructions/, extensions/, and merged hooks.json back into each plugin's own root as a second tracked compiled-output category -- same governance status as .claude-plugin/plugin.json: generated from .apm/, never hand-edited. tests/ subdirectories are excluded from the mirror (dev fixtures, not host-visible runtime content; several hardcode a relative repo-root walk-up sized for the .apm/-nested depth, which breaks when duplicated one level shallower). Applied for real across all 6 plugins and verified two ways: `claude plugin validate --strict` passes on every real plugin directory, and a live `claude --plugin-dir <path> -p "list skills/agents"` behavioral test confirms content is now actually discovered. Also, from the same issue #90 review round: - scripts/check-manifests.sh pointed at each plugin's root-level plugin.json (checking skills/hooks/mcpServers/agents pointer fields) -- that file was a stale near-duplicate of .claude-plugin/plugin.json nothing else read or wrote, now deleted across all 6 plugins. check-manifests.sh is rewritten to validate .claude-plugin/plugin.json instead, and drops the pointer-field checks entirely (nothing to check -- those fields are correctly absent by design). Content-presence drift is now check-plugin-content-sync's job, a new pre-push hook wired in .pre-commit-config.yaml. docs/adr/0017 records the root cause and decision in full, including two rejected alternatives (patching plugin.json's path fields directly -- apm's compiler strips them on every run; pointing marketplace.json at apm pack's build/ output -- a version-suffixed non-source directory nothing can install from without an extra build step). ADR-0015 and CONTEXT.md are updated to point at it. Refs: #90
This commit is contained in:
@@ -0,0 +1,54 @@
|
||||
---
|
||||
<!-- Vendor-neutral APM agent definition (plugin/APM scope).
|
||||
Path: <package-root>/.apm/agents/<name>.agent.md — one file, no counterpart.
|
||||
`apm compile` copies this frontmatter verbatim to BOTH the Claude Code and
|
||||
Copilot CLI targets — there is no per-target field integrator. Claude's
|
||||
`tools:` (space-separated string) and Copilot's `tools:` (alias list) are
|
||||
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 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
|
||||
mcpServers. Omitting `tools` means inherit-all-tools on both harnesses,
|
||||
which is never wrong.
|
||||
|
||||
Fill in all FILL IN: placeholders. Delete template comments before shipping. -->
|
||||
|
||||
name: AGENT_NAME
|
||||
<!-- Required. Lowercase letters and hyphens only. Must be unique within the scope. -->
|
||||
|
||||
description: FILL IN: Action-first description of what this agent does and when to invoke it.
|
||||
<!-- Required. The primary signal for autonomous delegation.
|
||||
Start with a verb: "Reviews...", "Analyzes...", "Generates..."
|
||||
Be specific about the triggering condition and expertise domain.
|
||||
Example: "Reviews pull request diffs for security issues. Use proactively after code changes." -->
|
||||
|
||||
<!-- model: sonnet
|
||||
Optional. Aliases: sonnet, opus, haiku, fable. Or full model ID.
|
||||
Omit to inherit the runtime default on whichever harness compiles this file. -->
|
||||
|
||||
<!-- source_keys:
|
||||
- slug-name
|
||||
Development-only. Add when research sources informed this agent (slugs must match
|
||||
sources.md at the package root — same directory as apm.yml).
|
||||
Omit when no research was used. Not a runtime field — silently ignored by both harnesses. -->
|
||||
---
|
||||
|
||||
FILL IN: System prompt body. Write as a direct role instruction.
|
||||
|
||||
You are a FILL IN: role description. When invoked, FILL IN: primary action.
|
||||
|
||||
## Inputs
|
||||
|
||||
FILL IN: What inputs does this agent expect? (files, context, parameters)
|
||||
|
||||
## Process
|
||||
|
||||
FILL IN: Steps the agent takes. Be specific about ordering if it matters.
|
||||
|
||||
## Output
|
||||
|
||||
FILL IN: What does the agent produce? Format, location, structure.
|
||||
@@ -0,0 +1,86 @@
|
||||
---
|
||||
<!-- Claude Code agent definition
|
||||
Fill in all FILL IN: placeholders. Remove or uncomment optional fields as needed.
|
||||
Delete template comments before shipping. -->
|
||||
|
||||
name: AGENT_NAME
|
||||
<!-- Required. Lowercase letters and hyphens only. Must be unique within the scope.
|
||||
Duplicate names are silently discarded — no warning is emitted. -->
|
||||
|
||||
description: FILL IN: Action-first description of what this agent does and when to invoke it.
|
||||
<!-- Required. The primary signal for autonomous delegation.
|
||||
Start with a verb: "Reviews...", "Analyzes...", "Generates..."
|
||||
Include "Use proactively" to trigger automatic invocation.
|
||||
Be specific about the triggering condition and domain.
|
||||
Example: "Reviews pull request diffs for security issues. Use proactively after code changes." -->
|
||||
|
||||
<!-- tools: Read Bash Grep
|
||||
Optional. Space-separated allowlist. Omit to inherit all tools from parent.
|
||||
Use Agent(type1,type2) to restrict which subagent types this agent can spawn.
|
||||
Omit Agent entirely to prevent this agent from spawning subagents.
|
||||
Never available to subagents regardless of tools field:
|
||||
AskUserQuestion, EnterPlanMode, ExitPlanMode, ScheduleWakeup, WaitForMcpServers
|
||||
Exception: ExitPlanMode IS available when parent session runs in permissionMode: plan -->
|
||||
|
||||
<!-- model: sonnet
|
||||
Optional. Aliases: sonnet, opus, haiku, fable. Or full model ID.
|
||||
Omit to inherit from the main session.
|
||||
Resolution order: CLAUDE_CODE_SUBAGENT_MODEL env var → per-invocation param → this field → session model. -->
|
||||
|
||||
<!-- effort: medium
|
||||
Optional. low / medium / high / xhigh / max. Overrides session effort level for this agent. -->
|
||||
|
||||
<!-- maxTurns: 20
|
||||
Optional. Integer cap on agentic turns. Prevents runaway on bounded tasks. -->
|
||||
|
||||
<!-- memory: project
|
||||
Optional. user / project / local. Enables cross-session MEMORY.md (first 200 lines loaded at startup).
|
||||
Auto-enables Read/Write/Edit tools. -->
|
||||
|
||||
<!-- isolation: worktree
|
||||
Optional. Set to "worktree" to run in an isolated temporary git worktree.
|
||||
Auto-cleaned if no changes are made. -->
|
||||
|
||||
<!-- color: blue
|
||||
Optional. UI color: red, blue, green, yellow, purple, orange, pink, cyan. -->
|
||||
|
||||
<!-- background: false
|
||||
Optional. Set true to force background execution. -->
|
||||
|
||||
<!-- disallowedTools: mcp__filesystem__write_file
|
||||
Optional. Space-separated denylist, applied before the tools allowlist.
|
||||
Supports mcp__* glob patterns (e.g. mcp__filesystem__* to block all filesystem tools). -->
|
||||
|
||||
<!-- skills:
|
||||
- skill-name
|
||||
Optional. Skill names preloaded into this agent's context at startup.
|
||||
Different from the source_keys metadata field (which is provenance-only). -->
|
||||
|
||||
<!-- initialPrompt: "Start by reading the README."
|
||||
Optional. Auto-submitted as the first turn when this agent activates as the main session thread.
|
||||
Only set when this agent is intended for main-thread (not subagent) activation. -->
|
||||
|
||||
<!-- source_keys:
|
||||
- slug-name
|
||||
Development-only. Add when research sources informed this agent (slugs must match sources.md at the plugin root).
|
||||
Omit when no research was used. Not a runtime field — silently ignored by Claude Code. -->
|
||||
|
||||
<!-- NOTE: hooks, mcpServers, and permissionMode are silently ignored for plugin agents.
|
||||
Those fields only work in .claude/agents/ or ~/.claude/agents/. -->
|
||||
---
|
||||
|
||||
FILL IN: System prompt body. Write as a direct role instruction.
|
||||
|
||||
You are a FILL IN: role description. When invoked, FILL IN: primary action.
|
||||
|
||||
## Inputs
|
||||
|
||||
FILL IN: What inputs does this agent expect? (files, context, parameters)
|
||||
|
||||
## Process
|
||||
|
||||
FILL IN: Steps the agent takes. Be specific about ordering if it matters.
|
||||
|
||||
## Output
|
||||
|
||||
FILL IN: What does the agent produce? Format, location, structure.
|
||||
@@ -0,0 +1,59 @@
|
||||
---
|
||||
<!-- GitHub Copilot CLI agent definition (CLI format — path: .github/agents/<name>.agent.md)
|
||||
File extension MUST be .agent.md — a plain .md file is not picked up by Copilot CLI.
|
||||
Fill in all FILL IN: placeholders. Remove or uncomment optional fields as needed.
|
||||
Body length limit: 30,000 characters — content beyond this is silently truncated.
|
||||
Delete template comments before shipping.
|
||||
|
||||
NOTE: This template is for the CLI format. The cloud/IDE format (path: .github/copilot/agents/<name>.md,
|
||||
extension: .md) supports additional fields: target, user-invocable, disable-model-invocation, mcp-servers.
|
||||
Do not add those fields here — they are silently ignored by the CLI runtime. -->
|
||||
|
||||
name: AGENT_NAME
|
||||
<!-- Required. Kebab-case identifier. Home-directory version wins on name collision. -->
|
||||
|
||||
description: FILL IN: Action-first description of what this agent does and when to invoke it.
|
||||
<!-- Required. Used by the runtime for automatic agent selection — quality matters.
|
||||
Start with a verb: "Reviews...", "Analyzes...", "Generates..."
|
||||
Example: "Reviews pull request diffs for security issues." -->
|
||||
|
||||
<!-- tools: ["read", "search", "edit"]
|
||||
Optional. Array of tool names. Omit = all available tools. [] = no tools.
|
||||
Copilot tool aliases (use these, not Claude Code names):
|
||||
execute — run shell commands (aliases: shell, Bash, powershell)
|
||||
read — read file contents (aliases: Read, NotebookRead)
|
||||
edit — modify files (aliases: Edit, MultiEdit, Write, NotebookEdit)
|
||||
search — search files (aliases: Grep, Glob)
|
||||
agent — invoke sub-agents (aliases: custom-agent, Task)
|
||||
web — web search and fetch (aliases: WebSearch, WebFetch)
|
||||
For MCP tools: "server-name/tool-name" or "server-name/*" -->
|
||||
|
||||
<!-- model: claude-sonnet-4-5
|
||||
Optional. Model to run this agent on.
|
||||
Cloud/IDE-only fields (target, user-invocable, disable-model-invocation, mcp-servers)
|
||||
are not valid in this CLI format — use the .github/copilot/agents/<name>.md path for those. -->
|
||||
|
||||
<!-- source_keys:
|
||||
- slug-name
|
||||
Development-only. Add when research sources informed this agent (slugs must match sources.md at the plugin root).
|
||||
Omit when no research was used. Not a Copilot runtime field — silently ignored. -->
|
||||
|
||||
<!-- DO NOT include these Claude Code-only fields:
|
||||
maxTurns, isolation, memory, permissionMode, effort, hooks, mcpServers -->
|
||||
---
|
||||
|
||||
FILL IN: System prompt body. Should match the Claude Code version — the agent's task is the same across providers.
|
||||
|
||||
You are a FILL IN: role description. When invoked, FILL IN: primary action.
|
||||
|
||||
## Inputs
|
||||
|
||||
FILL IN: What inputs does this agent expect? (files, context, parameters)
|
||||
|
||||
## Process
|
||||
|
||||
FILL IN: Steps the agent takes. Be specific about ordering if it matters.
|
||||
|
||||
## Output
|
||||
|
||||
FILL IN: What does the agent produce? Format, location, structure.
|
||||
Reference in New Issue
Block a user