fix(compile): scope managed-section footer wording - #2731
Conversation
Route generated footer wording through one canonical renderer and pass the AGENTS.md ownership mode through single-file and distributed compilation. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
Copilot review overview
Review tier: Lite
Findings: 1
New issues introduced by this change (1)
| Severity | Finding |
|---|---|
scripts/check_agents_footer_authority.py — The consumer check can false-positive because it only searches for the literal text… |
What changed in this PR
This PR fixes misleading generated-footer wording for root AGENTS.md when compilation.agents_md.mode: managed_section is enabled, ensuring the footer claims ownership of only the managed section (not the full file) and centralizing footer rendering to prevent future drift.
Changes:
- Introduces
build_generation_footer()as the single canonical footer renderer and updates all relevant compilation paths to use it. - Propagates
agents_md_modeinto both single-file and distributed rootAGENTS.mdgeneration so managed-section mode uses section-scoped wording. - Adds an architecture boundary check + regression tests, and updates docs to document the mode-specific footer contract.
| File | Description |
|---|---|
tests/unit/compilation/test_agents_footer_2689.py |
Regression coverage that managed-section mode emits section-scoped footer wording for both compilation strategies. |
tests/integration/test_architecture_agents_footer.py |
Architecture guard test ensuring a single canonical footer owner and that duplicates are rejected. |
src/apm_cli/compilation/template_builder.py |
Routes root single-file AGENTS.md footer through the canonical builder and passes mode. |
src/apm_cli/compilation/footer.py |
Adds the canonical mode-aware footer builder (build_generation_footer). |
src/apm_cli/compilation/distributed_compiler.py |
Uses mode-aware footer for root distributed output while keeping subdirectory outputs file-scoped. |
src/apm_cli/compilation/claude_formatter.py |
Routes CLAUDE footer through the shared footer builder (full-file wording). |
src/apm_cli/compilation/agents_compiler.py |
Propagates agents_md_mode into distributed config and routes Copilot footer via the shared builder. |
scripts/lint-architecture-boundaries.sh |
Adds a new architecture boundary check invocation for footer wording authority. |
scripts/check_agents_footer_authority.py |
New guard script rejecting duplicated footer wording or bypassed owner. |
docs/src/content/docs/reference/manifest-schema.md |
Documents managed-section footer semantics in the schema reference. |
docs/src/content/docs/producer/compile.md |
Documents managed-section footer semantics in the compile guide. |
.github/instructions/architecture.instructions.md |
Registers the canonical owner for footer wording in the architecture owner table. |
.apm/instructions/architecture.instructions.md |
Mirrors the owner-table registration for the canonical footer wording owner. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
| for relative_path in _CONSUMERS: | ||
| consumer = root / relative_path | ||
| source = consumer.read_text(encoding="utf-8") | ||
| if "build_generation_footer(" not in source: | ||
| violations.append(f"{relative_path}: generated footer must use build_generation_footer") |
APM Review Panel:
|
| Persona | B | R | N | Takeaway |
|---|---|---|---|---|
| Python Architect | 0 | 1 | 0 | Footer rendering is centralized, but the accepted agents_md mode vocabulary remains duplicated. |
| CLI Logging Expert | 0 | 0 | 1 | Managed-section wording is accurate and centralized; only the lint failure path repeats its headline. |
| DevX UX Expert | 0 | 0 | 0 | Managed-section footers scope the no-edit warning correctly while full-file outputs retain whole-file wording. |
| Supply Chain Security Expert | 0 | 0 | 0 | No supply-chain security concerns. |
| OSS Growth Hacker | 0 | 0 | 0 | Correct ownership wording removes a trust-breaking contradiction; no growth changes needed. |
| Doc Writer | 0 | 2 | 0 | Qualify footer emission and keep the behavior in one canonical page. |
| Test Coverage Expert | 0 | 1 | 0 | Root behavior passes, but nested full-file wording lacks a managed-mode regression trap. |
| Performance Expert | 0 | 1 | 0 | Footer rendering remains O(1); remove redundant per-output path resolution. |
B = blocking-severity findings, R = recommended, N = nits.
Counts are signal strength, not gates. The maintainer ships.
Top 5 follow-ups
- [Test Coverage Expert] Add the nested managed-mode full-file footer regression test. -- The
is_root=falsebranch must retain file-scoped wording but lacks an integration-with-fixtures guard. - [Python Architect] Give the accepted
agents_mdmode vocabulary one shared owner. -- Reusing one exported constant prevents footer validation, configuration, and write-path guards from drifting. - [Doc Writer] Make footer documentation conditional and keep the compile guide canonical. -- Distributed compilation can omit footers; the schema reference should cross-link instead of duplicating authority.
- [Performance Expert] Compare placement parents directly with the canonical base directory. -- This removes redundant filesystem resolution for every distributed output without changing behavior.
- [CLI Logging Expert] Emit the footer-authority lint failure headline once. -- Removing the duplicate headline keeps architecture-check failures concise.
Architecture
classDiagram
direction LR
class CompilationConfig {
+agents_md_mode str
}
class AgentsCompiler
class DistributedAgentsCompiler
class ClaudeFormatter
class TemplateBuilder
class FooterModule {
+build_generation_footer(mode) list
}
CompilationConfig --> AgentsCompiler
AgentsCompiler --> DistributedAgentsCompiler
AgentsCompiler ..> FooterModule
DistributedAgentsCompiler ..> FooterModule
ClaudeFormatter ..> FooterModule
TemplateBuilder ..> FooterModule
flowchart TD
A[Compilation config] --> B{Output strategy}
B -->|single file| C[Template builder]
B -->|distributed root| D[Distributed compiler]
C --> E[Canonical footer builder]
D --> E
E -->|managed_section root| F[Section wording]
E -->|full or nested| G[File wording]
Recommendation
Ship with these bounded, in-scope follow-ups folded, prioritizing the nested managed-mode regression test and single ownership of the mode vocabulary.
Full per-persona findings
Python Architect
- [recommended] Centralize the accepted agents_md mode vocabulary at
src/apm_cli/compilation/footer.py:3
The footer helper, configuration, and write path independently define the accepted values and can drift.
Suggested: Export one shared constant and reuse it inagents_compiler.py.
CLI Logging Expert
- [nit] Print the footer-authority failure headline once at
scripts/lint-architecture-boundaries.sh:221
The checker and wrapper currently emit the same failure headline.
DevX UX Expert
No findings.
Supply Chain Security Expert
No findings.
OSS Growth Hacker
No findings.
Auth Expert -- inactive
Only compilation runtime files are touched; no authentication surface is affected.
Doc Writer
- [recommended] Qualify the footer wording as conditional on a footer being emitted at
docs/src/content/docs/reference/manifest-schema.md:848
Distributed compilation omits the footer unless source attribution is enabled. - [recommended] Keep the footer behavior in one canonical page at
docs/src/content/docs/reference/manifest-schema.md:848
Retain the explanation in the compile guide and use the existing cross-link from the schema reference.
Test Coverage Expert
- [recommended] Managed mode lacks a regression test for nested full-file footers at
src/apm_cli/compilation/distributed_compiler.py:741
The new non-root branch preserves file-scoped wording but no managed-section test exercises it.
Proof (missing at):tests/unit/compilation/test_agents_footer_2689.py::test_managed_mode_keeps_subdirectory_footer_file_scoped-- proves: nested fully-owned AGENTS.md remains file-scoped in managed mode. [devx,portability-by-manifest]
Performance Expert
- [recommended] Avoid filesystem path resolution for every distributed output at
src/apm_cli/compilation/distributed_compiler.py:740
The base directory is already canonicalized, so twoPath.resolve()calls per placement are avoidable.
Suggested: Compareplacement.agents_path.parentdirectly withself.base_dir.
This panel is advisory. It does not block merge. Re-apply the panel-review label after addressing feedback to re-run.
Centralize mode validation, preserve nested footer wording with a regression trap, avoid repeated path resolution, clarify docs, and repair self-audit integrity. Addresses panel follow-ups from the shepherd review. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…ion-footer # Conflicts: # apm.lock.yaml
Parse consumer ASTs so comments and string literals cannot satisfy the footer authority guard. Addresses Copilot review signal on the new boundary check. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
APM Review Panel:
|
| Persona | B | R | N | Takeaway |
|---|---|---|---|---|
| Python Architect | 0 | 0 | 1 | Architecture is converged: footer rendering has one owner, explicit mode plumbing, and dual guardrails. |
| CLI Logging Expert | 0 | 0 | 0 | Managed-section footer wording is accurate and all renderers use the canonical builder. |
| DevX UX Expert | 0 | 0 | 0 | Ownership wording matches each output mode, is centralized, documented, and regression-tested. |
| Supply Chain Security Expert | 0 | 0 | 0 | No supply-chain security concerns in the footer wording or static ownership guard. |
| OSS Growth Hacker | 0 | 0 | 0 | The footer accurately scopes APM ownership without adding adoption friction. |
| Doc Writer | 0 | 0 | 0 | Compile guide and architecture instructions are accurate, concise, and discoverable. |
| Test Coverage Expert | 0 | 0 | 0 | Mode-aware footer behavior and canonical-owner routing are covered. |
| Performance Expert | 0 | 0 | 0 | No material regression: changed work is O(P), adds no I/O, and avoids repeated path resolution. |
B = blocking-severity findings, R = recommended, N = nits.
Counts are signal strength, not gates. The maintainer ships.
Architecture
classDiagram
direction LR
class CompilationConfig {
+agents_md_mode str
}
class AgentsCompiler
class TemplateBuilder
class DistributedAgentsCompiler
class ClaudeFormatter
class FooterRenderer {
+VALID_AGENTS_MD_MODES tuple
+build_generation_footer(mode) list
}
AgentsCompiler --> CompilationConfig
AgentsCompiler ..> TemplateBuilder
AgentsCompiler ..> DistributedAgentsCompiler
TemplateBuilder ..> FooterRenderer
DistributedAgentsCompiler ..> FooterRenderer
ClaudeFormatter ..> FooterRenderer
flowchart TD
A[Compilation config] --> B{Output strategy}
B -->|single file| C[Template builder]
B -->|distributed root| D[Distributed compiler]
B -->|fully generated output| E[Other formatter]
C --> F[Canonical footer renderer]
D --> F
E --> F
F -->|managed root| G[Section wording]
F -->|full or nested| H[File wording]
Recommendation
Ship at head 655886f1bc8875742aeff12e0c14c7b2c95e7da3; the panel found no actionable follow-up.
Folded in this run
- (panel) Add nested managed-mode full-file footer regression coverage -- resolved in
89639aef9e. - (panel) Give the accepted
agents_mdmode vocabulary one shared owner -- resolved in89639aef9e. - (panel) Make footer documentation conditional and keep the compile guide canonical -- resolved in
89639aef9e. - (panel) Avoid redundant path resolution for distributed placements -- resolved in
89639aef9e. - (panel) Emit the footer-authority lint failure headline once -- resolved in
89639aef9e. - (copilot) Require executable footer-owner calls in the static guard -- resolved in
655886f1bc.
Copilot signals reviewed
scripts/check_agents_footer_authority.py-- LEGIT: a comment or string could satisfy the raw text check without an executable call (resolved in655886f1bc).
Regression-trap evidence (mutation-break gate)
tests/unit/compilation/test_agents_footer_2689.py::test_managed_mode_keeps_subdirectory_footer_file_scoped-- deleted the non-root full-mode fallback; test FAILED as expected; guard restored.tests/unit/compilation/test_agents_footer_2689.py::test_generated_footer_describes_managed_section[single-file]-- bypassed the canonical renderer; test FAILED as expected; guard restored.tests/integration/test_architecture_agents_footer.py::test_generated_footer_guard_rejects_parallel_wording-- disabled duplicate-wording detection; test FAILED as expected; guard restored.tests/integration/test_architecture_agents_footer.py::test_generated_footer_guard_requires_executable_consumer_call-- replaced AST call detection with raw text matching; test FAILED as expected; guard restored.
Lint contract
The complete CI lint mirror passed at the exact head, including ruff, format, YAML I/O, file length, portable paths, pylint R0801, auth signals, and architecture boundaries.
CI
CI run 33324520816 and all other required checks passed after 0 CI fix iterations.
Mergeability status
| PR | head SHA | CEO stance | iters | folds | defers | Copilot rounds | CI | mergeable | mergeStateStatus | notes |
|---|---|---|---|---|---|---|---|---|---|---|
| #2731 | 655886f |
ship_now | 1 | 6 | 0 | 2 | green | MERGEABLE | BLOCKED | awaiting maintainer review |
Convergence
1 outer iteration; 2 Copilot rounds. Final panel recommendation: ship_now.
Ready for maintainer review.
Full per-persona findings
Python Architect
- [nit] No architecture follow-up requested.
The pure canonical renderer and explicit mode plumbing are the simplest correct design; behavioral and AST boundary checks provide the dual guardrail.
CLI Logging Expert
No findings.
DevX UX Expert
No findings.
Supply Chain Security Expert
No findings.
OSS Growth Hacker
No findings.
Auth Expert -- inactive
Only compilation files changed; no authentication surface is affected.
Doc Writer
No findings.
Test Coverage Expert
No findings.
Performance Expert
No findings.
This panel is advisory. It does not block merge. Re-apply the panel-review label after addressing feedback to re-run.

