chore: drop the duplicated package descriptions from root apm.yml

Why: for a local-path marketplace entry, apm treats a root description: as
an override of the package's own apm.yml, reported only at verbose level,
so the "two copies stay identical" rule had no enforcement. Same fix as
2def060 made for version:.

Implementation Notes:
- All six root copies matched their package apm.yml before removal; the
  compiled marketplace.json descriptions are unchanged.
- apm-workflow references now scope the "omit it" advice to local-path
  entries: on a remote entry, version: is the semver range that selects
  the tag, and version: or ref: is required.

Impact: ADR-0021 amended; the package apm.yml is the single source.

ADR: 0021
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-09-16 11:24:22 +00:00
parent c5d43b4d63
commit 398515bcad
4 changed files with 53 additions and 20 deletions

View File

@@ -18,6 +18,9 @@ file, `.claude-plugin/marketplace.json`. Read the "four generated files" in Cont
generated files" in Consequences as historical counts, true when written. The blast radius shrank;
the staleness hazard that motivated this ADR did not.
**Amended 2026-09-16:** the root `marketplace.packages[]` copy of each description was removed; the
package `apm.yml` is now the single source. See the amendment before Consequences.
## Context
A plugin's published description is one string authored twice — in `plugins/<name>/apm.yml` and in
@@ -203,6 +206,32 @@ sit inside ADR-0020's tiers; the tier would have been silent through all three f
string, not a link — and the README's own plugin list carries the same enumeration with the same
staleness, so this relocates the defect rather than fixing it.
## Amendment (2026-09-16): the root copy is removed — the package `apm.yml` is the single source
The Decision's rule that "the two copies … stay identical" is retired by removing the second copy.
The six `description:` lines under root `apm.yml`'s `marketplace.packages[]` are deleted, the same way
`2def060` deleted the six `version:` lines beside them. `plugins/<name>/apm.yml`'s `description:` is
now the only place a package's published description is authored.
The rule's own justification — "the root entry is what reaches the compiled marketplace" — was true
only while the root entry set the field. apm's Claude marketplace mapper resolves a local-path entry's
`description` curator-first: the entry's value wins when present, and when it is absent the value is
read from the package's own `apm.yml` (`apm_cli/marketplace/output_mappers.py`, the `is_local` branch
calling `_apply_field_with_precedence` with `source_label="package apm.yml"`). The root copy was
therefore an override, not a mirror. Nothing enforced the identity rule, and on drift apm silently
published the root value. Removing the copy removes the drift rather than leaving it unchecked.
All six root copies were byte-identical to their package's `apm.yml` when they were removed. After
the removal, `apm pack` regenerated `.claude-plugin/marketplace.json` with every `description` unchanged,
and `apm pack --check-versions --check-clean --dry-run` passes. The consequence for the "unbounded
obligation" in Context is that a description edit is now one edit, not two. The package version bump
and the catalog patch bump it earns are unchanged
(`plugins/kyberforge/.apm/skills/apm-workflow/references/configure.md`).
This applies to local-path (`source: ./…`) entries only. A remote entry has no local package
`apm.yml` to fall back to. Its `description:`, when set, is still the published text, and when it
is absent apm uses whatever its best-effort remote metadata fetch returns.
## Consequences
**Three descriptions are rewritten and the compiled output regenerated.** Eight generated files