Skip to content

fix(compile): include ADO three-level CLAUDE.md dependencies - #2952

Open
VyrnSynx (vyrnsynx) wants to merge 1 commit into
microsoft:mainfrom
vyrnsynx:fix/claude-compile-ado-three-level-deps
Open

fix(compile): include ADO three-level CLAUDE.md dependencies#2952
VyrnSynx (vyrnsynx) wants to merge 1 commit into
microsoft:mainfrom
vyrnsynx:fix/claude-compile-ado-three-level-deps

Conversation

@vyrnsynx

Copy link
Copy Markdown

Description

apm compile --target claude only walked apm_modules/{owner}/{package}/CLAUDE.md, so Azure DevOps packages materialized at apm_modules/{org}/{project}/{repo} never appeared in the Dependencies @import list (silent miss).

This change prefers declared install roots from apm.yml / lockfile declaration order (already aware of GitHub vs ADO vs virtual paths), and falls back to a shallow two- and three-level filesystem scan for fixture layouts without declarations. Nested CLAUDE.md under a GitHub package that already has a package-root file is not imported.

Fixes #2951

Type of change

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

Testing

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

uv run --extra dev pytest tests/unit/compilation/test_claude_formatter.py

Spec conformance (OpenAPM v0.1)

  • Spec edit: docs/src/content/docs/specs/openapm-v0.1.md updated
    (new/changed <a id="req-XXX"></a> anchor + prose + Appendix C
    row).
  • Manifest edit: docs/src/content/docs/specs/manifests/openapm-v0.1.requirements.yml
    updated.
  • Test edit: a @pytest.mark.req("req-XXX") test under
    tests/spec_conformance/ added or extended.
  • CONFORMANCE.{md,json} regenerated via
    uv run --extra dev python -m tests.spec_conformance.gen_statement
    and committed.
  • N/A -- this PR does not change OpenAPM-observable behaviour.

Claude compile previously walked only apm_modules/owner/package, so
Azure DevOps installs at org/project/repo were omitted from the
Dependencies @import list. Prefer declared install roots, with a
shallow two- and three-level filesystem fallback for fixtures.

Fixes microsoft#2951

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟡 Changes recommended

Unresolved dependency-root handling and fallback-scan issues must be addressed before approval.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Pull request overview

Fixes Claude compilation to import dependency CLAUDE.md files from Azure DevOps three-level paths.

Changes:

  • Uses manifest and lockfile declaration order for dependency roots.
  • Adds two- and three-level filesystem fallback scanning.
  • Adds regression tests and a changelog entry.
File summaries
File Summary Review notes
tests/unit/compilation/test_claude_formatter.py Covers ADO and mixed dependency layouts. Add coverage for declared ADO dependencies and redirected-root handling.
src/apm_cli/compilation/claude_formatter.py Collects dependency imports from declarations and filesystem layouts. Moderate issues remain with redirected-root lockfile paths and ambiguous depth-three fallback scanning; nits request declaration-path tests and compile documentation.
CHANGELOG.md Records the bug fix. No direct comments.
Review details

Suppressed comments (3)

src/apm_cli/compilation/claude_formatter.py:256

  • When --root is paired with apm install --root, the manifest remains under source_dir but apm.lock.yaml and apm_modules are under base_dir. A manifest with any direct dependency makes declared non-empty, so this condition skips the base-root lookup; consequently transitive lockfile paths are never considered and their CLAUDE.md files (including three-level ADO packages) are omitted. Merge the deploy-root lockfile paths with the source manifest paths through the canonical declaration-order helper, and add a redirected-root regression test.
        declared = get_dependency_declaration_order(str(self.source_dir))
        if not declared and self.base_dir.resolve() != self.source_dir.resolve():
            declared = get_dependency_declaration_order(str(self.base_dir))

src/apm_cli/compilation/claude_formatter.py:286

  • The fallback cannot distinguish an ADO org/project/repo package from a GitHub owner/repo/docs/CLAUDE.md file when the GitHub package has no root CLAUDE.md. In that layout, this loop emits @apm_modules/owner/repo/docs/CLAUDE.md even though it is not a package root, so the generated context imports arbitrary nested documentation. Keep the depth-3 heuristic behind declaration/materialization metadata (or another package-root marker) rather than treating every third-level CLAUDE.md as an ADO package.
                for repo_dir in mid_dir.iterdir():
                    if not repo_dir.is_dir() or repo_dir.name.startswith("."):
                        continue
                    ado_claude = repo_dir / "CLAUDE.md"
                    if ado_claude.is_file():
                        dependencies.append(
                            f"@apm_modules/{owner_dir.name}/{mid_dir.name}/{repo_dir.name}/CLAUDE.md"

src/apm_cli/compilation/claude_formatter.py:240

  • This changes the user-visible contents of generated CLAUDE.md files, but the PR updates no Starlight page. Add a concise note to the compile documentation describing that Claude imports declared dependency-root CLAUDE.md files, including the ADO org/project/repo layout, so the documented compile behavior stays aligned with the implementation.
        Prefers installed package roots from ``apm.yml`` / lockfile declaration
        order (GitHub ``owner/repo``, Azure DevOps ``org/project/repo``, and
        virtual paths). Falls back to a shallow filesystem scan that understands
        both two-level and three-level layouts when no declarations are present
        (e.g. unit fixtures).
  • Files reviewed: 3/3 changed files
  • Comments generated: 1
  • Review effort level: Lite

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment on lines +258 to +261
if declared:
for rel in declared:
if (modules_root / rel / "CLAUDE.md").is_file():
dependencies.append(f"@apm_modules/{rel}/CLAUDE.md")
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] Claude compilation omits CLAUDE.md from three-level dependencies

2 participants