fix(compile): scope managed-section footer wording
TL;DR
Managed root
AGENTS.mdblocks now say that the section, not the whole file,was generated by APM CLI. Full-file outputs keep their existing wording, and
all compilation paths now share one footer renderer to prevent drift.
Note
Closes #2689.
Problem (WHY)
managed_sectionmode, the generated footer claimed ownership of theentire
AGENTS.md, contradicting the preserved hand-written content outsidethe markers reported in #2689.
compilation renderers, despite the architecture rule that durable decisions
have "exactly ONE canonical owner".
Approach (WHAT)
sectionformanaged_sectionandfilefor the defaultfullmode.agents_md_modeinto both single-file and distributed root rendering.AGENTS.md,CLAUDE.md, and.github/copilot-instructions.mdon whole-file wording.Implementation (HOW)
src/apm_cli/compilation/footer.pysrc/apm_cli/compilation/template_builder.pysrc/apm_cli/compilation/distributed_compiler.pysrc/apm_cli/compilation/agents_compiler.pysrc/apm_cli/compilation/claude_formatter.pyscripts/check_agents_footer_authority.py,scripts/lint-architecture-boundaries.sh.github/instructions/architecture.instructions.md,.apm/instructions/architecture.instructions.mdtests/unit/compilation/test_agents_footer_2689.pytests/integration/test_architecture_agents_footer.pydocs/src/content/docs/producer/compile.md,docs/src/content/docs/reference/manifest-schema.mdDiagrams
Legend: The dashed node is the new canonical decision point shared by both root
AGENTS.md rendering strategies.
flowchart LR C[CompilationConfig] --> S[Single-file root renderer] C --> D[Distributed root renderer] S --> F[build_generation_footer] D --> F F -->|managed_section| M[Section wording] F -->|full| W[File wording] W --> O[Whole-file Claude and Copilot outputs] classDef new stroke-dasharray: 5 5; class F new;Trade-offs
prevents the same user-facing ownership decision from diverging again.
users configure custom markers.
fully generated, so labeling them as sections would be misleading.
Benefits
AGENTS.mdstrategies emit section-scoped wording inmanaged_sectionmode.fullmode retains the existing whole-file footer.guard that rejects reintroduced duplicates.
Validation
Targeted compilation and architecture tests:
Test taxonomy and quality gates:
Canonical lint:
Architecture boundary lint:
Mutation-break proof:
Scenario Evidence
AGENTS.md; only the generated block claims APM ownership in either strategytests/unit/compilation/test_agents_footer_2689.py::test_generated_footer_describes_managed_section(regression-trap for #2689)tests/unit/compilation/test_agents_footer_2689.py::test_full_mode_footer_retains_whole_file_wordingHow to test
AGENTS.mdwith the default managed-section markers andhand-written text outside them.
compilation.agents_md.mode: managed_sectionandcompilation.source_attribution: trueinapm.yml.apm compile --local-only; confirm the managed block saysThis section was generatedand surrounding content is unchanged.--single-agents; confirm the same section wording.mode: full; confirm the footer saysThis file was generated.Co-authored-by: Copilot 223556219+Copilot@users.noreply.github.com