Skip to content

fix: support catalog-only marketplace plugins - #2709

Merged
Daniel Meppiel (danielmeppiel) merged 6 commits into
microsoft:mainfrom
lkshrk:fix/metadata-only-marketplace-plugin
Aug 30, 2026
Merged

fix: support catalog-only marketplace plugins#2709
Daniel Meppiel (danielmeppiel) merged 6 commits into
microsoft:mainfrom
lkshrk:fix/metadata-only-marketplace-plugin

Conversation

@lkshrk

@lkshrk lkshrk (lkshrk) commented Aug 28, 2026

Copy link
Copy Markdown
Contributor

Description

Marketplace catalog entries can contain deployable LSP/MCP metadata even when their downloaded source has no apm.yml, SKILL.md, or plugin manifest. Preserve admitted inline catalog metadata through dependency resolution and synthesize the package manifest before ordinary validation.

The fix is fail-closed:

  • only name, description, version, lspServers, and mcpServers are retained;
  • nested values are deep-copied and excluded from marketplace identity/hash;
  • unrelated catalog fields cannot inject APM dependencies;
  • every declared LSP/MCP component must materialize successfully;
  • failed synthesis removes the rejected download.

Fixes #2708

Type of change

  • Bug fix
  • New feature
  • Documentation
  • Maintenance / refactor

Testing

  • Tested locally
  • All existing tests pass
  • Added tests for new functionality

Validation evidence:

How to test

uv run --python 3.12 pytest -q \
  tests/test_apm_resolver.py::TestMarketplaceResolution::test_metadata_only_marketplace_dep_uses_catalog_components \
  tests/unit/deps/test_shared.py::TestValidateAndLoadPackage::test_materializes_metadata_only_marketplace_plugin \
  tests/unit/deps/test_shared.py::TestValidateAndLoadPackage::test_rejects_invalid_marketplace_metadata_and_cleans_target

Spec conformance (OpenAPM v0.1)

  • N/A -- this fixes marketplace package normalization and does not change the OpenAPM v0.1 manifest contract.

Scenario Evidence

User promise Principle Automated evidence Regression trap
A catalog-only marketplace package materializes every admitted LSP and MCP server, rejects invalid metadata without durable writes, and ignores unrelated dependency fields. Secure by default; DevX tests/integration/test_marketplace_install_local.py::test_catalog_only_marketplace_installs_all_inline_servers; tests/integration/test_marketplace_install_local.py::test_invalid_catalog_only_metadata_fails_install_resolution Yes - issue #2708

apm-spec-waiver: Marketplace catalog compatibility translates admitted metadata into the existing OpenAPM manifest contract; it adds no normative OpenAPM requirement.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Fixes marketplace installs for “catalog-only” plugins (no apm.yml / SKILL.md / plugin manifest on disk) by preserving admitted deployable metadata from the marketplace catalog through resolution, then synthesizing an apm.yml before normal package validation.

Changes:

  • Extend MarketplacePlugin parsing to retain a deep-copied, admitted manifest subset (name/description/version/lspServers/mcpServers) that is excluded from identity/hash.
  • Thread the admitted manifest through marketplace resolution into DependencyReference.marketplace_manifest.
  • Materialize a synthetic apm.yml from the catalog manifest when needed (fail-closed + cleanup on failure), with new resolver/unit tests covering the LSP path.

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
tests/unit/deps/test_shared.py Adds unit coverage for metadata-only plugin materialization and fail-closed cleanup.
tests/test_apm_resolver.py Adds end-to-end resolver coverage ensuring catalog metadata is retained and used during install.
src/apm_cli/models/dependency/reference.py Adds marketplace_manifest field on DependencyReference to carry admitted catalog metadata.
src/apm_cli/marketplace/models.py Parses and deep-copies admitted catalog manifest fields onto MarketplacePlugin (excluded from hash/eq).
src/apm_cli/deps/apm_resolver.py Captures the plugin manifest from marketplace resolution onto the resolved DependencyReference.
src/apm_cli/deps/_shared.py Implements materialize_marketplace_manifest() and integrates it into _validate_and_load_package().
Suppressed comments (1)

