Skip to content

apm pack --check-clean: rewrite error message to teach the amend+force-with-lease recipe #1381

@danielmeppiel

Description

@danielmeppiel

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.

Metadata

Metadata

Assignees

Labels

area/marketplacemarketplace.json schema, federation, authoring suite, source parity.area/package-authoringapm pack/unpack, plugin authoring, vendoring guidance, bundle format.priority/highShips in current or next milestonestatus/acceptedDirection approved, safe to start work.status/triagedInitial agentic triage complete; pending maintainer ratification (silence = approval).theme/portabilityOne manifest, every target. Multi-target deploy, marketplace, packaging, install.type/featureNew capability, new flag, new primitive.

Type

No type
No fields configured for issues without a type.

Projects

Status
Done

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions