apm-cli 0.31.0__tar.gz → 0.32.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {apm_cli-0.31.0/src/apm_cli.egg-info → apm_cli-0.32.0}/PKG-INFO +2 -2
- {apm_cli-0.31.0 → apm_cli-0.32.0}/pyproject.toml +2 -2
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/cache/git_cache.py +28 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/cli.py +123 -17
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/commands/_helpers.py +43 -21
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/commands/deps/_utils.py +15 -9
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/commands/doctor.py +2 -2
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/commands/marketplace/check.py +11 -9
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/commands/prune.py +11 -16
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/core/deployment_ledger.py +25 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/deps/apm_resolver.py +47 -8
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/deps/github_downloader.py +18 -8
- apm_cli-0.32.0/src/apm_cli/deps/immutable_requirements.py +208 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/deps/lockfile.py +17 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/deps/tiered_ref_resolver.py +25 -6
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/install/context.py +1 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/install/helpers/ref_reuse.py +9 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/install/legacy_plugin_compat.py +17 -5
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/install/phases/download.py +3 -5
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/install/phases/integrate.py +3 -6
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/install/phases/lockfile.py +26 -2
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/install/phases/resolve.py +12 -8
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/install/pipeline.py +2 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/install/resolution_staging.py +11 -3
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/install/service.py +3 -3
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/integration/base_integrator.py +11 -1
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/integration/hook_integrator.py +2 -2
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/models/dependency/materialization.py +21 -2
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/models/dependency/object_fields.py +8 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/models/dependency/reference.py +1 -4
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/models/dependency/registry_entry.py +2 -11
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/models/manifest_contract.py +8 -3
- {apm_cli-0.31.0 → apm_cli-0.32.0/src/apm_cli.egg-info}/PKG-INFO +2 -2
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli.egg-info/SOURCES.txt +1 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli.egg-info/requires.txt +1 -1
- {apm_cli-0.31.0 → apm_cli-0.32.0}/tests/test_apm_resolver.py +30 -14
- {apm_cli-0.31.0 → apm_cli-0.32.0}/AUTHORS +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/LICENSE +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/NOTICE +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/README.md +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/setup.cfg +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/__init__.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/adapters/__init__.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/adapters/client/__init__.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/adapters/client/_mcp_runtime_args.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/adapters/client/antigravity.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/adapters/client/base.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/adapters/client/claude.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/adapters/client/codex.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/adapters/client/copilot.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/adapters/client/cursor.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/adapters/client/gemini.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/adapters/client/hermes.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/adapters/client/intellij.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/adapters/client/kiro.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/adapters/client/opencode.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/adapters/client/vscode.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/adapters/client/windsurf.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/adapters/package_manager/__init__.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/adapters/package_manager/base.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/adapters/package_manager/default_manager.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/adopt/__init__.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/adopt/discovery.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/adopt/manifest_edit.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/adopt/materialize.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/adopt/render.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/adopt/safety.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/agent_plugins/__init__.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/agent_plugins/assets.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/agent_plugins/constants.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/agent_plugins/errors.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/agent_plugins/io.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/agent_plugins/ir.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/agent_plugins/loader.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/agent_plugins/projection.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/agent_plugins/validation.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/bootstrap_mirror.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/bundle/__init__.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/bundle/agent_plugin_exporter.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/bundle/attest.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/bundle/claude_plugin_exporter.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/bundle/export_common.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/bundle/formats.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/bundle/local_bundle.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/bundle/lockfile_enrichment.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/bundle/packer.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/bundle/plugin_exporter.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/bundle/plugin_layout.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/bundle/reproducible_archive.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/bundle/unpacker.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/cache/__init__.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/cache/cleanup.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/cache/http_cache.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/cache/integrity.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/cache/locking.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/cache/paths.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/cache/url_normalize.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/commands/__init__.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/commands/_apm_yml_writer.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/commands/approve.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/commands/audit.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/commands/cache.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/commands/compile/__init__.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/commands/compile/cli.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/commands/compile/watcher.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/commands/config.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/commands/deps/__init__.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/commands/deps/cli.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/commands/deps/why.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/commands/discover.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/commands/experimental.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/commands/find.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/commands/init.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/commands/install.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/commands/lifecycle.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/commands/list_cmd.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/commands/lock.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/commands/marketplace/__init__.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/commands/marketplace/audit.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/commands/marketplace/doctor.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/commands/marketplace/init.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/commands/marketplace/migrate.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/commands/marketplace/outdated.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/commands/marketplace/plugin/__init__.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/commands/marketplace/plugin/add.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/commands/marketplace/plugin/remove.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/commands/marketplace/plugin/set.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/commands/marketplace/validate.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/commands/mcp.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/commands/outdated.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/commands/pack.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/commands/plugin/__init__.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/commands/plugin/init.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/commands/policy.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/commands/publish.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/commands/run.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/commands/runtime.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/commands/self_update.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/commands/targets.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/commands/uninstall/__init__.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/commands/uninstall/cli.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/commands/uninstall/engine.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/commands/uninstall/lockfile_state.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/commands/update.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/commands/view.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/compilation/__init__.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/compilation/agents_compiler.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/compilation/build_id.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/compilation/claude_formatter.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/compilation/constants.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/compilation/constitution.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/compilation/constitution_block.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/compilation/context_optimizer.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/compilation/distributed_compiler.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/compilation/footer.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/compilation/gemini_formatter.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/compilation/injector.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/compilation/inventory.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/compilation/link_resolver.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/compilation/managed_section.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/compilation/output_writer.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/compilation/root_context_protection.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/compilation/template_builder.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/compilation/user_root_context.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/config.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/constants.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/copilot_plugins/__init__.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/copilot_plugins/capability.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/copilot_plugins/catalog.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/copilot_plugins/constants.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/copilot_plugins/registrar.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/copilot_plugins/settings.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/core/__init__.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/core/_child_tls/__init__.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/core/_child_tls/_apm_tls.pth +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/core/_child_tls/_apm_tls_bootstrap.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/core/apm_yml.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/core/auth.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/core/azure_cli.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/core/build_orchestrator.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/core/command_logger.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/core/conflict_detector.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/core/deployment_state.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/core/docker_args.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/core/errors.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/core/experimental.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/core/host_providers.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/core/install_audit.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/core/lifecycle_scripts.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/core/null_logger.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/core/operations.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/core/output_mode.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/core/plugin_manifest.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/core/project_name.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/core/safe_installer.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/core/scope.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/core/script_executors.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/core/script_runner.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/core/script_trust.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/core/target_catalog.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/core/target_detection.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/core/tls_trust.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/core/token_manager.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/deps/__init__.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/deps/_shared.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/deps/aggregator.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/deps/artifactory_entry.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/deps/artifactory_orchestrator.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/deps/bare_cache.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/deps/clone_engine.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/deps/dependency_graph.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/deps/download_strategies.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/deps/git_auth_env.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/deps/git_file_transport.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/deps/git_reference_resolver.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/deps/git_remote_ops.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/deps/git_semver_resolver.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/deps/github_downloader_validation.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/deps/github_rate_limit.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/deps/host_backends.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/deps/installed_package.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/deps/outdated_ref_cache.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/deps/outdated_row.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/deps/package_validator.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/deps/path_anchoring.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/deps/plugin_parser.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/deps/reachability.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/deps/registry/__init__.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/deps/registry/auth.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/deps/registry/client.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/deps/registry/config_loader.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/deps/registry/extractor.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/deps/registry/feature_gate.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/deps/registry/outdated.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/deps/registry/resolver.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/deps/registry/semver.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/deps/registry_proxy.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/deps/revision_pins.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/deps/shared_clone_cache.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/deps/transport_selection.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/deps/verifier.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/deps/why_walker.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/drift.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/export/__init__.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/export/authoring.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/export/declared_license.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/export/formats.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/export/purl.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/export/sbom.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/export/spdx.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/export/spdx_data.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/factory.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/hook_contract.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/install/__init__.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/install/argv.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/install/artifactory_resolver.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/install/audit_replay.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/install/audit_target_roots.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/install/cache_pin.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/install/deployable_source_plan.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/install/deployed_paths.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/install/drift.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/install/drift_render.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/install/dry_run_plan.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/install/errors.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/install/exec_gate.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/install/finalization.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/install/gitlab_resolver.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/install/heals/__init__.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/install/heals/base.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/install/heals/branch_ref_drift.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/install/heals/buggy_lockfile_recovery.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/install/helpers/__init__.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/install/helpers/no_work.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/install/helpers/ref_seed.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/install/helpers/security_scan.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/install/insecure_policy.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/install/integrity.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/install/local_bundle_handler.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/install/local_bundle_paths.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/install/locking.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/install/lsp/__init__.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/install/lsp/integration.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/install/manifest_helpers.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/install/manifest_reconcile.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/install/mcp/__init__.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/install/mcp/args.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/install/mcp/command.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/install/mcp/conflicts.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/install/mcp/entry.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/install/mcp/integration.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/install/mcp/ownership.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/install/mcp/registry.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/install/mcp/warnings.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/install/mcp/writer.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/install/native_plugin_admission.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/install/outcome.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/install/package_resolution.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/install/package_selection.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/install/phases/__init__.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/install/phases/_redownload.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/install/phases/_skip_logic.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/install/phases/audit.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/install/phases/cleanup.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/install/phases/copilot_plugins.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/install/phases/finalize.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/install/phases/heal.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/install/phases/local_content.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/install/phases/policy_gate.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/install/phases/policy_target_check.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/install/phases/post_deps_local.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/install/phases/targets.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/install/plan.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/install/presentation/__init__.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/install/presentation/dry_run.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/install/primitive_classification.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/install/registry_wiring.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/install/request.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/install/root_redirect.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/install/service_integration.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/install/services.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/install/skill_path_migration.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/install/source_helpers.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/install/sources.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/install/summary.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/install/target_filter.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/install/target_hints.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/install/target_warnings.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/install/template.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/install/transaction.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/install/validation.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/integration/__init__.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/integration/_hook_dropped_targets.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/integration/_shared.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/integration/agent_integrator.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/integration/canvas_integrator.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/integration/cleanup.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/integration/command_integrator.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/integration/copilot_app_db.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/integration/copilot_app_project.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/integration/copilot_app_workflow_integrator.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/integration/copilot_app_ws.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/integration/copilot_cowork_paths.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/integration/coverage.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/integration/dispatch.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/integration/hook_bundle.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/integration/hook_command_paths.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/integration/hook_command_warnings.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/integration/hook_file_routing.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/integration/hook_ir.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/integration/hook_native_formats.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/integration/hook_ownership.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/integration/hook_reintegration.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/integration/hook_source_selection.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/integration/instruction_integrator.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/integration/kiro_hook_integrator.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/integration/lsp_integrator.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/integration/mcp_config_view.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/integration/mcp_integrator.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/integration/mcp_integrator_install.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/integration/opencode_frontmatter.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/integration/prompt_integrator.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/integration/skill_integrator.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/integration/skill_package_routing.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/integration/skill_support.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/integration/skill_transformer.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/integration/targets.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/integration/utils.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/marketplace/__init__.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/marketplace/_git_utils.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/marketplace/_io.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/marketplace/_shared.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/marketplace/audit.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/marketplace/auth_helpers.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/marketplace/builder.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/marketplace/client.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/marketplace/diagnostics.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/marketplace/drift_check.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/marketplace/errors.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/marketplace/git_stderr.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/marketplace/init_template.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/marketplace/migration.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/marketplace/models.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/marketplace/output_mappers.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/marketplace/output_profiles.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/marketplace/ref_resolver.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/marketplace/registry.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/marketplace/resolver.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/marketplace/semver.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/marketplace/shadow_detector.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/marketplace/source_identity.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/marketplace/tag_pattern.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/marketplace/validator.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/marketplace/version_check.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/marketplace/version_pins.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/marketplace/version_resolver.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/marketplace/yml_editor.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/marketplace/yml_schema.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/models/__init__.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/models/apm_package.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/models/dependency/__init__.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/models/dependency/host_virtual.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/models/dependency/identity.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/models/dependency/lsp.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/models/dependency/mcp.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/models/dependency/provider_coordinates.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/models/dependency/selection.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/models/dependency/subsets.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/models/dependency/types.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/models/format_detection.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/models/plugin.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/models/results.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/models/validation.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/output/__init__.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/output/formatters.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/output/models.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/output/script_formatters.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/policy/__init__.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/policy/_constraint_pinning.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/policy/_gitlab.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/policy/_help_text.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/policy/_shared.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/policy/ci_checks.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/policy/discovery.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/policy/inheritance.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/policy/install_preflight.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/policy/matcher.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/policy/models.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/policy/outcome_routing.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/policy/parser.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/policy/policy_checks.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/policy/project_config.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/policy/schema.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/primitives/__init__.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/primitives/discovery.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/primitives/models.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/primitives/parser.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/registry/__init__.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/registry/client.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/registry/integration.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/registry/operations.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/runtime/__init__.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/runtime/base.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/runtime/codex_runtime.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/runtime/copilot_runtime.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/runtime/factory.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/runtime/llm_runtime.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/runtime/manager.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/runtime/registry.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/runtime/utils.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/security/__init__.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/security/audit_report.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/security/content_scanner.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/security/executables.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/security/external/__init__.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/security/external/base.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/security/external/gate.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/security/external/generic_sarif.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/security/external/options.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/security/external/registry.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/security/external/runner.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/security/external/sarif_ingest.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/security/external/skillspector.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/security/file_scanner.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/security/gate.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/update_policy.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/utils/__init__.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/utils/archive.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/utils/atomic_io.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/utils/console.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/utils/content_hash.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/utils/diagnostics.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/utils/exclude.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/utils/file_ops.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/utils/git_env.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/utils/git_sparse.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/utils/github_host.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/utils/guards.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/utils/helpers.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/utils/install_tui.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/utils/net.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/utils/normalization.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/utils/path_security.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/utils/paths.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/utils/patterns.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/utils/perf_stats.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/utils/reflink.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/utils/short_sha.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/utils/staging_guard.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/utils/subprocess_env.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/utils/version_checker.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/utils/yaml_io.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/version.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/workflow/__init__.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/workflow/discovery.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/workflow/parser.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli/workflow/runner.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli.egg-info/dependency_links.txt +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli.egg-info/entry_points.txt +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/src/apm_cli.egg-info/top_level.txt +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/tests/test_apm_package_models.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/tests/test_codex_docker_args_fix.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/tests/test_codex_empty_string_and_defaults.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/tests/test_collision_integration.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/tests/test_console.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/tests/test_distributed_compilation.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/tests/test_empty_string_and_defaults.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/tests/test_enhanced_discovery.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/tests/test_github_downloader.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/tests/test_github_downloader_token_precedence.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/tests/test_gitlab_git_transport.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/tests/test_lockfile.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/tests/test_runnable_prompts.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/tests/test_runtime_manager_token_precedence.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/tests/test_token_manager.py +0 -0
- {apm_cli-0.31.0 → apm_cli-0.32.0}/tests/test_virtual_package_multi_install.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: apm-cli
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.32.0
|
|
4
4
|
Summary: MCP configuration tool
|
|
5
5
|
Author-email: Daniel Meppiel <user@example.com>
|
|
6
6
|
License: MIT License
|
|
@@ -67,7 +67,7 @@ Requires-Dist: pylint>=3.0.0; extra == "dev"
|
|
|
67
67
|
Requires-Dist: hypothesis>=6.0.0; extra == "dev"
|
|
68
68
|
Requires-Dist: mutmut==3.6.0; extra == "dev"
|
|
69
69
|
Provides-Extra: build
|
|
70
|
-
Requires-Dist: pyinstaller>=6.
|
|
70
|
+
Requires-Dist: pyinstaller>=6.17.0; extra == "build"
|
|
71
71
|
Dynamic: license-file
|
|
72
72
|
|
|
73
73
|
# APM – Agent Package Manager
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "apm-cli"
|
|
7
|
-
version = "0.
|
|
7
|
+
version = "0.32.0"
|
|
8
8
|
description = "MCP configuration tool"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.10"
|
|
@@ -56,7 +56,7 @@ dev = [
|
|
|
56
56
|
"mutmut==3.6.0",
|
|
57
57
|
]
|
|
58
58
|
build = [
|
|
59
|
-
"pyinstaller>=6.
|
|
59
|
+
"pyinstaller>=6.17.0",
|
|
60
60
|
]
|
|
61
61
|
|
|
62
62
|
[project.scripts]
|
|
@@ -33,6 +33,7 @@ import re
|
|
|
33
33
|
import subprocess
|
|
34
34
|
from pathlib import Path
|
|
35
35
|
|
|
36
|
+
from ..utils.atomic_io import atomic_write_text
|
|
36
37
|
from ..utils.git_sparse import apply_sparse_cone, repair_dangling_cone_symlinks
|
|
37
38
|
from ..utils.path_security import ensure_path_within
|
|
38
39
|
from .integrity import verify_checkout_sha
|
|
@@ -278,6 +279,31 @@ class GitCache:
|
|
|
278
279
|
promisor_url=url if use_partial else None,
|
|
279
280
|
)
|
|
280
281
|
|
|
282
|
+
def _resolved_ref_path(self, url: str, ref: str) -> Path:
|
|
283
|
+
digest = hashlib.sha256(ref.encode("utf-8")).hexdigest()
|
|
284
|
+
path = self._db_root / f"{cache_shard_key(url)}-{digest}.ref"
|
|
285
|
+
ensure_path_within(path, self._db_root)
|
|
286
|
+
return path
|
|
287
|
+
|
|
288
|
+
def remember_resolved_ref(self, url: str, ref: str, sha: str) -> None:
|
|
289
|
+
"""Persist an authorized remote observation independently of bare flavor."""
|
|
290
|
+
if not ref or not _SHA_RE.fullmatch(sha):
|
|
291
|
+
raise ValueError("A remote ref observation requires a ref and full SHA")
|
|
292
|
+
path = self._resolved_ref_path(url, ref)
|
|
293
|
+
with shard_lock(path):
|
|
294
|
+
atomic_write_text(path, sha.lower(), new_file_mode=0o600)
|
|
295
|
+
|
|
296
|
+
def read_resolved_ref(self, url: str, ref: str) -> tuple[bool, str | None]:
|
|
297
|
+
"""Return receipt presence and SHA; corrupt receipts must not revive old refs."""
|
|
298
|
+
path = self._resolved_ref_path(url, ref)
|
|
299
|
+
try:
|
|
300
|
+
sha = path.read_text(encoding="ascii")
|
|
301
|
+
except FileNotFoundError:
|
|
302
|
+
return False, None
|
|
303
|
+
except (OSError, UnicodeError):
|
|
304
|
+
return True, None
|
|
305
|
+
return True, sha if _SHA_RE.fullmatch(sha) else None
|
|
306
|
+
|
|
281
307
|
def _record_checkout_access(self, checkout_dir: Path) -> Path:
|
|
282
308
|
"""Record successful reuse of a finalized checkout under its shard lock."""
|
|
283
309
|
# Pruning ages the shared SHA root, not individual checkout variants.
|
|
@@ -960,6 +986,8 @@ class GitCache:
|
|
|
960
986
|
if entry.is_dir(follow_symlinks=False) and not entry.name.endswith(".lock"):
|
|
961
987
|
db_count += 1
|
|
962
988
|
total_size += _dir_size(Path(entry.path))
|
|
989
|
+
elif entry.name.endswith(".ref") and entry.is_file(follow_symlinks=False):
|
|
990
|
+
total_size += entry.stat(follow_symlinks=False).st_size
|
|
963
991
|
|
|
964
992
|
if self._checkouts_root.is_dir():
|
|
965
993
|
for shard_entry in os.scandir(str(self._checkouts_root)):
|
|
@@ -6,6 +6,7 @@ Thin wiring layer -- all command logic lives in ``apm_cli.commands.*`` modules.
|
|
|
6
6
|
# ruff: noqa: E402
|
|
7
7
|
|
|
8
8
|
import ctypes
|
|
9
|
+
import importlib
|
|
9
10
|
import logging
|
|
10
11
|
import os
|
|
11
12
|
import sys
|
|
@@ -25,7 +26,6 @@ from apm_cli.commands._helpers import (
|
|
|
25
26
|
print_version,
|
|
26
27
|
)
|
|
27
28
|
from apm_cli.commands.approve import approve_cmd, deny_cmd
|
|
28
|
-
from apm_cli.commands.audit import audit
|
|
29
29
|
from apm_cli.commands.cache import cache
|
|
30
30
|
from apm_cli.commands.compile import compile as compile_cmd
|
|
31
31
|
from apm_cli.commands.config import config
|
|
@@ -35,25 +35,18 @@ from apm_cli.commands.doctor import doctor
|
|
|
35
35
|
from apm_cli.commands.experimental import experimental
|
|
36
36
|
from apm_cli.commands.find import find as find_cmd
|
|
37
37
|
from apm_cli.commands.init import init
|
|
38
|
-
from apm_cli.commands.install import install
|
|
39
38
|
from apm_cli.commands.lifecycle import lifecycle
|
|
40
39
|
from apm_cli.commands.list_cmd import list as list_cmd
|
|
41
40
|
from apm_cli.commands.lock import lock
|
|
42
|
-
from apm_cli.commands.marketplace import marketplace
|
|
43
|
-
from apm_cli.commands.marketplace import search as marketplace_search
|
|
44
41
|
from apm_cli.commands.mcp import mcp
|
|
45
42
|
from apm_cli.commands.outdated import outdated as outdated_cmd
|
|
46
|
-
from apm_cli.commands.pack import pack_cmd, unpack_cmd
|
|
47
43
|
from apm_cli.commands.plugin import plugin as plugin_cmd
|
|
48
44
|
from apm_cli.commands.policy import policy
|
|
49
|
-
from apm_cli.commands.prune import prune
|
|
50
45
|
from apm_cli.commands.publish import publish_cmd
|
|
51
46
|
from apm_cli.commands.run import preview, run
|
|
52
47
|
from apm_cli.commands.runtime import runtime
|
|
53
48
|
from apm_cli.commands.self_update import self_update
|
|
54
49
|
from apm_cli.commands.targets import targets
|
|
55
|
-
from apm_cli.commands.uninstall import uninstall
|
|
56
|
-
from apm_cli.commands.update import update
|
|
57
50
|
from apm_cli.commands.view import view as view_cmd
|
|
58
51
|
|
|
59
52
|
_CLI_EPILOG = (
|
|
@@ -71,6 +64,85 @@ _CLI_EPILOG = (
|
|
|
71
64
|
)
|
|
72
65
|
|
|
73
66
|
|
|
67
|
+
class _LazyCommand(click.Command):
|
|
68
|
+
"""Stub whose real Click object is imported on first dispatch.
|
|
69
|
+
|
|
70
|
+
Root ``apm --help`` only needs name/help/hidden, so heavyweight modules
|
|
71
|
+
stay unloaded until the matching verb is invoked or its own ``--help``.
|
|
72
|
+
"""
|
|
73
|
+
|
|
74
|
+
def __init__(self, name: str, module: str, attr: str, help: str) -> None:
|
|
75
|
+
super().__init__(name=name, help=help)
|
|
76
|
+
self._module = module
|
|
77
|
+
self._attr = attr
|
|
78
|
+
|
|
79
|
+
def resolve(self) -> click.Command:
|
|
80
|
+
"""Import and return the real command object."""
|
|
81
|
+
loaded = getattr(importlib.import_module(self._module), self._attr)
|
|
82
|
+
if not isinstance(loaded, click.Command):
|
|
83
|
+
raise TypeError(f"{self._module}.{self._attr} is not a Click command")
|
|
84
|
+
return loaded
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
# Heavyweight verbs: imported only when the named subcommand is dispatched.
|
|
88
|
+
_LAZY_COMMANDS: tuple[tuple[str, str, str, str], ...] = (
|
|
89
|
+
(
|
|
90
|
+
"audit",
|
|
91
|
+
"apm_cli.commands.audit",
|
|
92
|
+
"audit",
|
|
93
|
+
"Scan installed primitives for hidden Unicode, drift, and lockfile/policy violations",
|
|
94
|
+
),
|
|
95
|
+
(
|
|
96
|
+
"install",
|
|
97
|
+
"apm_cli.commands.install",
|
|
98
|
+
"install",
|
|
99
|
+
"Install APM, MCP, and LSP dependencies (supports APM packages, Claude skills (SKILL.md), and plugin collections (plugin.json); auto-creates apm.yml; use --allow-insecure for http:// packages)",
|
|
100
|
+
),
|
|
101
|
+
(
|
|
102
|
+
"marketplace",
|
|
103
|
+
"apm_cli.commands.marketplace",
|
|
104
|
+
"marketplace",
|
|
105
|
+
"Manage marketplaces for discovery and governance",
|
|
106
|
+
),
|
|
107
|
+
(
|
|
108
|
+
"pack",
|
|
109
|
+
"apm_cli.commands.pack",
|
|
110
|
+
"pack_cmd",
|
|
111
|
+
"Pack distributable artifacts from your APM project.",
|
|
112
|
+
),
|
|
113
|
+
(
|
|
114
|
+
"prune",
|
|
115
|
+
"apm_cli.commands.prune",
|
|
116
|
+
"prune",
|
|
117
|
+
"Remove APM packages absent from the resolved dependency graph and repair stale deployment owners",
|
|
118
|
+
),
|
|
119
|
+
(
|
|
120
|
+
"search",
|
|
121
|
+
"apm_cli.commands.marketplace",
|
|
122
|
+
"search",
|
|
123
|
+
"Search plugins in a marketplace (QUERY@MARKETPLACE)",
|
|
124
|
+
),
|
|
125
|
+
(
|
|
126
|
+
"uninstall",
|
|
127
|
+
"apm_cli.commands.uninstall",
|
|
128
|
+
"uninstall",
|
|
129
|
+
"Remove packages using manifest entries or direct locked keys from 'apm deps list'",
|
|
130
|
+
),
|
|
131
|
+
(
|
|
132
|
+
"unpack",
|
|
133
|
+
"apm_cli.commands.pack",
|
|
134
|
+
"unpack_cmd",
|
|
135
|
+
"[Deprecated] Extract an APM bundle into the current project. Use 'apm install <bundle-path>' instead -- this command will be removed in a future release.",
|
|
136
|
+
),
|
|
137
|
+
(
|
|
138
|
+
"update",
|
|
139
|
+
"apm_cli.commands.update",
|
|
140
|
+
"update",
|
|
141
|
+
"Refresh APM dependencies to the latest matching refs",
|
|
142
|
+
),
|
|
143
|
+
)
|
|
144
|
+
|
|
145
|
+
|
|
74
146
|
class _OutputModeGroup(click.Group):
|
|
75
147
|
"""Capture full argv so root output mode precedes subcommand callbacks."""
|
|
76
148
|
|
|
@@ -78,6 +150,44 @@ class _OutputModeGroup(click.Group):
|
|
|
78
150
|
ctx.meta["apm_raw_args"] = tuple(args)
|
|
79
151
|
return super().parse_args(ctx, args)
|
|
80
152
|
|
|
153
|
+
def get_command(self, ctx: click.Context, cmd_name: str) -> click.Command | None:
|
|
154
|
+
cmd = super().get_command(ctx, cmd_name)
|
|
155
|
+
if isinstance(cmd, _LazyCommand):
|
|
156
|
+
resolved = cmd.resolve()
|
|
157
|
+
self.commands[cmd_name] = resolved
|
|
158
|
+
return resolved
|
|
159
|
+
return cmd
|
|
160
|
+
|
|
161
|
+
def format_commands(self, ctx: click.Context, formatter: click.HelpFormatter) -> None:
|
|
162
|
+
"""List subcommands from stubs so root --help does not import them."""
|
|
163
|
+
commands: list[tuple[str, click.Command]] = []
|
|
164
|
+
for subcommand in self.list_commands(ctx):
|
|
165
|
+
cmd = self.commands.get(subcommand)
|
|
166
|
+
if cmd is None or cmd.hidden:
|
|
167
|
+
continue
|
|
168
|
+
commands.append((subcommand, cmd))
|
|
169
|
+
|
|
170
|
+
if commands:
|
|
171
|
+
limit = formatter.width - 6 - max(len(name) for name, _cmd in commands)
|
|
172
|
+
rows = [(subcommand, cmd.get_short_help_str(limit)) for subcommand, cmd in commands]
|
|
173
|
+
if rows:
|
|
174
|
+
with formatter.section("Commands"):
|
|
175
|
+
formatter.write_dl(rows)
|
|
176
|
+
|
|
177
|
+
def shell_complete(self, ctx: click.Context, incomplete: str) -> list:
|
|
178
|
+
"""Complete from stubs so tab-complete does not import lazy verbs."""
|
|
179
|
+
from click.shell_completion import CompletionItem
|
|
180
|
+
|
|
181
|
+
results = [
|
|
182
|
+
CompletionItem(name, help=command.get_short_help_str())
|
|
183
|
+
for name in self.list_commands(ctx)
|
|
184
|
+
if name.startswith(incomplete)
|
|
185
|
+
for command in (self.commands.get(name),)
|
|
186
|
+
if command is not None and not command.hidden
|
|
187
|
+
]
|
|
188
|
+
results.extend(click.Command.shell_complete(self, ctx, incomplete))
|
|
189
|
+
return results
|
|
190
|
+
|
|
81
191
|
|
|
82
192
|
def _configure_logging(verbose: bool = False) -> None:
|
|
83
193
|
"""Configure stdlib logging for the ``apm_cli`` package.
|
|
@@ -187,7 +297,6 @@ def cli(ctx, verbose: bool) -> None:
|
|
|
187
297
|
|
|
188
298
|
# Register command groups
|
|
189
299
|
cli.add_command(approve_cmd, name="approve")
|
|
190
|
-
cli.add_command(audit)
|
|
191
300
|
cli.add_command(cache)
|
|
192
301
|
cli.add_command(deny_cmd, name="deny")
|
|
193
302
|
cli.add_command(deps)
|
|
@@ -202,16 +311,10 @@ cli.add_command(
|
|
|
202
311
|
hidden=True,
|
|
203
312
|
)
|
|
204
313
|
)
|
|
205
|
-
cli.add_command(pack_cmd, name="pack")
|
|
206
|
-
cli.add_command(unpack_cmd, name="unpack")
|
|
207
314
|
cli.add_command(publish_cmd, name="publish")
|
|
208
315
|
cli.add_command(init)
|
|
209
316
|
cli.add_command(discover)
|
|
210
|
-
cli.add_command(install)
|
|
211
317
|
cli.add_command(lock)
|
|
212
|
-
cli.add_command(uninstall)
|
|
213
|
-
cli.add_command(prune)
|
|
214
|
-
cli.add_command(update)
|
|
215
318
|
cli.add_command(self_update)
|
|
216
319
|
cli.add_command(plugin_cmd, name="plugin")
|
|
217
320
|
cli.add_command(compile_cmd, name="compile")
|
|
@@ -227,9 +330,12 @@ cli.add_command(policy)
|
|
|
227
330
|
cli.add_command(outdated_cmd, name="outdated")
|
|
228
331
|
cli.add_command(doctor)
|
|
229
332
|
cli.add_command(lifecycle)
|
|
230
|
-
cli.add_command(marketplace)
|
|
231
333
|
cli.add_command(find_cmd)
|
|
232
|
-
|
|
334
|
+
for _lazy_name, _lazy_module, _lazy_attr, _lazy_help in _LAZY_COMMANDS:
|
|
335
|
+
cli.add_command(
|
|
336
|
+
_LazyCommand(name=_lazy_name, module=_lazy_module, attr=_lazy_attr, help=_lazy_help),
|
|
337
|
+
name=_lazy_name,
|
|
338
|
+
)
|
|
233
339
|
|
|
234
340
|
|
|
235
341
|
def _get_current_code_page() -> "Optional[int]":
|
|
@@ -19,6 +19,7 @@ from ..constants import (
|
|
|
19
19
|
APM_MODULES_GITIGNORE_PATTERN,
|
|
20
20
|
APM_YML_FILENAME,
|
|
21
21
|
GITIGNORE_FILENAME,
|
|
22
|
+
SKILL_MD_FILENAME,
|
|
22
23
|
)
|
|
23
24
|
from ..core import project_name as _project_name
|
|
24
25
|
from ..update_policy import get_update_hint_message, is_self_update_enabled
|
|
@@ -191,7 +192,7 @@ def _expand_with_ancestors(
|
|
|
191
192
|
unless that path is also directly declared in *paths*. Callers should
|
|
192
193
|
pass only the subset of installed paths that look like *real
|
|
193
194
|
standalone packages* (i.e., directories that ship their own
|
|
194
|
-
``apm.yml``) -- not filesystem intermediaries (which typically have
|
|
195
|
+
``apm.yml`` or ``SKILL.md``) -- not filesystem intermediaries (which typically have
|
|
195
196
|
only a ``.apm/`` subtree from a cloned subdir dep). This preserves
|
|
196
197
|
orphan detection for the case where a user has a genuinely orphaned
|
|
197
198
|
``owner/repo`` package on disk alongside a declared sibling
|
|
@@ -256,19 +257,17 @@ def _standalone_installed_packages(
|
|
|
256
257
|
1. Path appears as a dependency key in *lockfile* -- the canonical
|
|
257
258
|
record of what APM installed. The lockfile is integrity-checked
|
|
258
259
|
and not forgeable by dropping/omitting files in ``apm_modules/``.
|
|
259
|
-
2. Fallback: path has its own ``apm.yml
|
|
260
|
+
2. Fallback: path has its own ``apm.yml`` or ``SKILL.md`` file. Used when the lockfile
|
|
260
261
|
is absent (older installs / fresh checkouts) or does not list
|
|
261
262
|
the key. A directory with only a ``.apm/`` marker is treated as
|
|
262
263
|
a filesystem intermediary, not a standalone package.
|
|
263
264
|
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
behaviour for projects that pre-date the lockfile or have not yet
|
|
267
|
-
re-installed.
|
|
265
|
+
Package markers preserve standalone orphan detection even when a
|
|
266
|
+
declaration points at a subdirectory of a removed package root.
|
|
268
267
|
|
|
269
268
|
Failure mode: only narrowly-typed shape errors against
|
|
270
269
|
``lockfile.dependencies`` (``AttributeError`` / ``TypeError`` /
|
|
271
|
-
``KeyError``) are absorbed and degrade to the
|
|
270
|
+
``KeyError``) are absorbed and degrade to the package-marker
|
|
272
271
|
fallback. Any other exception (e.g. lockfile parse / I/O failure)
|
|
273
272
|
propagates so the outer caller can decide whether to log or fail
|
|
274
273
|
closed -- preventing a corrupted or attacker-crafted lockfile from
|
|
@@ -287,7 +286,9 @@ def _standalone_installed_packages(
|
|
|
287
286
|
if p in lockfile_keys:
|
|
288
287
|
standalone.append(p)
|
|
289
288
|
continue
|
|
290
|
-
if (apm_modules_dir / p / APM_YML_FILENAME).exists()
|
|
289
|
+
if (apm_modules_dir / p / APM_YML_FILENAME).exists() or (
|
|
290
|
+
apm_modules_dir / p / SKILL_MD_FILENAME
|
|
291
|
+
).is_file():
|
|
291
292
|
standalone.append(p)
|
|
292
293
|
return standalone
|
|
293
294
|
|
|
@@ -322,23 +323,44 @@ def _check_orphaned_packages():
|
|
|
322
323
|
return []
|
|
323
324
|
|
|
324
325
|
installed = _scan_installed_packages(apm_modules_dir)
|
|
325
|
-
|
|
326
|
-
# which installed paths are real standalone packages (and so
|
|
327
|
-
# must NOT be masked by ancestor expansion). The lockfile is
|
|
328
|
-
# the canonical, tamper-evident record; apm.yml-existence is
|
|
329
|
-
# the fallback for projects without a lockfile yet.
|
|
330
|
-
# See _expand_with_ancestors for the user-safety rationale.
|
|
331
|
-
standalone_installed = _standalone_installed_packages(
|
|
332
|
-
installed, apm_modules_dir, lockfile=lockfile
|
|
333
|
-
)
|
|
334
|
-
expected_with_ancestors = _expand_with_ancestors(expected, standalone_installed)
|
|
335
|
-
# Sort for deterministic, diffable output across runs (rglob
|
|
336
|
-
# traversal order is filesystem-dependent).
|
|
337
|
-
return sorted(p for p in installed if p not in expected_with_ancestors)
|
|
326
|
+
return _find_orphaned_packages(installed, expected)
|
|
338
327
|
except Exception:
|
|
339
328
|
return []
|
|
340
329
|
|
|
341
330
|
|
|
331
|
+
def _find_orphaned_packages(installed: Iterable[str], expected: set[str]) -> list[str]:
|
|
332
|
+
"""Select roots unrelated to the retained dependency graph.
|
|
333
|
+
|
|
334
|
+
Keep both bundled descendants and whole roots containing needed children.
|
|
335
|
+
Ancestor prefixes protect only those containing roots, not their siblings.
|
|
336
|
+
Unlike dependency-list classification, deletion must retain recognized
|
|
337
|
+
ancestors at every depth, including aliases and hidden subdirectories.
|
|
338
|
+
"""
|
|
339
|
+
roots = set()
|
|
340
|
+
retained = set(expected)
|
|
341
|
+
for path in expected:
|
|
342
|
+
try:
|
|
343
|
+
validate_path_segments(path, context="orphan selection")
|
|
344
|
+
except PathTraversalError:
|
|
345
|
+
# Invalid tokens protect only an exact match, never a wider subtree.
|
|
346
|
+
continue
|
|
347
|
+
normalized = path.replace("\\", "/")
|
|
348
|
+
roots.add(normalized)
|
|
349
|
+
parts = normalized.split("/")
|
|
350
|
+
retained.update("/".join(parts[:depth]) for depth in range(1, len(parts) + 1))
|
|
351
|
+
|
|
352
|
+
orphaned = []
|
|
353
|
+
for path in installed:
|
|
354
|
+
normalized = path.replace("\\", "/")
|
|
355
|
+
if normalized in retained:
|
|
356
|
+
continue
|
|
357
|
+
parts = normalized.split("/")
|
|
358
|
+
if any("/".join(parts[:depth]) in roots for depth in range(1, len(parts))):
|
|
359
|
+
continue
|
|
360
|
+
orphaned.append(path)
|
|
361
|
+
return sorted(orphaned)
|
|
362
|
+
|
|
363
|
+
|
|
342
364
|
# ------------------------------------------------------------------
|
|
343
365
|
# Dependency-update helpers (shared by `apm update` and `apm deps update`)
|
|
344
366
|
# ------------------------------------------------------------------
|
|
@@ -11,27 +11,32 @@ from ...utils.yaml_io import load_yaml
|
|
|
11
11
|
def _scan_installed_packages(apm_modules_dir: Path) -> list:
|
|
12
12
|
"""Scan *apm_modules_dir* for installed package paths.
|
|
13
13
|
|
|
14
|
-
Walks the tree to find top-level directories containing ``apm.yml
|
|
15
|
-
``.apm``, supporting GitHub (2-level), ADO (3-level),
|
|
16
|
-
packages.
|
|
14
|
+
Walks the tree to find top-level directories containing ``apm.yml``,
|
|
15
|
+
``.apm``, or ``SKILL.md``, supporting aliases (1-level), GitHub (2-level), ADO (3-level),
|
|
16
|
+
and subdirectory packages. Manifests nested below another package are part of that
|
|
17
17
|
parent package and are excluded.
|
|
18
18
|
|
|
19
19
|
Returns:
|
|
20
|
-
List of
|
|
20
|
+
List of installed relative paths, including flattened aliases.
|
|
21
21
|
"""
|
|
22
22
|
installed: list = []
|
|
23
23
|
if not apm_modules_dir.exists():
|
|
24
24
|
return installed
|
|
25
25
|
for candidate in apm_modules_dir.rglob("*"):
|
|
26
|
-
if
|
|
26
|
+
if candidate.is_symlink() or not candidate.is_dir():
|
|
27
27
|
continue
|
|
28
|
-
if
|
|
28
|
+
if candidate.name.startswith(".") and candidate.parent != apm_modules_dir:
|
|
29
|
+
continue
|
|
30
|
+
if not (
|
|
31
|
+
(candidate / APM_YML_FILENAME).exists()
|
|
32
|
+
or (candidate / APM_DIR).exists()
|
|
33
|
+
or (candidate / SKILL_MD_FILENAME).is_file()
|
|
34
|
+
):
|
|
29
35
|
continue
|
|
30
36
|
if _is_nested_under_package(candidate, apm_modules_dir):
|
|
31
37
|
continue
|
|
32
38
|
rel_parts = candidate.relative_to(apm_modules_dir).parts
|
|
33
|
-
|
|
34
|
-
installed.append("/".join(rel_parts))
|
|
39
|
+
installed.append("/".join(rel_parts))
|
|
35
40
|
return installed
|
|
36
41
|
|
|
37
42
|
|
|
@@ -41,7 +46,7 @@ def _is_nested_under_package(candidate: Path, apm_modules_path: Path) -> bool:
|
|
|
41
46
|
When a package ships nested package or skill manifests, the ``rglob`` scan
|
|
42
47
|
would otherwise treat each sub-directory as an independent package. This
|
|
43
48
|
helper walks up from *candidate* towards *apm_modules_path* and returns
|
|
44
|
-
``True`` if any intermediate parent already contains ``apm.yml``, ``.apm``,
|
|
49
|
+
``True`` if any intermediate parent already contains ``apm.yml``, ``.apm``, ``SKILL.md``,
|
|
45
50
|
or a canonical Agent Plugin manifest -- meaning the candidate is part of
|
|
46
51
|
that package, not a standalone one.
|
|
47
52
|
"""
|
|
@@ -50,6 +55,7 @@ def _is_nested_under_package(candidate: Path, apm_modules_path: Path) -> bool:
|
|
|
50
55
|
if (
|
|
51
56
|
(parent / APM_YML_FILENAME).exists()
|
|
52
57
|
or (parent / APM_DIR).exists()
|
|
58
|
+
or (parent / SKILL_MD_FILENAME).is_file()
|
|
53
59
|
or _is_agent_plugin_root(parent)
|
|
54
60
|
):
|
|
55
61
|
return True
|
|
@@ -12,8 +12,6 @@ import sys
|
|
|
12
12
|
|
|
13
13
|
import click
|
|
14
14
|
|
|
15
|
-
from .marketplace.doctor import run_doctor
|
|
16
|
-
|
|
17
15
|
|
|
18
16
|
@click.command(
|
|
19
17
|
help=(
|
|
@@ -25,6 +23,8 @@ from .marketplace.doctor import run_doctor
|
|
|
25
23
|
@click.option("--verbose", "-v", is_flag=True, help="Show detailed output")
|
|
26
24
|
def doctor(verbose):
|
|
27
25
|
"""Top-level diagnostic entry point."""
|
|
26
|
+
from .marketplace.doctor import run_doctor
|
|
27
|
+
|
|
28
28
|
exit_code = run_doctor(verbose, logger_name="doctor")
|
|
29
29
|
if exit_code != 0:
|
|
30
30
|
sys.exit(exit_code)
|
|
@@ -15,7 +15,7 @@ from ...marketplace.ref_resolver import RefResolver
|
|
|
15
15
|
from ...marketplace.semver import satisfies_range
|
|
16
16
|
from ...marketplace.yml_schema import PackageEntry
|
|
17
17
|
from ...models.dependency.host_virtual import repository_owner
|
|
18
|
-
from ...utils.github_host import is_azure_devops_hostname
|
|
18
|
+
from ...utils.github_host import default_host, is_azure_devops_hostname
|
|
19
19
|
from . import (
|
|
20
20
|
_CheckResult,
|
|
21
21
|
_extract_tag_versions,
|
|
@@ -90,17 +90,18 @@ def check(offline, verbose):
|
|
|
90
90
|
# named a non-default host -- a host-prefixed source or a relative source
|
|
91
91
|
# composed onto ``marketplace.sourceBase`` -- must be resolved against
|
|
92
92
|
# that host with the host's (and, for sourceBase, the org's) token,
|
|
93
|
-
# exactly like ``apm pack`` does. Default-host entries
|
|
94
|
-
#
|
|
93
|
+
# exactly like ``apm pack`` does. Default-host entries resolve the
|
|
94
|
+
# configured default host through the same authentication path.
|
|
95
95
|
source_base = getattr(yml, "source_base", None)
|
|
96
96
|
resolvers: dict[tuple[str | None, str | None], RefResolver] = {}
|
|
97
97
|
auth_resolver: AuthResolver | None = None
|
|
98
98
|
|
|
99
99
|
def _resolver_for(host: str | None, org: str | None) -> RefResolver:
|
|
100
100
|
nonlocal auth_resolver
|
|
101
|
-
|
|
101
|
+
resolved_host = host or default_host() or "github.com"
|
|
102
|
+
key = (resolved_host, org)
|
|
102
103
|
if key not in resolvers:
|
|
103
|
-
if host is None:
|
|
104
|
+
if host is None and offline:
|
|
104
105
|
resolvers[key] = RefResolver(offline=offline)
|
|
105
106
|
else:
|
|
106
107
|
if auth_resolver is None and not offline:
|
|
@@ -108,14 +109,14 @@ def check(offline, verbose):
|
|
|
108
109
|
|
|
109
110
|
auth_resolver = AuthResolver()
|
|
110
111
|
auth = resolve_auth_for_host(
|
|
111
|
-
|
|
112
|
+
resolved_host,
|
|
112
113
|
offline=offline,
|
|
113
114
|
org=org,
|
|
114
115
|
auth_resolver=auth_resolver,
|
|
115
116
|
)
|
|
116
117
|
resolvers[key] = RefResolver(
|
|
117
118
|
offline=offline,
|
|
118
|
-
host=
|
|
119
|
+
host=resolved_host,
|
|
119
120
|
token=auth.token if auth else None,
|
|
120
121
|
auth_scheme=auth.auth_scheme if auth else "basic",
|
|
121
122
|
git_env=(
|
|
@@ -124,7 +125,7 @@ def check(offline, verbose):
|
|
|
124
125
|
else None
|
|
125
126
|
),
|
|
126
127
|
auth_resolver=auth_resolver,
|
|
127
|
-
auth_target=
|
|
128
|
+
auth_target=resolved_host,
|
|
128
129
|
)
|
|
129
130
|
return resolvers[key]
|
|
130
131
|
|
|
@@ -156,7 +157,8 @@ def check(offline, verbose):
|
|
|
156
157
|
else:
|
|
157
158
|
remote_label = f"https://{host}/{owner_repo}.git" if host else owner_repo
|
|
158
159
|
logger.verbose_detail(
|
|
159
|
-
f"Resolving {entry.name} via
|
|
160
|
+
f"Resolving {entry.name} via "
|
|
161
|
+
f"{host or default_host() or 'github.com'}: {remote_label}"
|
|
160
162
|
)
|
|
161
163
|
refs = _resolver_for(host, org).list_remote_refs(owner_repo)
|
|
162
164
|
|
|
@@ -21,9 +21,8 @@ from ..models.apm_package import APMPackage
|
|
|
21
21
|
from ..utils.path_security import safe_rmtree
|
|
22
22
|
from ._helpers import (
|
|
23
23
|
_build_expected_install_paths,
|
|
24
|
-
|
|
24
|
+
_find_orphaned_packages,
|
|
25
25
|
_scan_installed_packages,
|
|
26
|
-
_standalone_installed_packages,
|
|
27
26
|
)
|
|
28
27
|
from .uninstall.lockfile_state import lockfile_has_persisted_state
|
|
29
28
|
|
|
@@ -125,15 +124,6 @@ def prune(ctx, dry_run):
|
|
|
125
124
|
installed_packages = (
|
|
126
125
|
_scan_installed_packages(apm_modules_dir) if apm_modules_dir.exists() else set()
|
|
127
126
|
)
|
|
128
|
-
standalone_installed = _standalone_installed_packages(
|
|
129
|
-
installed_packages,
|
|
130
|
-
apm_modules_dir,
|
|
131
|
-
lockfile=lockfile,
|
|
132
|
-
)
|
|
133
|
-
expected_with_ancestors = _expand_with_ancestors(
|
|
134
|
-
expected_installed,
|
|
135
|
-
standalone_installed,
|
|
136
|
-
)
|
|
137
127
|
expected_lock_keys = {dependency.get_unique_key() for dependency in declared_deps}
|
|
138
128
|
if lockfile is not None:
|
|
139
129
|
expected_lock_keys.update(
|
|
@@ -144,14 +134,19 @@ def prune(ctx, dry_run):
|
|
|
144
134
|
lock_keys_by_path = (
|
|
145
135
|
_lock_keys_by_install_path(lockfile, apm_modules_dir) if lockfile is not None else {}
|
|
146
136
|
)
|
|
147
|
-
|
|
148
|
-
|
|
137
|
+
orphaned_paths = set(
|
|
138
|
+
_find_orphaned_packages(
|
|
139
|
+
set(installed_packages) | set(lock_keys_by_path), expected_installed
|
|
140
|
+
)
|
|
149
141
|
)
|
|
142
|
+
orphaned_packages = sorted(set(installed_packages) & orphaned_paths)
|
|
143
|
+
retained_packages = set(installed_packages) - orphaned_paths
|
|
144
|
+
for package in sorted(retained_packages - expected_installed):
|
|
145
|
+
logger.progress(f"Retained {package}: required package content.")
|
|
150
146
|
missing_orphaned_keys = sorted(
|
|
151
147
|
dep_key
|
|
152
148
|
for relative_path, dep_keys in lock_keys_by_path.items()
|
|
153
|
-
if relative_path in
|
|
154
|
-
or not (apm_modules_dir / relative_path).exists()
|
|
149
|
+
if relative_path not in orphaned_paths or not (apm_modules_dir / relative_path).exists()
|
|
155
150
|
for dep_key in dep_keys
|
|
156
151
|
if dep_key not in expected_lock_keys
|
|
157
152
|
)
|
|
@@ -208,7 +203,7 @@ def prune(ctx, dry_run):
|
|
|
208
203
|
if missing_orphaned_keys:
|
|
209
204
|
logger.progress(
|
|
210
205
|
f"Found {len(missing_orphaned_keys)} stale lockfile dependency "
|
|
211
|
-
"record(s) without
|
|
206
|
+
"record(s) without removable package content."
|
|
212
207
|
)
|
|
213
208
|
|
|
214
209
|
if dry_run:
|
|
@@ -203,6 +203,31 @@ class DeploymentLedgerCodec:
|
|
|
203
203
|
),
|
|
204
204
|
)
|
|
205
205
|
|
|
206
|
+
@staticmethod
|
|
207
|
+
def merge_dependencies(
|
|
208
|
+
lockfile: LockFile,
|
|
209
|
+
updated: LockFile,
|
|
210
|
+
*,
|
|
211
|
+
project_root: Path,
|
|
212
|
+
diagnostics: DiagnosticCollector,
|
|
213
|
+
) -> None:
|
|
214
|
+
"""Merge processed dependencies without discarding concrete deployment locators."""
|
|
215
|
+
current = DeploymentLedgerCodec.from_lockfile(updated)
|
|
216
|
+
retained = DeploymentLedgerCodec.reconcile_owner_references(
|
|
217
|
+
lockfile,
|
|
218
|
+
excluded_dependency_keys=updated.dependencies,
|
|
219
|
+
project_root=project_root,
|
|
220
|
+
diagnostics=diagnostics,
|
|
221
|
+
)
|
|
222
|
+
# add_dependency invalidates the legacy projection. Capture both
|
|
223
|
+
# canonical ledgers first, then restore their reconciled records once.
|
|
224
|
+
for dependency in updated.dependencies.values():
|
|
225
|
+
lockfile.add_dependency(dependency)
|
|
226
|
+
DeploymentLedgerCodec.apply_to_lockfile(
|
|
227
|
+
DeploymentLedger(records={**retained.ledger.records, **current.records}),
|
|
228
|
+
lockfile,
|
|
229
|
+
)
|
|
230
|
+
|
|
206
231
|
@staticmethod
|
|
207
232
|
def from_lockfile(lockfile: LockFile) -> DeploymentLedger:
|
|
208
233
|
"""Read canonical rows or synthesize them from legacy ownership views."""
|