src/apm_cli/deps/_shared.py:34

  • The materialization failure messages don’t include which dependency (or path) failed, which makes resolver/installer errors harder to diagnose. Include the dep repo_url and target path in the raised ValueError messages.
        if "lspServers" in declared and not package.get_lsp_dependencies():
            raise ValueError("Marketplace LSP metadata did not materialize a valid dependency")
        if "mcpServers" in declared and not package.get_mcp_dependencies():
            raise ValueError("Marketplace MCP metadata did not materialize a valid dependency")

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread src/apm_cli/deps/_shared.py Outdated
Comment thread src/apm_cli/models/dependency/reference.py Outdated
@danielmeppiel

Copy link
Copy Markdown
Collaborator

APM Review Panel: needs_rework

Catalog-only marketplace support removes publisher repackaging, but manifest synthesis must be fail-closed, path-safe, and variant-aware to be dependable.

cc lkshrk (@lkshrk) Sergio Sisternes (@sergio-sisternes-epam) -- a fresh advisory pass is ready for your review.

The compatibility goal is strong: publishers should not need to repackage valid catalog LSP or MCP metadata merely to satisfy APM. The panel nevertheless converges on correctness and security defects in the materialization boundary: partial component acceptance, swallowed resolver failures, symlink path escape, replayable failed synthesis, and reuse across differing catalog manifests.

These are demonstrated faults in an install and marketplace path, not speculative polish. Focused unit regression traps cover the basic happy path and cleanup case, but the mocked resolver/downloader test does not establish the complete marketplace flow. Keep the simple UX while making synthesis transactional, deterministic, fully validated, and accurately diagnosed.

Dissent. The architect classifies mixed valid and invalid declarations as blocking-severity while DevX and security classify the same issue as recommended. The higher signal fits because partial acceptance contradicts the stated fail-closed contract.

Aligned with: Portable by manifest: catalog metadata becomes an auditable package only when every component materializes. Secure by default: synthesis must prevent path escape and replay. OSS community driven: catalog-native support reduces repackaging. Pragmatic as npm: one-command installs need deterministic reuse and actionable failures.

Growth signal. Frame the release note around removing publisher repackaging friction without weakening validation.

Panel summary

Persona B R N Takeaway
Python Architect 1 1 0 Require per-component validation and one guarded materialization owner.
CLI Logging Expert 0 1 0 Make catalog failures accurate and actionable.
DevX UX Expert 1 2 0 Fix silent and partial failures before relying on this path.
Supply Chain Security Expert 2 1 0 Prevent path escapes and replayable failed synthesis.
OSS Growth Hacker 0 1 0 Add a user-facing compatibility release note.
Doc Writer 0 1 0 Document catalog-only marketplace packages.
Test Coverage Expert 0 2 0 Add scenario mapping and fixture-backed integration coverage.
Performance Expert 1 0 0 Track catalog metadata variants during consumer materialization.

B = blocking-severity findings, R = recommended, N = nits.
Counts are signal strength, not gates. The maintainer ships.

Top 5 follow-ups

  1. [Supply Chain Security Expert] (blocking-severity) Make synthesis path-safe and transactional so symlinks and cleanup failures cannot escape or replay rejected output.
  2. [Python Architect] (blocking-severity) Validate every declared LSP and MCP server at one canonical boundary and propagate materialization failures.
  3. [Performance Expert] (blocking-severity) Track deterministic catalog metadata variants without fragmenting the bare download cache.
  4. [Test Coverage Expert] Add scenario mapping and fixture-backed marketplace coverage for success and failure paths.
  5. [CLI Logging Expert] Surface accurate diagnostics, then document the contract and release note.

Architecture

classDiagram
    class MarketplacePlugin
    class DependencyReference
    class APMDependencyResolver
    class SharedDeps
    class PluginParser
    MarketplacePlugin --> DependencyReference : admitted metadata
    APMDependencyResolver --> SharedDeps : materializes
    SharedDeps --> PluginParser : synthesizes through
Loading
flowchart TD
    A[Marketplace catalog] --> B[Admit safe fields]
    B --> C[Resolve dependency]
    C --> D[Stage synthetic manifest]
    D --> E{Every server valid?}
    E -->|yes| F[Commit and validate]
    E -->|no| G[Reject and clean]
Loading

Recommendation

