Is this a bug? Yes — companion to #1138; the inverse-direction gap that #1138's dedup fix left open.
Summary
#1138 (PR #1146) made apm compile --target claude skip creating a CLAUDE.md when instructions are already deployed to .claude/rules/ (the files_written == 0 and skip_instructions guard at agents_compiler.py:785-791). That works for a clean checkout.
But it only suppresses creation. If a CLAUDE.md already exists on disk — authored in an earlier APM version, or generated before .claude/rules/ was populated — APM never removes it, on plain apm compile or apm compile --clean. The stale file lingers indefinitely, and because it predates the dedup it still contains the full instruction content that now also lives in .claude/rules/ — exactly the duplicate-context problem #1138 set out to eliminate.
Both targets share a version of this gap, but the Claude path is worse off: the AGENTS.md path at least has orphan-detection infrastructure (DistributedAgentsCompiler._find_orphaned_agents_files / _cleanup_orphaned_files), even though it doesn't currently catch the analogous redundant-file case (see the sibling AGENTS.md issue). The CLAUDE.md path has no cleanup logic at all — grep finds no rglob("CLAUDE.md"), no orphan check, no unlink anywhere in the Claude compile path.
Environment
- APM version: 0.19.0
- OS: macOS
Steps to reproduce
mkdir -p /tmp/apm-claude-stale/.apm/instructions && cd /tmp/apm-claude-stale
cat > apm.yml <<'EOF'
name: test-claude-stale
version: 1.0.0
targets: [claude]
EOF
cat > .apm/instructions/global.instructions.md <<'EOF'
---
description: A global instruction
---
This is global guidance.
EOF
# 1. Compile BEFORE .claude/rules/ exists -> CLAUDE.md is written (the "upgrade path" starting state)
apm compile --target claude
cat CLAUDE.md # full instructions present
# 2. Simulate `apm install` populating .claude/rules/, then recompile
mkdir -p .claude/rules
echo "This is global guidance." > .claude/rules/global.md
apm compile --target claude
cat CLAUDE.md # STILL THERE, still full instructions -> now duplicated with .claude/rules/
# 3. --clean does not help either
apm compile --target claude --clean
test -f CLAUDE.md && echo "CLAUDE.md STILL present after --clean"
Expected behavior
When instruction dedup fires (.claude/rules/ already holds the instructions), apm compile --clean should remove a pre-existing, APM-generated CLAUDE.md that would now be redundant — gated on the APM-generated marker (<!-- Generated by APM CLI -->, claude_formatter.py:26) so a hand-authored CLAUDE.md is never deleted. Plain apm compile should remain non-destructive (it already correctly avoids creating a new one).
The sibling AGENTS.md issue asks for the same --clean behavior on that path; fixing both gives consistent, predictable cleanup across targets. (Neither path does this today.)
Actual behavior
- Step 1 writes a full
CLAUDE.md (expected for that starting state).
- Step 2: dedup fires and logs "Instructions already in .claude/rules/ — omitting from CLAUDE.md", but the existing
CLAUDE.md is left untouched — now duplicating .claude/rules/.
- Step 3:
apm compile --clean does not remove it. There is no CLAUDE.md cleanup path to invoke.
Root cause
_compile_claude_md (agents_compiler.py:617-857) only guards new writes (line 785: if files_written == 0 and skip_instructions: → log and write nothing). It never inspects or removes an existing on-disk CLAUDE.md.
- There is no Claude analog to
DistributedAgentsCompiler._find_orphaned_agents_files / _cleanup_orphaned_files (distributed_compiler.py:643, 722). The clean_orphaned / --clean flow is wired only into the AGENTS.md distributed compiler, so it never reaches the Claude target. (Note: even that AGENTS.md flow only removes files no longer in the generated set — it does not currently remove regenerated-but-redundant files; that is the subject of the sibling AGENTS.md issue.)
Suggested fix
In _compile_claude_md, when skip_instructions is true and a root CLAUDE.md already exists:
- If
config.clean_orphaned (--clean) is set and the existing file carries the APM-generated marker (claude_formatter.py:26), remove it and log the removal.
- If the existing file lacks the marker (hand-authored), leave it and emit the same "hand-authored file will not be overwritten" warning the Copilot-root path already uses (
agents_compiler.py:1131-1138).
- Plain
apm compile (no --clean): unchanged — suppress creation only, never delete. Optionally surface a hint that a stale CLAUDE.md exists and --clean would remove it.
Acceptance criteria
Related
Is this a bug? Yes — companion to #1138; the inverse-direction gap that #1138's dedup fix left open.
Summary
#1138 (PR #1146) made
apm compile --target claudeskip creating aCLAUDE.mdwhen instructions are already deployed to.claude/rules/(thefiles_written == 0 and skip_instructionsguard atagents_compiler.py:785-791). That works for a clean checkout.But it only suppresses creation. If a
CLAUDE.mdalready exists on disk — authored in an earlier APM version, or generated before.claude/rules/was populated — APM never removes it, on plainapm compileorapm compile --clean. The stale file lingers indefinitely, and because it predates the dedup it still contains the full instruction content that now also lives in.claude/rules/— exactly the duplicate-context problem #1138 set out to eliminate.Both targets share a version of this gap, but the Claude path is worse off: the AGENTS.md path at least has orphan-detection infrastructure (
DistributedAgentsCompiler._find_orphaned_agents_files/_cleanup_orphaned_files), even though it doesn't currently catch the analogous redundant-file case (see the sibling AGENTS.md issue). The CLAUDE.md path has no cleanup logic at all —grepfinds norglob("CLAUDE.md"), no orphan check, nounlinkanywhere in the Claude compile path.Environment
Steps to reproduce
Expected behavior
When instruction dedup fires (
.claude/rules/already holds the instructions),apm compile --cleanshould remove a pre-existing, APM-generatedCLAUDE.mdthat would now be redundant — gated on the APM-generated marker (<!-- Generated by APM CLI -->,claude_formatter.py:26) so a hand-authoredCLAUDE.mdis never deleted. Plainapm compileshould remain non-destructive (it already correctly avoids creating a new one).The sibling AGENTS.md issue asks for the same
--cleanbehavior on that path; fixing both gives consistent, predictable cleanup across targets. (Neither path does this today.)Actual behavior
CLAUDE.md(expected for that starting state).CLAUDE.mdis left untouched — now duplicating.claude/rules/.apm compile --cleandoes not remove it. There is no CLAUDE.md cleanup path to invoke.Root cause
_compile_claude_md(agents_compiler.py:617-857) only guards new writes (line 785:if files_written == 0 and skip_instructions:→ log and write nothing). It never inspects or removes an existing on-diskCLAUDE.md.DistributedAgentsCompiler._find_orphaned_agents_files/_cleanup_orphaned_files(distributed_compiler.py:643,722). Theclean_orphaned/--cleanflow is wired only into the AGENTS.md distributed compiler, so it never reaches the Claude target. (Note: even that AGENTS.md flow only removes files no longer in the generated set — it does not currently remove regenerated-but-redundant files; that is the subject of the sibling AGENTS.md issue.)Suggested fix
In
_compile_claude_md, whenskip_instructionsis true and a rootCLAUDE.mdalready exists:config.clean_orphaned(--clean) is set and the existing file carries the APM-generated marker (claude_formatter.py:26), remove it and log the removal.agents_compiler.py:1131-1138).apm compile(no--clean): unchanged — suppress creation only, never delete. Optionally surface a hint that a staleCLAUDE.mdexists and--cleanwould remove it.Acceptance criteria
CLAUDE.md+ populated.claude/rules/+apm compile --clean→CLAUDE.mdremoved.CLAUDE.md(no marker) is never removed; warning emitted instead.apm compilestill deletes nothing (non-destructive).CLAUDE.mdever created).--no-dedup/--force-instructionsstill regenerate a fullCLAUDE.mdand never trigger removal.CHANGELOG.md### Fixedentry referencing this issue and [FEATURE] Skip instructions in CLAUDE.md when already deployed to .claude/rules/ #1138.Related