Skip to content

fix(compile): scope managed-section footer wording - #2731

Merged
Daniel Meppiel (danielmeppiel) merged 4 commits into
mainfrom
fix/2689-managed-section-footer
Aug 30, 2026
Merged

fix(compile): scope managed-section footer wording#2731
Daniel Meppiel (danielmeppiel) merged 4 commits into
mainfrom
fix/2689-managed-section-footer

Conversation

@danielmeppiel

Copy link
Copy Markdown
Collaborator

fix(compile): scope managed-section footer wording

TL;DR

Managed root AGENTS.md blocks 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)

  • In managed_section mode, the generated footer claimed ownership of the
    entire AGENTS.md, contradicting the preserved hand-written content outside
    the markers reported in #2689.
  • [!] The same whole-file sentence was assembled independently by four
    compilation renderers, despite the architecture rule that durable decisions
    have "exactly ONE canonical owner".

Approach (WHAT)

  • Add one footer builder that selects section for managed_section and
    file for the default full mode.
  • Pass agents_md_mode into both single-file and distributed root rendering.
  • Keep subdirectory AGENTS.md, CLAUDE.md, and
    .github/copilot-instructions.md on whole-file wording.
  • Guard the wording owner with behavioral and static mutation tests.

Implementation (HOW)

Files Change
src/apm_cli/compilation/footer.py Defines the canonical mode-aware footer.
src/apm_cli/compilation/template_builder.py Uses the configured mode for single-file root output.
src/apm_cli/compilation/distributed_compiler.py Applies the configured mode only to the root placement.
src/apm_cli/compilation/agents_compiler.py Propagates the mode and routes Copilot whole-file output through the shared builder.
src/apm_cli/compilation/claude_formatter.py Routes Claude whole-file output through the shared builder.
scripts/check_agents_footer_authority.py, scripts/lint-architecture-boundaries.sh Reject duplicated ownership wording or bypassed consumers.
.github/instructions/architecture.instructions.md, .apm/instructions/architecture.instructions.md Register the new canonical owner.
tests/unit/compilation/test_agents_footer_2689.py Covers managed distributed and single-file output plus full-mode compatibility.
tests/integration/test_architecture_agents_footer.py Proves the static authority guard rejects a duplicate.
docs/src/content/docs/producer/compile.md, docs/src/content/docs/reference/manifest-schema.md Document the mode-specific footer contract.

Diagrams

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;
Loading

Trade-offs

  • Central helper over three local conditionals. This adds a small module but
    prevents the same user-facing ownership decision from diverging again.
  • Generic section wording over marker names. The footer stays accurate when
    users configure custom markers.
  • Root-only mode propagation. Subdirectory and harness-specific files remain
    fully generated, so labeling them as sections would be misleading.

Benefits

  1. Both supported root AGENTS.md strategies emit section-scoped wording in
    managed_section mode.
  2. Default full mode retains the existing whole-file footer.
  3. Four compilation renderers share one wording owner, enforced by a boundary
    guard that rejects reintroduced duplicates.

Validation

Targeted compilation and architecture tests:

159 passed in 2.30s

Test taxonomy and quality gates:

54 passed in 125.98s (0:02:05)
[+] assertion-quality ratchet clean: AQ001=4, AQ002=12
[+] exact test duplicate ratchet clean: 1141 files, 0 allowed duplicate group(s)

Canonical lint:

All checks passed!
1682 files already formatted
Your code has been rated at 10.00/10
[+] auth-signal lint clean

Architecture boundary lint:

[+] architecture boundary lint clean

Mutation-break proof:

2 failed in 1.55s
[+] Mutation rejected by regression test

Scenario Evidence