Fold transactional path safety, per-component fail-closed propagation, deterministic manifest-variant handling, integration coverage, diagnostics, and documentation into this PR before maintainer review.


Full per-persona findings

Python Architect

  • [blocking] Validate every declared catalog server, not merely each nonempty category at src/apm_cli/deps/_shared.py:31.
  • [recommended] Add a static boundary guard for the catalog materialization owner.

CLI Logging Expert

  • [recommended] Report catalog validation failures accurately instead of labeling them as download failures.

DevX UX Expert

  • [blocking] Invalid catalog metadata can be swallowed during resolver work.
  • [recommended] Mixed valid and invalid declarations can install partially.
  • [recommended] Document catalog-only extraction in the install contract.

Supply Chain Security Expert

  • [blocking] A dangling apm.yml symlink can redirect synthesis outside the package.
  • [blocking] Failed cleanup can leave a rejected generated manifest reusable on retry.
  • [recommended] Reject mixed valid and invalid declarations in full.

OSS Growth Hacker

  • [recommended] Add the marketplace compatibility fix to CHANGELOG.md.

Auth Expert -- inactive

The touched dependency and marketplace paths do not change authentication, token, credential, or host behavior.

Doc Writer

  • [recommended] Add the catalog-only path and fail-closed limits to the package-type reference and marketplace guide.

Test Coverage Expert

Performance Expert

  • [blocking] Warm installs can reuse a generated manifest for different catalog metadata because consumer materialization does not track the variant.

This panel is advisory. It does not block merge. Re-apply the panel-review label after addressing feedback to re-run.

@danielmeppiel

Copy link
Copy Markdown
Collaborator

APM Review Panel: needs_rework

PR #2709 resolves the major architecture and security defects; three bounded folds remain to protect release clarity, install confidence, and catalog-scale performance.

cc lkshrk (@lkshrk) Sergio Sisternes (@sergio-sisternes-epam) -- a fresh advisory pass is ready for your review.

The second pass converges positively: CI is green, focused security tests pass, and architecture, CLI logging, DevX, and supply-chain reviewers found no remaining major defect. The remaining work is narrow and in scope.

Remove the duplicate 0.29.0 heading, add a fixture-backed successful apm install test, and replace append-time linear dependency membership checks with a name index plus scaling guard.

Dissent. Documentation classifies the duplicate heading as blocking-severity while architecture and growth treat it as recommended. The higher signal fits because conflicting release sections weaken the durable public record and the correction is trivial.

Aligned with: Portable by manifest: prove the end-to-end install promise. Secure by default: focused security tests pass. OSS community driven: preserve a clear release record. Pragmatic as npm: directly test install and keep catalog merging predictably fast.

Growth signal. A clean release record and proven one-command install path reduce evaluation friction.

Panel summary

Persona B R N Takeaway
Python Architect 0 1 1 Architecture findings are resolved; remove the duplicate release heading.
CLI Logging Expert 0 0 0 Catalog failures now surface actionably.
DevX UX Expert 0 0 0 Silent and partial failures are resolved and documented.
Supply Chain Security Expert 0 0 0 Initial security issues are fixed and tested.
OSS Growth Hacker 0 1 0 Correct the duplicate release heading.
Doc Writer 1 0 0 Remove the conflicting duplicate release section.
Test Coverage Expert 0 1 0 Add successful full-install fixture coverage.
Performance Expert 0 1 0 Replace quadratic dependency merging with a name index.

B = blocking-severity findings, R = recommended, N = nits.
Counts are signal strength, not gates. The maintainer ships.

Top 3 follow-ups

  1. [Doc Writer] (blocking-severity) Remove the duplicate ## [0.29.0] - 2026-08-26 heading -- the public release record must be unambiguous.
  2. [Test Coverage Expert] Add a fixture-backed successful full apm install test -- direct resolver coverage does not prove the user command path.
  3. [Performance Expert] Use an O(n) name index in _union_dep_list and add a scaling guard -- append-time linear scans compound with catalog size.

Architecture

flowchart TD
    A[Marketplace catalog] --> B[Canonical materializer]
    B --> C[Stage manifest]
    C --> D{Every server valid?}
    D -->|yes| E[Atomic commit]
    D -->|no| F[Reject and clean]
    E --> G[Install pipeline]
