Skip to content

Apply PR #1020 review nits: type precision, reason constant, frozenset family validation#1035

Closed
danielmeppiel wants to merge 4 commits intomainfrom
followup/pr-1020-review-nits
Closed

Apply PR #1020 review nits: type precision, reason constant, frozenset family validation#1035
danielmeppiel wants to merge 4 commits intomainfrom
followup/pr-1020-review-nits

Conversation

@danielmeppiel
Copy link
Copy Markdown
Collaborator

TL;DR

Applies the three optional review nits from @apm-bot's Review Panel comment on #1020 on top of @tillig's HEAD (292bda1). No behavior change for end users; tightens internals so future contributors and direct API callers can't trip over the same footguns.

The required action (doc sync) was verified as a no-op — docs/src/content/docs/reference/cli-commands.md:1712 and packages/apm-guide/.apm/skills/apm-usage/commands.md:28 already document the correct multi-target behavior.

Problem

PR #1020 fixed apm compile --target claude,codex so it stops emitting an unrequested GEMINI.md. The Review Panel approved it with a small list of optional cleanups that improve robustness without changing user-visible output:

  1. Type imprecisionCompileTargetType = Union[str, frozenset] loses the inner element type that the rest of the module already assumes ({"agents", "claude", "gemini"}).
  2. Brittle reason couplingcli.py relied on "no target" in detection_reason to pick the "AGENTS.md only" log branch. If the reason string in target_detection.detect_target() ever changes wording, that branch silently goes dead.
  3. Silent frozenset bypassAgentsCompiler.compile() skipped _KNOWN_TARGETS validation when config.target is a frozenset. Any direct API caller passing a bogus family (e.g. frozenset({"bogus"})) would succeed with empty/partial output instead of failing loudly.

Changes

File Change
src/apm_cli/core/target_detection.py Union[str, frozenset]Union[str, frozenset[str]]. Added REASON_NO_TARGET_FOLDER = "no target folder found" constant; detect_target() returns it instead of a string literal.
src/apm_cli/commands/compile/cli.py Imports REASON_NO_TARGET_FOLDER; replaces "no target" in detection_reason with detection_reason == REASON_NO_TARGET_FOLDER. User-facing log message is unchanged ("Compiling for AGENTS.md only (no target folder found)").
src/apm_cli/compilation/agents_compiler.py Added _KNOWN_COMPILE_FAMILIES = frozenset({"agents", "claude", "gemini"}). The frozenset branch now validates the set and returns an explicit error if any member is unknown.
tests/unit/compilation/test_compile_target_flag.py Adds test_unknown_frozenset_target_family_returns_failure regression test.

Why an explicit branch instead of assert

The reviewer suggested an assert. Rejected: assert is stripped under python -O, and inside compile() it would surface as a generic Compilation failed: ... — strictly worse UX than the existing unknown-target error path. The explicit branch costs ~10 lines, runs once per compile, and yields an actionable message for direct API callers (the error names the bad family and lists accepted families).

Validation

pytest tests/unit/compilation/ tests/unit/core/ tests/unit/commands/ -q
...
806 passed in 5.50s

Includes the new regression test plus all existing target-routing, multi-target, and detection tests.

Relationship to #1020

This branch is based on PR #1020's HEAD (292bda1). It is a follow-up, not a competing PR — happy to:

Whatever maintainers prefer.

How to test

git fetch origin followup/pr-1020-review-nits
git checkout followup/pr-1020-review-nits
uv venv && source .venv/bin/activate && uv pip install -e ".[dev]"
pytest tests/unit/compilation/ tests/unit/core/ -q

Manual smoke (in any APM project):

apm compile --target claude,codex   # still: AGENTS.md + CLAUDE.md, no GEMINI.md
apm compile --target claude         # CLAUDE.md only
apm compile                         # auto-detect; "no target folder found" log path unchanged

Refs #1020.

tillig and others added 4 commits April 28, 2026 08:50
Co-authored-by: Copilot <copilot@github.com>
…set family validation

- Parameterize CompileTargetType as Union[str, frozenset[str]] for precision
- Extract REASON_NO_TARGET_FOLDER constant in target_detection; replace
  brittle substring match in compile CLI with equality comparison.
  User-facing log message is unchanged.
- Add explicit family validation in AgentsCompiler when config.target is
  a frozenset. Previously the frozenset branch silently bypassed
  _KNOWN_TARGETS validation; an invalid family (e.g. via direct API use)
  could silently produce partial output. Now fails explicitly with a
  clear error listing the bad value and accepted families.
- Add regression test test_unknown_frozenset_target_family_returns_failure.

