Skip to content

Deploy instructions to .claude/rules/ for Claude Code#527

Merged
danielmeppiel merged 5 commits into
mainfrom
copilot/fix-apm-install-deployment-claude
Apr 2, 2026
Merged

Deploy instructions to .claude/rules/ for Claude Code#527
danielmeppiel merged 5 commits into
mainfrom
copilot/fix-apm-install-deployment-claude

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented Apr 1, 2026

Description

apm install deploys .instructions.md files to .github/instructions/ (Copilot) and .cursor/rules/ (Cursor) but silently skips .claude/rules/ for Claude Code. This adds Claude Code as an instruction deployment target, converting applyTo: frontmatter to Claude's native paths: format per the Claude Code rules spec.

Mapping: python.instructions.md with applyTo: "**/*.py" deploys as .claude/rules/python.md with:

---
paths:
  - "**/*.py"
---

Instructions without applyTo: become unconditional rules (no frontmatter).

Changes:

  • targets.py: Add "instructions" primitive to Claude target — PrimitiveMapping("rules", ".md", "claude_rules")
  • instruction_integrator.py: Add _convert_to_claude_rules() (applyTo:paths: YAML list), copy_instruction_claude(), legacy wrappers. Generalize filename rename and content-transform dispatch to be format-driven rather than Cursor-specific. Legacy glob fallback is disabled for Claude rules (legacy_pattern = None) to avoid deleting user-authored .md files under .claude/rules/
  • base_integrator.py: Add instructions_clauderules_claude bucket alias for partition routing
  • install.py: Extend log label to show rule(s) for claude_rules format
  • Docs: Add .claude/rules/*.md to Claude primitives table in ide-tool-integration.md

No new dependencies. Uninstall/sync works automatically via the existing target-driven API — sync_for_target() and partition_managed_files() pick up the new primitive from KNOWN_TARGETS.

Type of change

  • Bug fix
  • New feature
  • Documentation
  • Maintenance / refactor

Testing

  • Tested locally
  • All existing tests pass
  • Added tests for new functionality (if applicable)

22 new tests: TestConvertToClaudeRules (7 — frontmatter conversion edge cases), TestClaudeRulesIntegration (11 — deploy, rename, collision, managed-file overwrite), TestClaudeRulesSyncIntegration (4 — manifest removal, legacy fallback preservation of user files). Updated test_data_driven_dispatch.py with bucket key parity, alias, and partition routing assertions.

Copilot AI and others added 2 commits April 1, 2026 12:55
Add Claude Code as an instruction deployment target. `apm install` now
deploys .instructions.md files to .claude/rules/*.md when a .claude/
directory exists, converting applyTo: frontmatter to Claude's native
paths: format.

Agent-Logs-Url: https://github.com/microsoft/apm/sessions/13cf381a-2289-43c1-8769-19ff7c42f188

Co-authored-by: danielmeppiel <51440732+danielmeppiel@users.noreply.github.com>
Copilot AI changed the title [WIP] Fix apm install deployment to .claude/rules directory Deploy instructions to .claude/rules/ for Claude Code Apr 1, 2026
Copilot AI requested a review from danielmeppiel April 1, 2026 13:38
@danielmeppiel danielmeppiel marked this pull request as ready for review April 2, 2026 05:26
Copilot AI review requested due to automatic review settings April 2, 2026 05:26
Copy link
Copy Markdown
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

Adds Claude Code as an apm install instructions deployment target by deploying .instructions.md as Claude rules under .claude/rules/, including a frontmatter conversion from applyTo: to Claude’s paths: format. This aligns instruction deployment behavior across Copilot/Cursor/Claude using the existing target-driven integrator architecture.

Changes:

  • Add instructions primitive mapping for the Claude target (.claude/rules/*.md, format_id="claude_rules").
  • Implement Claude rules content conversion + integrate/sync wrappers in InstructionIntegrator, and route managed files via a new bucket alias.
  • Add tests, documentation updates, and a changelog entry.

Reviewed changes

Copilot reviewed 8 out of 9 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
tests/unit/integration/test_instruction_integrator.py Adds unit + integration tests for Claude rules conversion, deploy, collisions, and sync behavior.
tests/unit/integration/test_data_driven_dispatch.py Extends bucket parity/alias assertions and verifies .claude/rules/ partition routing.
src/apm_cli/integration/targets.py Registers Claude instructions deployment mapping (rules, .md, claude_rules).
src/apm_cli/integration/instruction_integrator.py Adds claude_rules transform/copy + dispatch, and updates sync legacy pattern selection.
src/apm_cli/integration/base_integrator.py Adds bucket alias instructions_claude -> rules_claude for partition routing.
src/apm_cli/commands/install.py Updates install log label to show rule(s) for claude_rules (and cursor rules).
docs/src/content/docs/integrations/ide-tool-integration.md Documents .claude/rules/*.md as the destination for instructions (rules).
CHANGELOG.md Adds an Unreleased entry describing Claude rules deployment support.

Comment thread src/apm_cli/integration/instruction_integrator.py Outdated
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
@danielmeppiel
Copy link
Copy Markdown
Collaborator

@copilot fix the tests - certainly we broke it by accepting the PR review comment (read it) which I judged legit. See if there is more to it than that.

…estion

The accepted PR review changed legacy_pattern from "*.md" to None for
Claude rules to avoid deleting user-authored .md files. Update the test
to verify the new intentional behavior: legacy fallback preserves files
when managed_files is None.

Agent-Logs-Url: https://github.com/microsoft/apm/sessions/aa461ca4-e9eb-4adf-bef4-b8118f4780d4

Co-authored-by: danielmeppiel <51440732+danielmeppiel@users.noreply.github.com>
Copy link
Copy Markdown
Contributor Author

Copilot AI commented Apr 2, 2026

@copilot fix the tests - certainly we broke it by accepting the PR review comment (read it) which I judged legit. See if there is more to it than that.

Fixed in 0f6201a. The accepted review suggestion changed legacy_pattern from "*.md" to None for Claude rules (to avoid deleting user-authored .md files under .claude/rules/). The test test_sync_legacy_fallback_removes_all_md was asserting the old behavior. Renamed it to test_sync_legacy_fallback_preserves_user_files and updated assertions to verify the new intentional behavior: when managed_files=None, no files are removed and user-authored rules are preserved. All 535 integration tests pass.

@danielmeppiel danielmeppiel merged commit 79e5995 into main Apr 2, 2026
13 checks passed
@danielmeppiel danielmeppiel deleted the copilot/fix-apm-install-deployment-claude branch April 2, 2026 12:06
danielmeppiel added a commit that referenced this pull request Apr 2, 2026
Introduce TargetProfile.for_scope() and resolve_targets() so scope
resolution happens exactly once -- no parameter threading, no caller
responsibility.  This supersedes PRs #536 and #537 and folds in #527.

Scope resolution:
- for_scope(user_scope) returns a frozen copy with root_dir resolved
  and unsupported primitives filtered out
- resolve_targets() is the single entry point combining detection,
  scope resolution, and primitive filtering
- Integrators read target.root_dir directly -- always correct
- partition_managed_files() uses longest-prefix-match routing,
  fixing .config/opencode/ multi-level root paths
- validate_deploy_path() derives prefixes from resolved targets
- Uninstall Phase 2 re-integration uses resolved targets,
  eliminating wrong-path deployment bug

Claude Code instructions (#527):
- Deploy .instructions.md to .claude/rules/*.md with applyTo: to
  paths: frontmatter conversion
- Legacy glob disabled for .claude/rules/ to protect user .md files
- 22 new tests for conversion, integration, sync, and partition

Copilot CLI user-scope fix (#536):
- Add instructions to unsupported_user_primitives (per official docs)
- Fix resolve_dependencies to use apm_dir at user scope

Fixes #530

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@danielmeppiel
Copy link
Copy Markdown
Collaborator

Folded into #542 which adds this feature alongside the scope-resolution architecture refactor. All 22 tests and the full implementation are included. Thank you!

danielmeppiel added a commit that referenced this pull request Apr 2, 2026
Introduce TargetProfile.for_scope() and resolve_targets() so scope
resolution happens exactly once -- no parameter threading, no caller
responsibility.  This supersedes PRs #536 and #537 and folds in #527.

Scope resolution:
- for_scope(user_scope) returns a frozen copy with root_dir resolved
  and unsupported primitives filtered out
- resolve_targets() is the single entry point combining detection,
  scope resolution, and primitive filtering
- Integrators read target.root_dir directly -- always correct
- partition_managed_files() uses longest-prefix-match routing,
  fixing .config/opencode/ multi-level root paths
- validate_deploy_path() derives prefixes from resolved targets
- Uninstall Phase 2 re-integration uses resolved targets,
  eliminating wrong-path deployment bug

Claude Code instructions (#527):
- Deploy .instructions.md to .claude/rules/*.md with applyTo: to
  paths: frontmatter conversion
- Legacy glob disabled for .claude/rules/ to protect user .md files
- 22 new tests for conversion, integration, sync, and partition

Copilot CLI user-scope fix (#536):
- Add instructions to unsupported_user_primitives (per official docs)
- Fix resolve_dependencies to use apm_dir at user scope

Fixes #530

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
danielmeppiel added a commit that referenced this pull request Apr 2, 2026
* fix: scope-resolved target profiles + Claude Code instructions

Introduce TargetProfile.for_scope() and resolve_targets() so scope
resolution happens exactly once -- no parameter threading, no caller
responsibility.  This supersedes PRs #536 and #537 and folds in #527.

Scope resolution:
- for_scope(user_scope) returns a frozen copy with root_dir resolved
  and unsupported primitives filtered out
- resolve_targets() is the single entry point combining detection,
  scope resolution, and primitive filtering
- Integrators read target.root_dir directly -- always correct
- partition_managed_files() uses longest-prefix-match routing,
  fixing .config/opencode/ multi-level root paths
- validate_deploy_path() derives prefixes from resolved targets
- Uninstall Phase 2 re-integration uses resolved targets,
  eliminating wrong-path deployment bug

Claude Code instructions (#527):
- Deploy .instructions.md to .claude/rules/*.md with applyTo: to
  paths: frontmatter conversion
- Legacy glob disabled for .claude/rules/ to protect user .md files
- 22 new tests for conversion, integration, sync, and partition

Copilot CLI user-scope fix (#536):
- Add instructions to unsupported_user_primitives (per official docs)
- Fix resolve_dependencies to use apm_dir at user scope

Fixes #530

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix: address PR review -- trie routing, legacy prefix cleanup, CHANGELOG refs

- Replace O(M*P) sorted-prefix scan with O(depth) trie lookup in
  partition_managed_files (reviewer comment 1)
- Use default KNOWN_TARGETS for uninstall partition so legacy
  deployed_files from buggy user-scope installs are still bucketed
  and cleaned up (reviewer comment 2)
- Remove targets= from orphan validate_deploy_path so legacy
  .github/ paths from old user-scope installs can be cleaned up
  (reviewer comment 3)
- Fix CHANGELOG PR references to use #542 (reviewer comment 4)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix: dynamic skill sync prefixes + uninstall Phase 2 targets

Fix #538: pass resolved targets to skill_integrator.integrate_package_skill()
in uninstall Phase 2 so user-scope re-integration deploys to .copilot/skills/
not .github/skills/. Add auto_create guard to copy_skill_to_target().

Fix #539: refactor sync_integration() to derive skill prefixes dynamically
from targets instead of hardcoded .github/skills/, .claude/skills/, etc.
User-scope paths like .copilot/skills/ and .config/opencode/skills/ are
now handled correctly. Pass resolved targets from uninstall engine.

9 new tests covering resolved-target routing, auto_create guards,
user-scope manifest removal, legacy cleanup, and cross-tool guards.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
sergio-sisternes-epam pushed a commit that referenced this pull request May 19, 2026
* Initial plan

* Initial plan for Claude Code .claude/rules/ instruction deployment

Agent-Logs-Url: https://github.com/microsoft/apm/sessions/13cf381a-2289-43c1-8769-19ff7c42f188

Co-authored-by: danielmeppiel <51440732+danielmeppiel@users.noreply.github.com>

* Deploy instructions to .claude/rules/ for Claude Code

Add Claude Code as an instruction deployment target. `apm install` now
deploys .instructions.md files to .claude/rules/*.md when a .claude/
directory exists, converting applyTo: frontmatter to Claude's native
paths: format.

Agent-Logs-Url: https://github.com/microsoft/apm/sessions/13cf381a-2289-43c1-8769-19ff7c42f188

Co-authored-by: danielmeppiel <51440732+danielmeppiel@users.noreply.github.com>

* Update src/apm_cli/integration/instruction_integrator.py

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Fix test for Claude rules legacy fallback after accepting review suggestion

The accepted PR review changed legacy_pattern from "*.md" to None for
Claude rules to avoid deleting user-authored .md files. Update the test
to verify the new intentional behavior: legacy fallback preserves files
when managed_files is None.

Agent-Logs-Url: https://github.com/microsoft/apm/sessions/aa461ca4-e9eb-4adf-bef4-b8118f4780d4

Co-authored-by: danielmeppiel <51440732+danielmeppiel@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: danielmeppiel <51440732+danielmeppiel@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
sergio-sisternes-epam pushed a commit that referenced this pull request May 19, 2026
* fix: scope-resolved target profiles + Claude Code instructions

Introduce TargetProfile.for_scope() and resolve_targets() so scope
resolution happens exactly once -- no parameter threading, no caller
responsibility.  This supersedes PRs #536 and #537 and folds in #527.

Scope resolution:
- for_scope(user_scope) returns a frozen copy with root_dir resolved
  and unsupported primitives filtered out
- resolve_targets() is the single entry point combining detection,
  scope resolution, and primitive filtering
- Integrators read target.root_dir directly -- always correct
- partition_managed_files() uses longest-prefix-match routing,
  fixing .config/opencode/ multi-level root paths
- validate_deploy_path() derives prefixes from resolved targets
- Uninstall Phase 2 re-integration uses resolved targets,
  eliminating wrong-path deployment bug

Claude Code instructions (#527):
- Deploy .instructions.md to .claude/rules/*.md with applyTo: to
  paths: frontmatter conversion
- Legacy glob disabled for .claude/rules/ to protect user .md files
- 22 new tests for conversion, integration, sync, and partition

Copilot CLI user-scope fix (#536):
- Add instructions to unsupported_user_primitives (per official docs)
- Fix resolve_dependencies to use apm_dir at user scope

Fixes #530

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix: address PR review -- trie routing, legacy prefix cleanup, CHANGELOG refs

- Replace O(M*P) sorted-prefix scan with O(depth) trie lookup in
  partition_managed_files (reviewer comment 1)
- Use default KNOWN_TARGETS for uninstall partition so legacy
  deployed_files from buggy user-scope installs are still bucketed
  and cleaned up (reviewer comment 2)
- Remove targets= from orphan validate_deploy_path so legacy
  .github/ paths from old user-scope installs can be cleaned up
  (reviewer comment 3)
- Fix CHANGELOG PR references to use #542 (reviewer comment 4)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix: dynamic skill sync prefixes + uninstall Phase 2 targets

Fix #538: pass resolved targets to skill_integrator.integrate_package_skill()
in uninstall Phase 2 so user-scope re-integration deploys to .copilot/skills/
not .github/skills/. Add auto_create guard to copy_skill_to_target().

Fix #539: refactor sync_integration() to derive skill prefixes dynamically
from targets instead of hardcoded .github/skills/, .claude/skills/, etc.
User-scope paths like .copilot/skills/ and .config/opencode/skills/ are
now handled correctly. Pass resolved targets from uninstall engine.

9 new tests covering resolved-target routing, auto_create guards,
user-scope manifest removal, legacy cleanup, and cross-tool guards.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
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.

[BUG] apm install does not deploy instructions to .claude/rules/

3 participants