Loading

Recommendation

Fold these three bounded changes, rerun CI, then ship.


Full per-persona findings

Python Architect

  • [recommended] Remove the duplicate 0.29.0 changelog heading.
  • [nit] Align the catalog metadata carrier name only if that field is changed later; no churn now.

CLI Logging Expert

No findings.

DevX UX Expert

No findings.

Supply Chain Security Expert

No findings.

OSS Growth Hacker

  • [recommended] Remove the duplicate and incorrectly dated v0.29.0 heading.

Auth Expert -- inactive

The marketplace and dependency changes do not alter auth behavior.

Doc Writer

  • [blocking] Remove the duplicate 0.29.0 heading with the conflicting date.

Test Coverage Expert

  • [recommended] Add a successful full install fixture test for catalog-only LSP and MCP metadata.

Performance Expert

  • [recommended] Replace _union_dep_list quadratic nested-dict membership checks with an O(n) name index and scaling guard.

This panel is advisory. It does not block merge. Re-apply the panel-review label after addressing feedback to re-run.

@danielmeppiel

Copy link
Copy Markdown
Collaborator

APM Review Panel: needs_rework

PR #2709 needs safety and portability rework before its generated-manifest cache can be trusted.

cc lkshrk (@lkshrk) Sergio Sisternes (@sergio-sisternes-epam) -- a fresh advisory pass is ready for your review.

The panel converges on three in-scope concerns. The strongest signals are a demonstrated cache-integrity weakness that permits appended undeclared dependencies to survive reuse, and checkout-root-dependent synthesis that makes equivalent metadata produce different bytes and hashes. Green CI does not outweigh these demonstrations.

The symlinked .apm rejection also needs an integration regression trap. Architecture, DevX, performance, growth, and documentation report no substantive concern. Consolidate repeated path-heavy diagnostics while revising this boundary.

Aligned with: Portable by manifest: identical metadata must hash identically across roots. Secure by default: validate complete cached content and reject symlinked .apm. Governed by policy: cached artifacts cannot add undeclared dependencies. Pragmatic as npm: emit one package-level diagnostic.

Panel summary

Persona B R N Takeaway
Python Architect 0 0 1 Preserve the centralized transaction shape.
CLI Logging Expert 0 2 0 Consolidate repeated errors and avoid absolute paths.
DevX UX Expert 0 0 0 Full success and failure paths pass.
Supply Chain Security Expert 2 0 0 Bind cache reuse to full bytes and remove root-dependent output.
OSS Growth Hacker 0 0 0 Changelog and marketplace framing are clear.
Doc Writer 0 0 0 Docs and changelog are accurate.
Test Coverage Expert 1 0 0 Add symlinked .apm integration coverage.
Performance Expert 0 0 0 Dependency union is linear and variant handling is bounded.

B = blocking-severity findings, R = recommended, N = nits.
Counts are signal strength, not gates. The maintainer ships.

Top 4 follow-ups

  1. [Supply Chain Security Expert] (blocking-severity) Validate complete generated manifest content before cache reuse -- a preserved header must not admit appended dependencies.
  2. [Supply Chain Security Expert] (blocking-severity) Remove absolute checkout-root substitution from generated bytes and hashes -- equivalent metadata must remain reproducible.
  3. [Test Coverage Expert] (blocking-severity) Add integration coverage proving a symlinked .apm directory is rejected without an outside write.
  4. [CLI Logging Expert] Emit one package-level failure using package identity instead of repeated absolute-path diagnostics.

Architecture

flowchart TD
    A[Catalog metadata] --> B[Build canonical expected bytes]
    B --> C{Existing generated bytes match?}
    C -->|yes| D[Reuse]
    C -->|no| E[Stage and validate]
    E --> F{Paths safe and all servers valid?}
    F -->|yes| G[Atomic commit]
    F -->|no| H[Reject and clean]
Loading

Recommendation

Fold the demonstrated cache-integrity and portability fixes, add the symlink integration trap, consolidate the diagnostic, and rerun CI.


Full per-persona findings

Python Architect

  • [nit] Preserve the current centralized transaction shape.

CLI Logging Expert

  • [recommended] Render catalog rejection once through CommandLogger.
  • [recommended] Name the marketplace package instead of its absolute checkout path.

