Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .apm/instructions/architecture.instructions.md
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ semicolon-delimited, and specific to the file(s) that own the fact.
| Local marketplace package-version manifest precedence | marketplace/version_check.py (_read_local_version) | `src/apm_cli/marketplace/version_check.py` |
| applyTo normalization and hidden-tool placement | utils/patterns.py (normalize_apply_to); compilation/context_optimizer.py (ContextOptimizer) | `src/apm_cli/utils/patterns.py`; `src/apm_cli/compilation/context_optimizer.py` |
| Effective marketplace output path | marketplace/output_profiles.py (resolve_effective_output_path) | `src/apm_cli/marketplace/output_profiles.py` |
| Marketplace metadata-enrichment outcome and certifiability | marketplace/builder.py (MetadataEnrichmentResult) | `src/apm_cli/marketplace/builder.py` |
| Bootstrap project-name validation and fallback | core/project_name.py (resolve_bootstrap_project_name) | `src/apm_cli/core/project_name.py` |
| Marketplace raw-structure diagnostics | marketplace/models.py parser; validator.py consumes them | `src/apm_cli/marketplace/models.py`; `src/apm_cli/marketplace/validator.py` |
| Agent Plugins v1 contract interpretation, component discovery, and portable manifest authority | agent_plugins/loader.py (load_agent_plugin, _load_apm_configuration) | `src/apm_cli/agent_plugins/loader.py`; `src/apm_cli/agent_plugins/ir.py` |
Expand Down
1 change: 1 addition & 0 deletions .github/instructions/architecture.instructions.md
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ semicolon-delimited, and specific to the file(s) that own the fact.
| Local marketplace package-version manifest precedence | marketplace/version_check.py (_read_local_version) | `src/apm_cli/marketplace/version_check.py` |
| applyTo normalization and hidden-tool placement | utils/patterns.py (normalize_apply_to); compilation/context_optimizer.py (ContextOptimizer) | `src/apm_cli/utils/patterns.py`; `src/apm_cli/compilation/context_optimizer.py` |
| Effective marketplace output path | marketplace/output_profiles.py (resolve_effective_output_path) | `src/apm_cli/marketplace/output_profiles.py` |
| Marketplace metadata-enrichment outcome and certifiability | marketplace/builder.py (MetadataEnrichmentResult) | `src/apm_cli/marketplace/builder.py` |
| Bootstrap project-name validation and fallback | core/project_name.py (resolve_bootstrap_project_name) | `src/apm_cli/core/project_name.py` |
| Marketplace raw-structure diagnostics | marketplace/models.py parser; validator.py consumes them | `src/apm_cli/marketplace/models.py`; `src/apm_cli/marketplace/validator.py` |
| Agent Plugins v1 contract interpretation, component discovery, and portable manifest authority | agent_plugins/loader.py (load_agent_plugin, _load_apm_configuration) | `src/apm_cli/agent_plugins/loader.py`; `src/apm_cli/agent_plugins/ir.py` |
Expand Down
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
(by @MohammedAlkindi; closes #2639) (#2645)
- `apm install` now resolves positional virtual-subdirectory git semver ranges before literal-ref preflight, while preserving registry version validation. (by @aryansk; closes #2514) (#2590)
- `apm uninstall --global` now cleans removed-only target files before deleting their ownership state, while preserving files owned by surviving packages. (#2658)
- `apm pack` now reports unavailable remote package metadata, exposes its
certifiability in JSON, and prevents `--check-clean` from certifying a
degraded regeneration. `--strict-metadata` exits before writing an incomplete
marketplace artifact. (closes #2524)
Comment on lines +58 to +61
- Windows binary is now Authenticode-signed in the release workflow, eliminating
the `Trojan:Script/Wacatac.H!ml` Windows Defender false positive on unsigned
PyInstaller bundles. (#2435)
Expand Down
4 changes: 2 additions & 2 deletions apm.lock.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2783,7 +2783,7 @@ deployments:
owners:
- .
active_owner: .
content_hash: sha256:c085444fd1341c4a8daf421fa1403c41200bf8f077fd187fe04633f6384a553a
content_hash: sha256:f79f633b93e55cf577df2b29a5cbe559a26462776d1d846d08254082feea2bf2
- kind: project-relative
target: copilot
value: .github/instructions/changelog.instructions.md
Expand Down Expand Up @@ -3290,7 +3290,7 @@ local_deployed_file_hashes:
.github/agents/spec-tag-architect.agent.md: sha256:82907265c5e7cf1ac61ad96866fa7c5683b69c8f09b7a4c5f3cc241acc9568ca
.github/agents/supply-chain-security-expert.agent.md: sha256:8fb8cc426d6af17ba084a28b3f026c2b475b62e3ca63ed2f88b83bd823f877af
.github/agents/test-coverage-expert.agent.md: sha256:48c2172d1f18a394fa83ef9dc2be0b9b921a4e51e976498165250fed66369711
.github/instructions/architecture.instructions.md: sha256:c085444fd1341c4a8daf421fa1403c41200bf8f077fd187fe04633f6384a553a
.github/instructions/architecture.instructions.md: sha256:f79f633b93e55cf577df2b29a5cbe559a26462776d1d846d08254082feea2bf2
.github/instructions/changelog.instructions.md: sha256:1e51ec4c74e847967962bd279dc4c6e582c5d3578490b3c28d5f3acd3e05f73e
.github/instructions/cicd.instructions.md: sha256:33201cb88ea2f34b4950a9b52f87dc8dfb682796aaf53068ba7ae406c0c5e2c2
.github/instructions/cli.instructions.md: sha256:8e39e8d5047ce88575cb02f87c2bcede584dfef258bd86f7466c7badf136541a
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,7 @@ apm pack --offline # cached refs only
apm pack --include-prerelease # allow pre-release tags
apm pack -v # per-entry resolution detail
apm pack --marketplace=claude --json # JSON output for CI pipelines
apm pack --strict-metadata # require remote Claude package metadata fetches
```

For the release-gate flags (`--check-versions`, `--check-clean`),
Expand Down
50 changes: 33 additions & 17 deletions docs/src/content/docs/producer/releasing-from-any-ci.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@ shell-script translation of these lines.
set -euo pipefail
VERSION="${VERSION:?VERSION must be set, e.g. v1.2.3}"

apm pack --check-versions --check-clean --json > pack-report.json
apm pack --check-versions --check-clean --dry-run --json > pack-report.json
apm pack --check-versions --strict-metadata

for f in build/*.zip .claude-plugin/marketplace.json; do
[ -f "$f" ] || continue
Expand All @@ -37,12 +38,16 @@ gh release create "$VERSION" \

What each command does:

- `apm pack --check-versions --check-clean --json` runs the pack with
the release gates enabled. `--check-versions` fails if per-package
- `apm pack --check-versions --check-clean --dry-run --json` verifies
the committed artifacts without writing them. `--check-versions` fails if per-package
versions disagree with `marketplace.versioning.strategy`.
`--check-clean` fails if the on-disk `marketplace.json` does not
match what a fresh pack would produce. `--json` writes a
machine-readable summary to stdout; human logs go to stderr.
match what a fresh pack would produce, or if remote Claude package metadata
could not be fetched to certify that regeneration -- see
[Marketplace artifacts](../../reference/cli/pack/#marketplace-artifacts)
for the failure modes. `apm pack --check-versions --strict-metadata`
generates the release artifacts only after remote metadata is certifiable.
`--json` writes a machine-readable summary to stdout; human logs go to stderr.
- `sha256sum` produces one sidecar per artifact. Consumers verify
with `sha256sum -c <file>.sha256`.
- `gh release create` uploads the bundle, the marketplace artifact,
Expand Down Expand Up @@ -76,11 +81,13 @@ jobs:

[`microsoft/apm-action@v1`](https://github.com/microsoft/apm-action)
with `mode: release` is a convenience wrapper for the canonical
sequence above. It installs the CLI, runs `apm pack
--check-versions --check-clean --json`, generates the sidecars, and
sequence above. It installs the CLI, verifies with `apm pack
--check-versions --check-clean --dry-run --json`, generates the artifacts
and sidecars, and
calls `gh release create` against the pushed tag. Use it when you
want one less script to maintain; use the raw `run:` form below when
you need to customise any step.
you need to customise any step, including `--strict-metadata`
certification before artifact generation.

> **Reference deployment.** [`DevExpGbb/zava-agent-config`](https://github.com/DevExpGbb/zava-agent-config)
> runs this exact pipeline. The
Expand All @@ -102,7 +109,8 @@ artifact format.
with: { python-version: "3.12" }
- run: pip install apm-cli
- run: |
apm pack --check-versions --check-clean --json > pack-report.json
apm pack --check-versions --check-clean --dry-run --json > pack-report.json
apm pack --check-versions --strict-metadata
for f in build/*.zip .claude-plugin/marketplace.json; do
[ -f "$f" ] || continue
sha256sum "$f" > "${f}.sha256"
Expand All @@ -125,7 +133,8 @@ release:
- if: '$CI_COMMIT_TAG =~ /^v/'
script:
- pip install apm-cli
- apm pack --check-versions --check-clean --json > pack-report.json
- apm pack --check-versions --check-clean --dry-run --json > pack-report.json
- apm pack --check-versions --strict-metadata
- |
for f in build/*.zip .claude-plugin/marketplace.json; do
[ -f "$f" ] || continue
Expand All @@ -149,7 +158,8 @@ pipeline {
steps {
sh '''
pip install apm-cli
apm pack --check-versions --check-clean --json > pack-report.json
apm pack --check-versions --check-clean --dry-run --json > pack-report.json
apm pack --check-versions --strict-metadata
for f in build/*.zip .claude-plugin/marketplace.json; do
[ -f "$f" ] || continue
sha256sum "$f" > "${f}.sha256"
Expand All @@ -176,7 +186,8 @@ steps:
- task: UsePythonVersion@0
inputs: { versionSpec: "3.12" }
- script: pip install apm-cli
- script: apm pack --check-versions --check-clean --json > pack-report.json
- script: apm pack --check-versions --check-clean --dry-run --json > pack-report.json
- script: apm pack --check-versions --strict-metadata
- script: |
for f in build/*.zip .claude-plugin/marketplace.json; do
[ -f "$f" ] || continue
Expand All @@ -201,11 +212,16 @@ steps:
| 1 | runtime | Build or network error. Inspect the JSON report; rerun. |
| 2 | schema | `apm.yml` is invalid. Fix the manifest before tagging. |
| 3 | `--check-versions`| Per-package versions disagree with `marketplace.versioning.strategy`. See [Versioning strategies](../versioning-strategies/). |
| 4 | `--check-clean` | Committed `marketplace.json` does not match a fresh pack. Run `apm pack` locally, commit the diff (or `git commit --amend --no-edit` to fold into the current commit), then re-tag and push the updated tag (`git tag -f vX.Y.Z && git push --force-with-lease origin vX.Y.Z`). |

The gates never write to disk -- they only refuse to release.
Recover by running the same `apm pack` locally without `--check-*`,
inspecting the diff, and pushing a clean tag.
| 4 | `--check-clean` | Committed `marketplace.json` does not match a fresh pack, or remote Claude package metadata was unfetchable. For drift, run `apm pack` locally, commit the diff, then re-tag. For metadata unavailability, restore the remote source or CI credentials and rerun; committing a regenerated file cannot certify unavailable metadata. |
| 5 | `--strict-metadata`| Remote Claude package metadata could not be fetched, so `apm pack` refused to write. Retry with network access, or omit `--strict-metadata` when the default warning is acceptable. |

`--check-versions` and `--check-clean` are validation-only and never
write to disk. `--strict-metadata` certifies metadata before the
subsequent pack writes artifacts. Recover drift by running `apm pack`
locally without `--check-*`, inspecting the diff, and pushing a clean
tag. For metadata unavailability, restore the remote source or CI
credentials instead; regenerating a file cannot certify missing
metadata.

:::note
`microsoft/apm-action@v1` is a thin convenience wrapper, not a new
Expand Down
15 changes: 12 additions & 3 deletions docs/src/content/docs/reference/cli/pack.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,11 @@ Bundles are target-agnostic. The consumer's project decides where files land at
| `--include-prerelease` | off | Marketplace: allow pre-release tags to satisfy version ranges. |
| `-m`, `--marketplace FORMATS` | all configured | Comma-separated list of marketplace formats to build. Sentinels: `all` (every configured format), `none` (skip marketplace entirely). |
| `--marketplace-path FORMAT=PATH` | manifest default | Override the output path for a specific format. Repeatable. Example: `--marketplace-path codex=./dist/codex.json`. |
| `--json` | off | Emit machine-readable JSON to stdout. All logs move to stderr. Shape: `{ok, dry_run, warnings, errors, marketplace: {outputs: [...]}}`. |
| `--json` | off | Emit machine-readable JSON to stdout. All logs move to stderr. Shape: `{ok, dry_run, warnings, errors, metadata_enrichment: {certifiable, outcomes: [...]}, marketplace: {outputs: [...]}}`. |
| `--legacy-skill-paths` | off | Bundle skills under per-client paths (e.g. `.cursor/skills/`) instead of the converged `.agents/skills/`. Compatibility flag. |
| `--check-versions` | off | Release gate: verify per-package versions agree with the configured `marketplace.versioning.strategy` (`lockstep`, `tag_pattern`, or `per_package`). Exits `3` on misalignment. Composes with `--check-clean` and `--dry-run`. |
| `--check-clean` | off | Release gate: regenerate every configured marketplace output to a temp representation and diff against the same effective path used by `apm pack`, including `--marketplace-path` overrides. Exits `4` for drift. Combine with `--dry-run` to compare without normal pack output generation. |
| `--check-clean` | off | Release gate: regenerate every configured marketplace output to a temp representation and diff against the same effective path used by `apm pack`, including `--marketplace-path` overrides. Exits `4` for drift or for remote Claude metadata that can't be fetched to certify the regeneration. Combine with `--dry-run` to compare without normal pack output generation. |
| `--strict-metadata` | off | Claude marketplace: fail before writing when remote package metadata cannot be fetched. Use it in publishing CI to require those fetches to succeed. Exits `5`. |
| `--target`, `-t VALUE` | auto-detect | **Deprecated.** Recorded as informational `pack.target` metadata only; ignored by `apm install`. Will be removed in a future release. |

:::caution[Migrating automation from `.tar.gz`?]
Expand Down Expand Up @@ -170,6 +171,13 @@ dependencies:

Configure marketplace artifact paths in `apm.yml` with the `marketplace.outputs` map, keyed by format. Use `--marketplace-path FORMAT=PATH` to override per-format output paths at pack time.

Remote Claude entries can inherit `description` and `version` from their own
`apm.yml`. If APM cannot fetch that metadata, normal packing writes the artifact
with an actionable warning so authors can add those fields to the marketplace
entry or retry with network access. Use `--strict-metadata` in publishing CI to
fail before writing with uncertifiable remote metadata. `--check-clean` also fails with exit
`4` rather than certifying a regeneration whose metadata could not be fetched.

### Plugin manifests

Ship one APM package; consumers get a native plugin for their tool of choice. When `apm.yml` declares a [`target:`](../../manifest-schema/#36-target) (or `targets:`) field containing `claude` or `copilot`, `apm pack` generates an ecosystem-specific `plugin.json` so the same source tree drops into a Claude Code plugin directory or a Copilot plugin path with no hand-editing.
Expand Down Expand Up @@ -244,7 +252,8 @@ Plugin manifest generation runs after BUNDLE and MARKETPLACE phases so the gener
| `1` | Build or runtime error: network failure, ref not found, no tag matches a marketplace range, lockfile read error, or unhandled packer exception. |
| `2` | `apm.yml` schema validation error. |
| `3` | `--check-versions` failed: per-package versions disagree with the configured marketplace versioning strategy. |
| `4` | `--check-clean` failed: marketplace working tree is dirty (regenerated output differs from on-disk file). |
| `4` | `--check-clean` failed: marketplace working tree is dirty (regenerated output differs from on-disk file), or remote Claude metadata could not be fetched to certify the comparison. |
| `5` | `--strict-metadata` failed: remote marketplace metadata was unavailable, so APM did not write the artifact. |

## Related

Expand Down
Loading
Loading