Skip to content

fix: plugin agents not deployed due to directory nesting bug#214

Merged
danielmeppiel merged 3 commits intomainfrom
fix/plugin-agent-nesting
Mar 9, 2026
Merged

fix: plugin agents not deployed due to directory nesting bug#214
danielmeppiel merged 3 commits intomainfrom
fix/plugin-agent-nesting

Conversation

@danielmeppiel
Copy link
Collaborator

Problem

When plugin.json declares agents as a custom list (e.g. "agents": ["./agents"]), _map_plugin_artifacts preserved the directory name, creating .apm/agents/agents/ instead of .apm/agents/. This caused agent files to be silently dropped during integration — they never reached the AgentIntegrator.

Real-world impact: The context-engineering plugin from github/awesome-copilot has a context-architect.md agent that was never deployed to .github/agents/.

Root Cause

Unlike skills (which are named directories containing SKILL.md), agents are flat files — each .md is one agent. The custom-list branch in _map_plugin_artifacts was using copytree(d, target / d.name) which nests the directory, but should use copytree(d, target) to merge contents directly — matching how the non-custom (default) path already worked.

Changes

Fix 1 — plugin_parser.py (root cause)

Agents custom-list branch now merges directory contents into .apm/agents/ directly instead of preserving the directory name as a subdirectory.

Fix 2 — agent_integrator.py (defensive)

Changed glob()rglob() in find_agent_files so agents in subdirectories are still discovered even if nesting occurs from other sources.

Fix 3 — plugin.py (consistency)

Plugin.from_path only discovered *.agent.md files. Now also discovers plain .md files (excluding known non-agent names like README.md), matching what AgentIntegrator.find_agent_files already does.

Tests

  • Updated test_mixed_files_and_dirs to assert flattened (correct) behavior
  • Added test_custom_agents_dir_list_flattens_contents — regression test for the exact context-engineering plugin pattern
  • Added test_find_agent_files_discovers_nested_subdirectories — validates rglob resilience
  • Added test_get_target_filename_plain_md — confirms .md.agent.md rename for .github/agents/

Verification

  • All 1729 tests pass, 0 regressions
  • End-to-end: apm install in sample project now correctly deploys context-architect.agent.md to .github/agents/

When plugin.json declares agents as a custom list (e.g. "agents": ["./agents"]),
_map_plugin_artifacts preserved the directory name, creating .apm/agents/agents/
instead of .apm/agents/. This caused agent files to be silently dropped during
integration.

Root cause: unlike skills (named directories), agents are flat files — the custom
list branch should merge directory contents directly, not nest by dir name.

Also:
- Harden find_agent_files with rglob for subdirectory resilience
- Fix Plugin.from_path to discover plain .md agents (not just .agent.md)

Fixes agent deployment for plugins like awesome-copilot/context-engineering.
Copilot AI review requested due to automatic review settings March 9, 2026 19:57
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Fixes plugin agent deployment when plugin.json uses a custom agents directory list (e.g. "agents": ["./agents"]), ensuring mapped agent files end up where AgentIntegrator can discover and integrate them.

Changes:

  • Flatten agent directory contents into .apm/agents/ in plugin artifact mapping to avoid .apm/agents/agents/ nesting.
  • Make AgentIntegrator.find_agent_files() resilient to nested agent directories by switching glob()rglob().
  • Expand plugin agent discovery to include plain .md files under agents/ (not only *.agent.md), plus add/adjust regression tests.

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
src/apm_cli/deps/plugin_parser.py Fixes agent mapping so custom agent directories are merged directly into .apm/agents/.
src/apm_cli/integration/agent_integrator.py Switches to recursive discovery for .apm/agents to avoid silent drops when nesting occurs.
src/apm_cli/models/plugin.py Broadens Plugin.from_path() agent discovery to include plain .md files.
tests/unit/test_plugin_parser.py Updates/extends mapping tests to assert flattened agents behavior and prevent regression.
tests/unit/integration/test_agent_integrator.py Adds tests for nested agent discovery and plain .md.agent.md target naming.

Comment on lines 169 to 173
# Map agents/
# Unlike skills (which are named directories containing SKILL.md), agents
# are flat files — each .md is one agent. So we always merge directory
# contents directly into .apm/agents/ (no nesting by dir name).
agent_sources = _resolve_sources("agents", "agents")
Copy link

Copilot AI Mar 9, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Docs appear to be out of sync with this change: docs/plugins.md currently states that when a custom component path array contains directories, each directory is preserved as a named subdirectory. With this update agents directories are always flattened into .apm/agents/ (no agents/<dir-name>/ nesting). Please update docs/plugins.md to clarify that agents are an exception (flattened), while skills keep the named-subdir behavior.

Copilot uses AI. Check for mistakes.
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch — fixed in afb01d6. docs/plugins.md now clarifies that agents are flattened into .apm/agents/ while skills keep the named-subdirectory behavior.

All .md files in an agents/ directory should be respected regardless
of filename. The directory semantics already imply the file type.
@danielmeppiel danielmeppiel merged commit 7ac999d into main Mar 9, 2026
12 checks passed
@danielmeppiel danielmeppiel deleted the fix/plugin-agent-nesting branch March 9, 2026 20:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants