Problem
When apm pack --check-clean detects drift between the checked-in marketplace.json and what regeneration would produce, the error tells producers that there's drift but not how to fix it cleanly. Producers staring at a red CI status on their release PR end up doing one of:
- a noisy follow-up commit (
chore: regen marketplace.json) that clutters the PR history
- a force-push without
--force-with-lease, which is unsafe
- giving up and asking on the discussion forum (we've seen this twice: #1322, #1332)
The lockfile pattern (treat marketplace.json like package-lock.json — checked in, regenerated by pipeline, drift-gated in CI) is sound; what's missing is the teaching moment at the exact place the producer hits the wall.
Proposed fix
Rewrite the --check-clean error to include the canonical recovery recipe. Concretely, when drift is detected, emit:
[x] marketplace.json drift detected at .claude-plugin/marketplace.json
Your checked-in marketplace.json doesn't match what 'apm pack' would
generate from apm.yml. To recover cleanly:
apm pack # regenerate locally
git add .claude-plugin/marketplace.json
git commit --amend --no-edit # fold into the current commit
git push --force-with-lease # safe re-push
Or as a follow-up commit:
apm pack && git add .claude-plugin/marketplace.json
git commit -m 'chore(marketplace): regen'
Why this exists: marketplace.json is checked in (lockfile pattern)
so consumers can resolve packages without running 'apm pack'. CI
enforces that the checked-in copy matches the apm.yml source of
truth.
Also: emit the same lines for each marketplace.outputs profile (claude, codex) so multi-output drift surfaces the right path per profile.
Out of scope (explicit)
- No
pack-bot mode, no GitHub-App auto-regen, no pre-commit hooks. A DevUX panel evaluated those options (provocateur / pragmatist / automation lenses). The pragmatist verdict — ship the teaching error and re-evaluate later — won on "is the complexity worth it?". The lockfile pattern is fine; we just need to teach it at the right moment.
- No
_generated_by JSON key change. Worth its own ticket if/when we see a real merge-conflict pain pattern in the wild.
Acceptance
apm pack --check-clean on drift prints the recipe above (exact wording can iterate).
- The recipe handles multi-output (claude + codex) by listing the right path per profile.
- A test in
tests/integration/ asserts the error text contains both commit --amend and force-with-lease.
Evidence trail
- Empirical surface: zava-agent-config v6.1.1 release (run 26079513903) where two community discussions traced back to this exact friction.
- Related but separate: apm-action#45 (v1.9.1) fixed the noisy 'produced N tarballs' warning seen in the same run; this issue is the remaining producer-side UX gap.
Problem
When
apm pack --check-cleandetects drift between the checked-inmarketplace.jsonand what regeneration would produce, the error tells producers that there's drift but not how to fix it cleanly. Producers staring at a red CI status on their release PR end up doing one of:chore: regen marketplace.json) that clutters the PR history--force-with-lease, which is unsafeThe lockfile pattern (treat marketplace.json like
package-lock.json— checked in, regenerated by pipeline, drift-gated in CI) is sound; what's missing is the teaching moment at the exact place the producer hits the wall.Proposed fix
Rewrite the
--check-cleanerror to include the canonical recovery recipe. Concretely, when drift is detected, emit:Also: emit the same lines for each
marketplace.outputsprofile (claude, codex) so multi-output drift surfaces the right path per profile.Out of scope (explicit)
pack-botmode, no GitHub-App auto-regen, no pre-commit hooks. A DevUX panel evaluated those options (provocateur / pragmatist / automation lenses). The pragmatist verdict — ship the teaching error and re-evaluate later — won on "is the complexity worth it?". The lockfile pattern is fine; we just need to teach it at the right moment._generated_byJSON key change. Worth its own ticket if/when we see a real merge-conflict pain pattern in the wild.Acceptance
apm pack --check-cleanon drift prints the recipe above (exact wording can iterate).tests/integration/asserts the error text contains bothcommit --amendandforce-with-lease.Evidence trail