# Scenario (user promise) Principle(s) Test(s) proving it Type
1 Compile a managed root AGENTS.md; only the generated block claims APM ownership in either strategy DevX, Portability by manifest tests/unit/compilation/test_agents_footer_2689.py::test_generated_footer_describes_managed_section (regression-trap for #2689) integration
2 Compile with default full-file ownership; the established footer remains unchanged DevX tests/unit/compilation/test_agents_footer_2689.py::test_full_mode_footer_retains_whole_file_wording unit

How to test

  • Create AGENTS.md with the default managed-section markers and
    hand-written text outside them.
  • Set compilation.agents_md.mode: managed_section and
    compilation.source_attribution: true in apm.yml.
  • Run apm compile --local-only; confirm the managed block says
    This section was generated and surrounding content is unchanged.
  • Repeat with --single-agents; confirm the same section wording.
  • Switch to mode: full; confirm the footer says
    This file was generated.

Co-authored-by: Copilot 223556219+Copilot@users.noreply.github.com

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>

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.

Copilot review overview

Review tier: Lite
Findings: 1 Medium severity

New issues introduced by this change (1)
Severity Finding
Medium severity 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_mode into both single-file and distributed root AGENTS.md generation 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.

Comment on lines +43 to +47
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")
@danielmeppiel

Copy link
Copy Markdown
Collaborator Author

APM Review Panel: ship_with_followups

This fix restores truthful ownership boundaries in generated AGENTS.md footers while preserving full-file wording across compile paths.

cc Sergio Sisternes (@sergio-sisternes-epam) -- a fresh advisory pass is ready for your review.

The panel agrees that the managed root wording now accurately limits APM's ownership claim to the generated section, while full-file outputs retain the existing file-scoped warning. Centralizing footer rendering strengthens consistency without introducing security, authentication, or material performance risk.

The highest-signal follow-up is the missing nested managed-mode regression test. That branch preserves a user-facing promise and should be protected. The remaining findings are bounded quality improvements: establish one owner for the mode vocabulary, make documentation conditional and canonical, remove redundant path resolution, and avoid repeating the lint failure headline.

Aligned with: Governed by policy: the footer states the precise generated boundary. OSS community driven: accurate ownership wording avoids misleading contributors. Pragmatic as npm: one shared renderer makes guidance predictable.

Growth signal. Include this as a trust-preserving compile reliability fix in release notes; it does not warrant a standalone launch beat.

Panel summary

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

  1. [Test Coverage Expert] Add the nested managed-mode full-file footer regression test. -- The is_root=false branch must retain file-scoped wording but lacks an integration-with-fixtures guard.
  2. [Python Architect] Give the accepted agents_md mode vocabulary one shared owner. -- Reusing one exported constant prevents footer validation, configuration, and write-path guards from drifting.
  3. [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.
  4. [Performance Expert] Compare placement parents directly with the canonical base directory. -- This removes redundant filesystem resolution for every distributed output without changing behavior.
  5. [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
Loading
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]
Loading

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 in agents_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 two Path.resolve() calls per placement are avoidable.
    Suggested: Compare placement.agents_path.parent directly with self.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>
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>
@danielmeppiel

Copy link
Copy Markdown
Collaborator Author

APM Review Panel: ship_now

Generated footers now truthfully identify one canonical owner for each mode, removing ambiguity without adding architectural or runtime cost.

cc Sergio Sisternes (@sergio-sisternes-epam) -- a fresh advisory pass is ready for your review.

The panel converges without substantive dissent: ownership wording is accurate, mode-aware, documented, tested, and routed through one canonical builder. The architect's explicit no-follow-up nit is non-actionable. Full lint and GitHub checks are green, with no security, UX, documentation, coverage, or performance concerns.

Aligned with: OSS community driven: truthful ownership language preserves contributor and user trust in generated artifacts. Pragmatic as npm: one canonical owner and explicit mode plumbing keep generated output predictable and easy to understand.

Growth signal. Use a concise release-note line emphasizing clearer, trustworthy generated-file ownership.

Panel summary

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
Loading
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]
Loading

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_md mode vocabulary one shared owner -- resolved in 89639aef9e.
  • (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 in 655886f1bc).

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.

@danielmeppiel
Daniel Meppiel (danielmeppiel) merged commit bc91f05 into main Aug 30, 2026
18 checks passed
@danielmeppiel
Daniel Meppiel (danielmeppiel) deleted the fix/2689-managed-section-footer branch August 30, 2026 17:43
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] Use mode-aware footer text in managed_section mode instead of hardcoded "This file was generated by APM CLI"

2 participants