DevX UX Expert

No findings.

Supply Chain Security Expert

  • [blocking] Do not trust the generated manifest header as a complete integrity check.
  • [blocking] Keep synthesized catalog manifests independent of checkout path.

OSS Growth Hacker

No findings.

Auth Expert -- inactive

The touched files do not affect authentication or credential resolution.

Doc Writer

No findings.

Test Coverage Expert

  • [blocking] Symlinked .apm rejection lacks a malicious-input integration test.

Performance Expert

No findings.

This panel is advisory. It does not block merge. Re-apply the panel-review label after addressing feedback to re-run.

@danielmeppiel

Copy link
Copy Markdown
Collaborator

APM Review Panel: ship_now

PR #2709 safely verifies generated marketplace catalogs while preserving portable manifests and clear failure diagnostics.

cc lkshrk (@lkshrk) Sergio Sisternes (@sergio-sisternes-epam) -- a fresh advisory pass is ready for your review.

The panel converges on shipping e5937dc. Security's focused tests and the full marketplace regression set pass; performance measured near-linear scaling and zero-RTT warm reuse; architecture, documentation, and CLI logging found no substantive issue.

The DevX diagnostic concern is outweighed by direct integration evidence: the user-visible output identifies invalid-catalog@local-mkt and contains invalid marketplace metadata exactly once. Captured stdlib logging is not a second Click terminal error. The optional changelog wording nit does not require code churn.

Dissent. DevX suggested further diagnostic consolidation, while the CLI logging expert verified the user-visible contract. The executed integration assertion is load-bearing, so the logging expert's conclusion prevails.

Aligned with: Portable by manifest: plugin-root placeholders remain portable on disk and resolve only in memory. Secure by default: canonical generated bytes are rebuilt before reuse and symlinked .apm paths fail closed. Pragmatic as npm: failures identify the marketplace once.

Panel summary

Persona B R N Takeaway
Python Architect 0 0 1 All architecture findings are resolved with one guarded owner.
CLI Logging Expert 0 0 0 One stable package-level diagnostic is verified.
DevX UX Expert 0 1 0 Install behavior is correct; it suggested optional recovery wording.
Supply Chain Security Expert 0 0 0 Full-byte repair, portable placeholders, and symlink defenses pass.
OSS Growth Hacker 0 0 1 Marketplace framing is clear; wording polish is optional.
Doc Writer 0 0 0 Docs, links, and changelog chronology are accurate.
Test Coverage Expert 0 0 0 Focused marketplace regressions, including .apm symlinks, pass.
Performance Expert 0 0 0 Dependency union is linear and warm reuse adds no network RTT.

B = blocking-severity findings, R = recommended, N = nits.
Counts are signal strength, not gates. The maintainer ships.

Architecture

flowchart TD
    A[Marketplace metadata] --> B[Canonical materializer]
    B --> C[Stage portable manifest]
    C --> D{Complete bytes and paths valid?}
    D -->|yes| E[Atomic commit]
    D -->|no| F[Reject and clean]
    E --> G[Resolve placeholders in memory]
    G --> H[Install and lock]
Loading

Recommendation

Ship the reviewed commit as-is; all checks are green and no substantive foldable item remains.

Folded in this run

  • (panel) Transactional, path-safe synthesis and cleanup -- resolved in 7a01860.
  • (panel) Per-component fail-closed validation and resolver error propagation -- resolved in 7a01860.
  • (panel) Warm manifest-variant rematerialization -- resolved in 7a01860.
  • (panel) Canonical owner table, static boundary, and architecture assertion -- resolved in 7a01860.
  • (panel) Fixture-backed successful and rejected full install paths -- resolved in be7c20c.
  • (panel) Linear dependency union and deterministic anti-scan test -- resolved in be7c20c.
  • (panel) Duplicate changelog release heading removal -- resolved in be7c20c.
  • (panel) Complete generated-byte verification before cache reuse -- resolved in e5937dc.
  • (panel) Checkout-root-independent bytes with in-memory placeholder resolution -- resolved in e5937dc.
  • (panel) Symlinked .apm integration regression trap -- resolved in e5937dc.
  • (panel) Single stable marketplace-identity diagnostic -- resolved in e5937dc.

