Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 9 additions & 3 deletions src/apm_cli/commands/compile/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -703,10 +703,16 @@ def _coerce_provenance_targets(value):
f"-- run 'apm audit --file {output_path}' to inspect"
)
try:
from ...compilation.output_writer import CompiledOutputWriter
# Honour managed_section mode (issue #1764).
if config.agents_md_mode == "managed_section":
compiler._write_output_file_with_config(
str(output_path), final_content, config
)
else:
from ...compilation.output_writer import CompiledOutputWriter

CompiledOutputWriter().write(output_path, final_content)
except OSError as e:
CompiledOutputWriter().write(output_path, final_content)
except (OSError, ValueError) as e:
logger.error(f"Failed to write final AGENTS.md: {e}")
sys.exit(1)
else:
Expand Down
7 changes: 7 additions & 0 deletions src/apm_cli/compilation/agents_compiler.py
Original file line number Diff line number Diff line change
Expand Up @@ -1553,6 +1553,13 @@ def _write_distributed_file(
except Exception as exc:
_logger.debug("Constitution injection failed for %s: %s", agents_path, exc)

# Honour managed_section mode for the root AGENTS.md (issue #1764).
# Sub-directory files are fully APM-generated and always overwritten.
is_root = agents_path.parent.resolve() == self.base_dir.resolve()
if is_root and config.agents_md_mode == "managed_section":
self._write_output_file_with_config(str(agents_path), final_content, config)
return
Comment on lines +1556 to +1561

from .output_writer import CompiledOutputWriter

CompiledOutputWriter().write(agents_path, final_content)
Expand Down
90 changes: 90 additions & 0 deletions tests/unit/compilation/test_managed_section.py
Original file line number Diff line number Diff line change
Expand Up @@ -351,6 +351,96 @@ def test_write_output_file_managed_section_file_missing(self, tmp_path):
with pytest.raises(ManagedSectionError, match=r"(?i)does not exist|not exist|create it"):
compiler._write_output_file_with_config(str(output_file), "New content.\n", config)


class TestManagedSectionDistributed:
"""Regression tests for managed_section in distributed compilation (issue #1764)."""

def test_distributed_root_agents_md_honours_managed_section(self, tmp_path):
"""Root AGENTS.md preserves human content when managed_section is active."""
from apm_cli.compilation.agents_compiler import AgentsCompiler, CompilationConfig

start = "<!-- apm:start -->"
end = "<!-- apm:end -->"
root_agents = tmp_path / "AGENTS.md"
root_agents.write_text(
"# Team guidance\n\n"
"Human-authored content.\n\n"
f"{start}\n"
"Old APM block.\n"
f"{end}\n\n"
"Footer stays.\n"
)

config = CompilationConfig(
agents_md_mode="managed_section",
agents_md_start_marker=start,
agents_md_end_marker=end,
dry_run=False,
)

compiler = AgentsCompiler(str(tmp_path))
compiler._write_distributed_file(root_agents, "New APM block.", config)

written = root_agents.read_text()
assert "Human-authored content." in written
assert "Footer stays." in written
assert "New APM block." in written
assert "Old APM block." not in written

def test_distributed_subdir_agents_md_ignores_managed_section(self, tmp_path):
"""Sub-directory AGENTS.md is fully overwritten even with managed_section."""
from apm_cli.compilation.agents_compiler import AgentsCompiler, CompilationConfig

start = "<!-- apm:start -->"
end = "<!-- apm:end -->"
subdir = tmp_path / "src"
subdir.mkdir()
subdir_agents = subdir / "AGENTS.md"
subdir_agents.write_text(
"# Old content\n\n"
f"{start}\n"
"Old APM block.\n"
f"{end}\n\n"
"Human content that will be overwritten.\n"
)

config = CompilationConfig(
agents_md_mode="managed_section",
agents_md_start_marker=start,
agents_md_end_marker=end,
dry_run=False,
)

compiler = AgentsCompiler(str(tmp_path))
compiler._write_distributed_file(subdir_agents, "Fully new content.", config)

written = subdir_agents.read_text()
assert written == "Fully new content."
assert "Human content that will be overwritten." not in written

def test_distributed_root_agents_md_full_mode_overwrites(self, tmp_path):
"""Root AGENTS.md is fully overwritten when mode is 'full' (default)."""
from apm_cli.compilation.agents_compiler import AgentsCompiler, CompilationConfig

root_agents = tmp_path / "AGENTS.md"
root_agents.write_text("Old content that should be replaced.\n")

config = CompilationConfig(
agents_md_mode="full",
dry_run=False,
)

compiler = AgentsCompiler(str(tmp_path))
compiler._write_distributed_file(root_agents, "Completely new content.", config)

written = root_agents.read_text()
assert written == "Completely new content."
assert "Old content" not in written


class TestManagedSectionDirectoryAtPath:
"""Regression: directory at target path produces clear error."""

def test_write_output_file_managed_section_directory_at_path(self, tmp_path):
"""When mode=managed_section and a directory occupies the target path, raise ManagedSectionError.

Expand Down
Loading