Docs sync: verified docs/src/content/docs/reference/cli-commands.md and
packages/apm-guide/.apm/skills/apm-usage/commands.md already document the
correct (post-fix) multi-target behavior; no edits needed.

Refs #1020

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings April 29, 2026 11:52
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Applies follow-up review nits on top of PR #1020 by tightening the internal compile-target representation and validation, and by de-coupling CLI behavior from brittle reason-string substring checks.

Changes:

  • Introduces CompileTargetType (including frozenset[str]) and exports REASON_NO_TARGET_FOLDER for equality-based comparisons.
  • Updates compile CLI to support multi-target compilation via frozenset routing and reason-constant comparison.
  • Adds defensive validation for multi-target frozenset families in AgentsCompiler, plus regression tests and a changelog entry.
Show a summary per file
File Description
tests/unit/compilation/test_compile_target_flag.py Adds/updates regression tests for multi-target resolution and frozenset validation behavior.
src/apm_cli/core/target_detection.py Adds CompileTargetType, REASON_NO_TARGET_FOLDER, and updates should_compile_* helpers to accept frozenset targets.
src/apm_cli/compilation/agents_compiler.py Validates frozenset-based multi-target families and returns a clear error on unknown families.
src/apm_cli/commands/compile/cli.py Switches from substring matching to reason constant equality; adds frozenset-aware target handling and progress messaging.
CHANGELOG.md Adds an Unreleased Fixed entry for the compile targeting behavior.

Copilot's findings

  • Files reviewed: 5/5 changed files
  • Comments generated: 2

Comment on lines 450 to 481
if isinstance(target, list):
# Multi-target list: show what the compiler will produce
_target_label = ",".join(target)
if effective_target == "all":
logger.progress(
f"Compiling for AGENTS.md + CLAUDE.md (--target {_target_label})"
)
elif effective_target == "claude":
logger.progress(
f"Compiling for CLAUDE.md (--target {_target_label})"
)
else:
logger.progress(
f"Compiling for AGENTS.md (--target {_target_label})"
)
elif detected_target == "minimal":
from ...core.target_detection import (
should_compile_agents_md,
should_compile_claude_md,
should_compile_gemini_md,
)
_parts = []
if should_compile_agents_md(effective_target):
_parts.append("AGENTS.md")
if should_compile_claude_md(effective_target):
_parts.append("CLAUDE.md")
if should_compile_gemini_md(effective_target):
_parts.append("GEMINI.md")
logger.progress(
f"Compiling for {' + '.join(_parts)} (--target {_target_label})"
)
elif (
isinstance(effective_target, str)
and effective_target == "vscode"
and detection_reason == REASON_NO_TARGET_FOLDER
):
logger.progress(f"Compiling for AGENTS.md only ({detection_reason})")
logger.progress(
" Create .github/, .claude/, .codex/, .opencode/ or .cursor/ folder for full integration",
symbol="light_bulb",
)
else:
description = get_target_description(detected_target)
description = get_target_description(effective_target)
logger.progress(
f"Compiling for {description} - {detection_reason}"
Copy link

Copilot AI Apr 29, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When effective_target comes from apm.yml as a multi-target list (so _resolve_compile_target(config_target) returns a frozenset) and the CLI --target flag is not a list, this branch falls through to get_target_description(effective_target), which will render as "unknown target" in the progress log. Consider handling isinstance(effective_target, frozenset) (regardless of the original target type) by building the AGENTS.md/CLAUDE.md/GEMINI.md parts list the same way as the isinstance(target, list) branch, so config-driven multi-targets get an accurate progress message.

Copilot uses AI. Check for mistakes.
Comment thread CHANGELOG.md
Comment on lines 18 to 20
- Remove redundant `seen` set from `_scan_patterns()` discovery walk (#918)
- Correct targeting of compiled artifacts so GEMINI.md is only created if requested (#1019)

Copy link

Copilot AI Apr 29, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This changelog entry appears to reference the issue number (#1019) rather than the PR that delivered the fix, and it doesn't end with a PR number as required by the project's Keep a Changelog convention. Update the line to end with the actual PR number (likely #1020 and/or this follow-up PR), and consider wrapping GEMINI.md in backticks for consistency with nearby entries.

Copilot generated this review using guidance from repository custom instructions.
@danielmeppiel
Copy link
Copy Markdown
Collaborator Author

Folded the single follow-up commit (fb314d3) directly onto #1020's branch (maintainerCanModify: true) instead of carrying a separate PR. Closing in favor of #1020.

@danielmeppiel danielmeppiel deleted the followup/pr-1020-review-nits branch April 29, 2026 12:10
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.

3 participants