fix(compile): include ADO three-level CLAUDE.md dependencies - #2952
Open
VyrnSynx (vyrnsynx) wants to merge 1 commit into
Open
fix(compile): include ADO three-level CLAUDE.md dependencies#2952VyrnSynx (vyrnsynx) wants to merge 1 commit into
VyrnSynx (vyrnsynx) wants to merge 1 commit into
Conversation
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
VyrnSynx (vyrnsynx)
requested review from
Daniel Meppiel (danielmeppiel) and
Sergio Sisternes (sergio-sisternes-epam)
as code owners
September 11, 2026 18:48
Contributor
There was a problem hiding this comment.
🟡 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
--rootis paired withapm install --root, the manifest remains undersource_dirbutapm.lock.yamlandapm_modulesare underbase_dir. A manifest with any direct dependency makesdeclarednon-empty, so this condition skips the base-root lookup; consequently transitive lockfile paths are never considered and theirCLAUDE.mdfiles (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/repopackage from a GitHubowner/repo/docs/CLAUDE.mdfile when the GitHub package has no rootCLAUDE.md. In that layout, this loop emits@apm_modules/owner/repo/docs/CLAUDE.mdeven 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-levelCLAUDE.mdas 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.mdfiles, but the PR updates no Starlight page. Add a concise note to the compile documentation describing that Claude imports declared dependency-rootCLAUDE.mdfiles, including the ADOorg/project/repolayout, 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") |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
apm compile --target claudeonly walkedapm_modules/{owner}/{package}/CLAUDE.md, so Azure DevOps packages materialized atapm_modules/{org}/{project}/{repo}never appeared in the Dependencies@importlist (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. NestedCLAUDE.mdunder a GitHub package that already has a package-root file is not imported.Fixes #2951
Type of change
Testing
uv run --extra dev pytest tests/unit/compilation/test_claude_formatter.pySpec conformance (OpenAPM v0.1)
docs/src/content/docs/specs/openapm-v0.1.mdupdated(new/changed
<a id="req-XXX"></a>anchor + prose + Appendix Crow).
docs/src/content/docs/specs/manifests/openapm-v0.1.requirements.ymlupdated.
@pytest.mark.req("req-XXX")test undertests/spec_conformance/added or extended.CONFORMANCE.{md,json}regenerated viauv run --extra dev python -m tests.spec_conformance.gen_statementand committed.