Regression-trap evidence (mutation-break gate)

  • Per-component validation, symlink rejection, stage cleanup, variant handling, resolver error recording, full-install materialization, linear union, complete-byte repair, portable placeholders, marketplace identity, and AC35 were each removed in turn; their named regression tests failed as expected; every guard was restored.

Lint contract

uv run --frozen --extra dev ruff check src/ tests/ and uv run --frozen --extra dev ruff format --check src/ tests/ both passed at e5937dc. Pylint R0801, auth signals, architecture boundaries, file length, and diff checks also passed.

CI

All checks passed on CI run 33304715591 and Merge Gate 33304715670 after 1 CI recovery iteration.

Mergeability status

PR head SHA CEO stance iters folds defers Copilot rounds CI mergeable mergeStateStatus notes
#2709 e5937dc ship_now 4 11 0 2 green MERGEABLE BLOCKED pending required review

Convergence

4 outer iterations; 2 Copilot rounds with no inline comments. Final panel recommendation: ship_now.

Ready for maintainer review.


Full per-persona findings

Python Architect

No actionable findings. Preserve the centralized adapter plus transaction-script shape.

CLI Logging Expert

No findings. The package identity appears exactly once in the user-visible failure.

DevX UX Expert

  • [recommended] Suggested a more explicit recovery action. CEO arbitration declined this as non-load-bearing because the dedicated logging review and exact output assertion prove the current contract.

Supply Chain Security Expert

No findings. Full-byte cache repair, portable placeholder preservation, and symlink defenses passed focused probes.

OSS Growth Hacker

  • [nit] Optional user-outcome wording for the changelog entry.

Auth Expert -- inactive

The PR changes no authentication or credential-resolution surface.

Doc Writer

No findings.

Test Coverage Expert

No findings.

Performance Expert

No findings. Measured 1K-to-10K scaling remained near linear and warm reuse performed no network operation.

This panel is advisory. It does not block merge. Re-apply the panel-review label after addressing feedback to re-run.

lkshrk (lkshrk) and others added 6 commits August 30, 2026 16:30
Preserve admitted inline LSP/MCP metadata without trusting unrelated catalog fields.\n\nRefs microsoft#2708
Make catalog-only marketplace synthesis transactional, path-safe, variant-aware, and fail-closed per the review-panel follow-ups. Add canonical-owner guards, functional regression coverage, and user-facing documentation.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
apm-spec-waiver: Marketplace catalog compatibility translates admitted metadata into the existing OpenAPM manifest contract; it adds no normative OpenAPM requirement.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Exercise successful catalog-only installs through the real command path, keep dependency merging linear at catalog scale, and remove the merge-created duplicate release heading. Addresses final panel follow-ups.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Rebuild canonical generated bytes before cache reuse, keep plugin-root placeholders portable on disk and resolve them in memory, cover symlinked .apm rejection, and consolidate marketplace diagnostics. Addresses terminal panel findings.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@danielmeppiel
Daniel Meppiel (danielmeppiel) force-pushed the fix/metadata-only-marketplace-plugin branch from e5937dc to e56e5fa Compare August 30, 2026 14:33
@danielmeppiel

Copy link
Copy Markdown
Collaborator

Rebased onto current main at b68fcad -> e56e5fa.

Conflicting paths resolved (faithful merge of both intents):

  • apm.lock.yaml
  • docs/src/content/docs/reference/package-types.md

Lint contract: uv run --extra dev ruff check src/ tests/ and
uv run --extra dev ruff format --check src/ tests/ both silent
post-rebase.

Post-push mergeability: gh pr view --json mergeStateStatus,mergeable
reports BLOCKED / MERGEABLE. BLOCKED is the required-review gate, not a conflict. Push used
git push --force-with-lease=fix/metadata-only-marketplace-plugin:e5937dc830aa7a7765af321233081bbb9d6b3b37 author-fork HEAD:fix/metadata-only-marketplace-plugin (--force-with-lease, never bare --force).

Ready for maintainer review.

@danielmeppiel
Daniel Meppiel (danielmeppiel) merged commit 59b70a5 into microsoft:main Aug 30, 2026
22 checks passed
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] Metadata-only marketplace plugins fail package validation during install

3 participants