Skip to content

fix(applyTo): fold #1387 panel follow-ups (docs + DRY + YAML escape)#1449

Open
danielmeppiel wants to merge 1 commit into
mainfrom
followup/1387-panel-nits
Open

fix(applyTo): fold #1387 panel follow-ups (docs + DRY + YAML escape)#1449
danielmeppiel wants to merge 1 commit into
mainfrom
followup/1387-panel-nits

Conversation

@danielmeppiel
Copy link
Copy Markdown
Collaborator

Summary

Follow-up to #1387 (which fixed comma-separated applyTo globs in Claude/Cursor/Windsurf, closes #1366). The APM review panel posted ship_with_followups with 0 blocking and 5 nit-level items; this PR folds all 5.

What lands

  1. CHANGELOG -- Fixed entry under [Unreleased] with the per-harness behavior spelled out and the Copilot-verbatim carve-out called out. (fix(integration): respect comma-separated applyTo globs in Claude/Cursor/Windsurf #1387, closes [BUG] applyTo comma-separated globs are not split ? Claude target emits broken paths: and compiler warns "matches no files" #1366)
  2. docs/producer/author-primitives/instructions-and-agents.md -- worked comma-list example, brace-alternation carve-out, and per-target rendering in "What compiles where".
  3. packages/apm-guide/.apm/skills/apm-usage/package-authoring.md -- apm-usage resource gets the same comma-list note (linting rule 4 parity).
  4. refactor(patterns) -- _has_top_level_comma moves from context_optimizer.py into utils/patterns.py as has_top_level_comma. Single source of truth for the brace-depth state machine; eliminates the DRY violation flagged by python-architect.
  5. security(integrators) -- new yaml_double_quote() helper escapes backslashes, double-quotes, newlines, CR, and tab before emission. Defence-in-depth against adversarial or copy-paste-mangled applyTo values; risk is LOW today (parse_apply_to already strips whitespace; Windsurf already strips newlines) but producer output is now well-formed even on hostile input.

Validation

  • uv run --extra dev ruff check src/ tests/ -- silent.
  • uv run --extra dev ruff format --check src/ tests/ -- silent.
  • 175 targeted tests pass (tests/unit/utils/test_patterns.py, tests/unit/compilation/test_context_optimizer.py, tests/unit/integration/test_instruction_integrator.py, tests/integration/test_apply_to_comma_e2e.py).
  • 11 new unit tests added: TestHasTopLevelComma (6) and TestYamlDoubleQuote (5 + yaml.safe_load round-trip). Mutation-break verified -- dropping the escape in yaml_double_quote fails all 5 escape tests plus the round-trip.

References

Lands the panel recommendations on #1387 (closes #1366) that were
filed as nits after the merge:

- CHANGELOG: add Fixed entry under [Unreleased] documenting the
  comma-separated applyTo fix across Claude/Cursor/Windsurf, with
  the Copilot-verbatim carve-out spelled out (#1387, closes #1366).
- docs(instructions-and-agents): demonstrate the comma-list contract
  with a worked example, document the brace-alternation carve-out,
  and clarify per-target rendering in "What compiles where".
- docs(apm-usage/package-authoring): mirror the comma-list syntax
  note in the apm-usage skill resource (linting rule 4).
- refactor(patterns): move _has_top_level_comma from
  context_optimizer into utils/patterns.py as has_top_level_comma
  (DRY: single source of truth for the brace-depth state machine).
- security(integrators): emit YAML scalars via a new
  yaml_double_quote() helper that escapes backslashes, quotes, and
  control characters. Defence-in-depth against adversarial or
  copy-paste-mangled applyTo values; risk is LOW today (parse_apply_to
  strips whitespace and Windsurf strips newlines) but producer output
  is now well-formed even on hostile input. Added 11 unit tests
  including yaml.safe_load round-trip and a has_top_level_comma
  brace-aware suite.

Lint silent; 175 tests pass (26 in test_patterns.py).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings May 22, 2026 07:07
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

Folds review-panel follow-ups from #1387 by tightening applyTo comma-list behavior documentation, de-duplicating comma-vs-brace detection logic, and hardening YAML emission for instruction target frontmatter.

Changes:

  • Document applyTo comma-list vs brace-alternation semantics and per-target rendering (Copilot vs Claude/Cursor/Windsurf).
  • Refactor comma-discrimination into utils.patterns.has_top_level_comma() and add unit coverage.
  • Add yaml_double_quote() and apply it in instruction integrator YAML outputs to prevent malformed frontmatter on special characters.
Show a summary per file
File Description
tests/unit/utils/test_patterns.py Adds unit tests for has_top_level_comma() and yaml_double_quote() (incl. yaml.safe_load round-trip).
src/apm_cli/utils/patterns.py Introduces has_top_level_comma() and yaml_double_quote() alongside parse_apply_to().
src/apm_cli/integration/instruction_integrator.py Uses yaml_double_quote() when emitting globs: / paths: YAML for Cursor/Windsurf/Claude conversions.
src/apm_cli/compilation/context_optimizer.py Replaces local _has_top_level_comma with shared has_top_level_comma.
packages/apm-guide/.apm/skills/apm-usage/package-authoring.md Updates apm-usage package authoring docs to clarify comma-list semantics and target behavior.
docs/src/content/docs/producer/author-primitives/instructions-and-agents.md Adds a worked comma-list example + clarifies per-target compilation behavior.
CHANGELOG.md Adds an Unreleased Fixed entry describing the applyTo comma-list behavior across harnesses.

Copilot's findings

  • Files reviewed: 7/7 changed files
  • Comments generated: 3

Comment on lines +16 to +18
Single source of truth for the comma-vs-brace discrimination; the
placement optimizer and the integrators both consume this so the
semantics of ``parse_apply_to`` and its callers stay in lock-step.
Comment on lines +32 to +40
def yaml_double_quote(value: str) -> str:
"""Escape ``value`` for embedding inside a YAML double-quoted scalar.

Defence-in-depth for the instruction integrators that emit YAML
frontmatter via f-strings (``f' - "{g}"'``). A glob containing a
literal backslash, double-quote, or control character would break
the surrounding YAML if inlined verbatim; this helper escapes the
minimal set needed for the YAML 1.2 double-quoted form. Returns the
value already wrapped in the surrounding double quotes.
Comment thread CHANGELOG.md

### Fixed

- Comma-separated `applyTo` globs now correctly emit a YAML list under `globs:` / `paths:` in Claude, Cursor, and Windsurf instruction outputs (Copilot output unchanged -- it already preserves `applyTo` verbatim and handles comma-lists natively). The shared `parse_apply_to()` helper is brace-aware, so `**/*.{css,scss},**/*.py` is split on the top-level comma only. Closes a documented promise that was silently broken on the three non-Copilot harnesses. (#1387, closes #1366)
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] applyTo comma-separated globs are not split ? Claude target emits broken paths: and compiler warns "matches no files"

2 participants