apm-cli 0.24.0__tar.gz → 0.25.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.24.0 → apm_cli-0.25.0}/NOTICE +35 -0
- {apm_cli-0.24.0/src/apm_cli.egg-info → apm_cli-0.25.0}/PKG-INFO +2 -1
- {apm_cli-0.24.0 → apm_cli-0.25.0}/pyproject.toml +2 -2
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/adapters/client/base.py +13 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/adapters/client/claude.py +20 -5
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/adapters/client/codex.py +13 -10
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/bundle/packer.py +4 -2
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/bundle/plugin_exporter.py +137 -9
- apm_cli-0.25.0/src/apm_cli/bundle/plugin_layout.py +24 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/cache/http_cache.py +23 -1
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/cli.py +21 -2
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/commands/_helpers.py +6 -4
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/commands/audit.py +14 -7
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/commands/compile/cli.py +146 -86
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/commands/deps/_utils.py +69 -12
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/commands/deps/cli.py +232 -48
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/commands/deps/why.py +0 -8
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/commands/init.py +16 -1
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/commands/install.py +261 -312
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/commands/lock.py +0 -5
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/commands/marketplace/check.py +13 -4
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/commands/mcp.py +16 -10
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/commands/pack.py +0 -5
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/commands/policy.py +5 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/commands/prune.py +5 -5
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/commands/publish.py +7 -1
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/commands/runtime.py +3 -2
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/commands/uninstall/cli.py +41 -13
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/commands/uninstall/engine.py +48 -15
- apm_cli-0.25.0/src/apm_cli/commands/uninstall/lockfile_state.py +78 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/commands/update.py +135 -6
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/compilation/agents_compiler.py +145 -113
- apm_cli-0.25.0/src/apm_cli/compilation/output_writer.py +83 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/compilation/user_root_context.py +34 -36
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/core/apm_yml.py +4 -15
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/core/auth.py +57 -94
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/core/command_logger.py +40 -1
- apm_cli-0.25.0/src/apm_cli/core/deployment_ledger.py +380 -0
- apm_cli-0.25.0/src/apm_cli/core/deployment_state.py +358 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/core/errors.py +19 -16
- apm_cli-0.25.0/src/apm_cli/core/host_providers.py +197 -0
- apm_cli-0.25.0/src/apm_cli/core/output_mode.py +66 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/core/script_runner.py +42 -56
- apm_cli-0.25.0/src/apm_cli/core/target_catalog.py +282 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/core/target_detection.py +100 -30
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/deps/apm_resolver.py +107 -32
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/deps/dependency_graph.py +6 -4
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/deps/host_backends.py +25 -74
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/deps/lockfile.py +176 -11
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/deps/plugin_parser.py +42 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/drift.py +3 -6
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/install/context.py +2 -1
- apm_cli-0.25.0/src/apm_cli/install/deployed_paths.py +88 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/install/errors.py +4 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/install/heals/branch_ref_drift.py +1 -1
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/install/heals/buggy_lockfile_recovery.py +1 -1
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/install/helpers/ref_reuse.py +41 -18
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/install/local_bundle_handler.py +5 -2
- apm_cli-0.25.0/src/apm_cli/install/manifest_reconcile.py +433 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/install/mcp/__init__.py +5 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/install/mcp/command.py +10 -3
- apm_cli-0.25.0/src/apm_cli/install/mcp/integration.py +230 -0
- apm_cli-0.25.0/src/apm_cli/install/mcp/ownership.py +68 -0
- apm_cli-0.25.0/src/apm_cli/install/outcome.py +100 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/install/package_resolution.py +10 -1
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/install/phases/finalize.py +3 -8
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/install/phases/integrate.py +5 -1
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/install/phases/lockfile.py +84 -13
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/install/phases/policy_target_check.py +10 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/install/phases/post_deps_local.py +35 -10
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/install/phases/resolve.py +26 -23
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/install/phases/targets.py +53 -2
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/install/pipeline.py +67 -7
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/install/request.py +2 -0
- apm_cli-0.25.0/src/apm_cli/install/resolution_staging.py +59 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/install/service.py +9 -3
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/install/services.py +29 -33
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/install/skill_path_migration.py +6 -10
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/install/sources.py +12 -17
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/install/summary.py +45 -32
- apm_cli-0.25.0/src/apm_cli/install/target_warnings.py +57 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/install/template.py +23 -1
- apm_cli-0.25.0/src/apm_cli/install/transaction.py +204 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/install/validation.py +41 -1
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/integration/__init__.py +4 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/integration/base_integrator.py +63 -5
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/integration/hook_integrator.py +150 -213
- apm_cli-0.25.0/src/apm_cli/integration/hook_ir.py +54 -0
- apm_cli-0.25.0/src/apm_cli/integration/hook_native_formats.py +176 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/integration/kiro_hook_integrator.py +51 -70
- apm_cli-0.25.0/src/apm_cli/integration/mcp_config_view.py +327 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/integration/mcp_integrator.py +88 -76
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/integration/mcp_integrator_install.py +42 -2
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/integration/skill_integrator.py +56 -7
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/integration/targets.py +165 -81
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/marketplace/auth_helpers.py +30 -13
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/marketplace/builder.py +77 -60
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/marketplace/models.py +13 -18
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/marketplace/ref_resolver.py +119 -9
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/marketplace/registry.py +28 -10
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/marketplace/resolver.py +39 -7
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/marketplace/version_resolver.py +14 -1
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/models/apm_package.py +163 -20
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/models/dependency/identity.py +40 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/models/dependency/mcp.py +13 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/models/dependency/reference.py +43 -25
- apm_cli-0.25.0/src/apm_cli/models/manifest_contract.py +31 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/models/results.py +16 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/policy/ci_checks.py +81 -44
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/policy/discovery.py +91 -32
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/policy/inheritance.py +2 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/policy/install_preflight.py +4 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/policy/outcome_routing.py +17 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/policy/parser.py +21 -4
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/policy/policy_checks.py +1 -1
- apm_cli-0.25.0/src/apm_cli/runtime/base.py +176 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/runtime/codex_runtime.py +3 -20
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/runtime/factory.py +12 -10
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/runtime/manager.py +11 -28
- apm_cli-0.25.0/src/apm_cli/runtime/registry.py +126 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/security/gate.py +19 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/utils/github_host.py +24 -19
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/workflow/runner.py +1 -1
- {apm_cli-0.24.0 → apm_cli-0.25.0/src/apm_cli.egg-info}/PKG-INFO +2 -1
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli.egg-info/SOURCES.txt +18 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli.egg-info/requires.txt +1 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/tests/test_apm_package_models.py +51 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/tests/test_github_downloader.py +47 -3
- {apm_cli-0.24.0 → apm_cli-0.25.0}/tests/test_lockfile.py +15 -0
- apm_cli-0.24.0/src/apm_cli/compilation/output_writer.py +0 -49
- apm_cli-0.24.0/src/apm_cli/install/deployed_paths.py +0 -70
- apm_cli-0.24.0/src/apm_cli/install/manifest_reconcile.py +0 -112
- apm_cli-0.24.0/src/apm_cli/runtime/base.py +0 -103
- {apm_cli-0.24.0 → apm_cli-0.25.0}/AUTHORS +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/LICENSE +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/README.md +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/setup.cfg +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/__init__.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/adapters/__init__.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/adapters/client/__init__.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/adapters/client/_mcp_runtime_args.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/adapters/client/antigravity.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/adapters/client/copilot.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/adapters/client/cursor.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/adapters/client/gemini.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/adapters/client/hermes.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/adapters/client/intellij.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/adapters/client/kiro.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/adapters/client/opencode.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/adapters/client/vscode.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/adapters/client/windsurf.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/adapters/package_manager/__init__.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/adapters/package_manager/base.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/adapters/package_manager/default_manager.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/bootstrap_mirror.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/bundle/__init__.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/bundle/attest.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/bundle/local_bundle.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/bundle/lockfile_enrichment.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/bundle/unpacker.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/cache/__init__.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/cache/git_cache.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/cache/integrity.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/cache/locking.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/cache/paths.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/cache/url_normalize.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/commands/__init__.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/commands/_apm_yml_writer.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/commands/approve.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/commands/cache.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/commands/compile/__init__.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/commands/compile/watcher.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/commands/config.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/commands/deps/__init__.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/commands/doctor.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/commands/experimental.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/commands/find.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/commands/lifecycle.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/commands/list_cmd.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/commands/marketplace/__init__.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/commands/marketplace/audit.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/commands/marketplace/doctor.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/commands/marketplace/init.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/commands/marketplace/migrate.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/commands/marketplace/outdated.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/commands/marketplace/plugin/__init__.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/commands/marketplace/plugin/add.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/commands/marketplace/plugin/remove.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/commands/marketplace/plugin/set.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/commands/marketplace/validate.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/commands/outdated.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/commands/plugin/__init__.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/commands/plugin/init.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/commands/run.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/commands/self_update.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/commands/targets.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/commands/uninstall/__init__.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/commands/view.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/compilation/__init__.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/compilation/build_id.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/compilation/claude_formatter.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/compilation/constants.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/compilation/constitution.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/compilation/constitution_block.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/compilation/context_optimizer.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/compilation/distributed_compiler.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/compilation/gemini_formatter.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/compilation/injector.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/compilation/link_resolver.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/compilation/managed_section.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/compilation/template_builder.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/config.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/constants.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/core/__init__.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/core/azure_cli.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/core/build_orchestrator.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/core/conflict_detector.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/core/docker_args.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/core/experimental.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/core/install_audit.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/core/lifecycle_scripts.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/core/null_logger.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/core/operations.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/core/plugin_manifest.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/core/safe_installer.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/core/scope.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/core/script_executors.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/core/script_trust.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/core/token_manager.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/deps/__init__.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/deps/_shared.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/deps/aggregator.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/deps/artifactory_entry.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/deps/artifactory_orchestrator.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/deps/bare_cache.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/deps/clone_engine.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/deps/download_strategies.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/deps/git_auth_env.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/deps/git_file_transport.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/deps/git_reference_resolver.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/deps/git_remote_ops.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/deps/git_semver_resolver.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/deps/github_downloader.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/deps/github_downloader_validation.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/deps/installed_package.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/deps/outdated_ref_cache.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/deps/outdated_row.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/deps/package_validator.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/deps/path_anchoring.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/deps/registry/__init__.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/deps/registry/auth.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/deps/registry/client.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/deps/registry/config_loader.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/deps/registry/extractor.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/deps/registry/feature_gate.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/deps/registry/outdated.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/deps/registry/resolver.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/deps/registry/semver.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/deps/registry_proxy.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/deps/revision_pins.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/deps/shared_clone_cache.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/deps/tiered_ref_resolver.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/deps/transport_selection.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/deps/verifier.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/deps/why_walker.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/export/__init__.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/export/authoring.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/export/declared_license.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/export/formats.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/export/purl.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/export/sbom.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/export/spdx.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/export/spdx_data.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/factory.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/install/__init__.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/install/artifactory_resolver.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/install/cache_pin.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/install/drift.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/install/exec_gate.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/install/gitlab_resolver.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/install/heals/__init__.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/install/heals/base.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/install/helpers/__init__.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/install/helpers/ref_seed.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/install/helpers/security_scan.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/install/insecure_policy.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/install/integrity.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/install/lsp/__init__.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/install/lsp/integration.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/install/mcp/args.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/install/mcp/conflicts.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/install/mcp/entry.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/install/mcp/registry.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/install/mcp/warnings.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/install/mcp/writer.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/install/package_selection.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/install/phases/__init__.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/install/phases/_redownload.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/install/phases/_skip_logic.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/install/phases/audit.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/install/phases/cleanup.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/install/phases/download.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/install/phases/heal.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/install/phases/local_content.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/install/phases/policy_gate.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/install/plan.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/install/presentation/__init__.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/install/presentation/dry_run.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/install/registry_wiring.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/install/root_redirect.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/install/target_filter.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/integration/_shared.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/integration/agent_integrator.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/integration/canvas_integrator.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/integration/cleanup.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/integration/command_integrator.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/integration/copilot_app_db.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/integration/copilot_app_project.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/integration/copilot_app_workflow_integrator.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/integration/copilot_app_ws.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/integration/copilot_cowork_paths.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/integration/coverage.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/integration/dispatch.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/integration/hook_bundle.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/integration/hook_file_routing.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/integration/instruction_integrator.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/integration/lsp_integrator.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/integration/opencode_frontmatter.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/integration/prompt_integrator.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/integration/skill_transformer.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/integration/utils.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/marketplace/__init__.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/marketplace/_git_utils.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/marketplace/_io.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/marketplace/_shared.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/marketplace/audit.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/marketplace/client.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/marketplace/diagnostics.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/marketplace/drift_check.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/marketplace/errors.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/marketplace/git_stderr.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/marketplace/init_template.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/marketplace/migration.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/marketplace/output_mappers.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/marketplace/output_profiles.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/marketplace/semver.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/marketplace/shadow_detector.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/marketplace/tag_pattern.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/marketplace/validator.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/marketplace/version_check.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/marketplace/version_pins.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/marketplace/yml_editor.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/marketplace/yml_schema.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/models/__init__.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/models/dependency/__init__.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/models/dependency/lsp.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/models/dependency/object_fields.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/models/dependency/subsets.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/models/dependency/types.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/models/format_detection.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/models/plugin.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/models/validation.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/output/__init__.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/output/formatters.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/output/models.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/output/script_formatters.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/policy/__init__.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/policy/_constraint_pinning.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/policy/_help_text.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/policy/_shared.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/policy/matcher.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/policy/models.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/policy/project_config.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/policy/schema.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/primitives/__init__.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/primitives/discovery.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/primitives/models.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/primitives/parser.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/registry/__init__.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/registry/client.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/registry/integration.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/registry/operations.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/runtime/__init__.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/runtime/copilot_runtime.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/runtime/llm_runtime.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/runtime/utils.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/security/__init__.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/security/audit_report.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/security/content_scanner.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/security/executables.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/security/external/__init__.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/security/external/base.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/security/external/gate.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/security/external/generic_sarif.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/security/external/options.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/security/external/registry.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/security/external/runner.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/security/external/sarif_ingest.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/security/external/skillspector.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/security/file_scanner.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/update_policy.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/utils/__init__.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/utils/archive.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/utils/atomic_io.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/utils/console.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/utils/content_hash.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/utils/diagnostics.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/utils/exclude.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/utils/file_ops.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/utils/git_env.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/utils/git_sparse.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/utils/guards.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/utils/helpers.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/utils/install_tui.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/utils/normalization.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/utils/path_security.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/utils/paths.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/utils/patterns.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/utils/perf_stats.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/utils/reflink.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/utils/short_sha.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/utils/subprocess_env.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/utils/version_checker.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/utils/yaml_io.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/version.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/workflow/__init__.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/workflow/discovery.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli/workflow/parser.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli.egg-info/dependency_links.txt +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli.egg-info/entry_points.txt +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/src/apm_cli.egg-info/top_level.txt +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/tests/test_apm_resolver.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/tests/test_codex_docker_args_fix.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/tests/test_codex_empty_string_and_defaults.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/tests/test_collision_integration.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/tests/test_console.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/tests/test_distributed_compilation.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/tests/test_empty_string_and_defaults.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/tests/test_enhanced_discovery.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/tests/test_github_downloader_token_precedence.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/tests/test_gitlab_git_transport.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/tests/test_runnable_prompts.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/tests/test_runtime_manager_token_precedence.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/tests/test_token_manager.py +0 -0
- {apm_cli-0.24.0 → apm_cli-0.25.0}/tests/test_virtual_package_multi_install.py +0 -0
|
@@ -703,6 +703,41 @@ THE SOFTWARE.
|
|
|
703
703
|
|
|
704
704
|
---
|
|
705
705
|
|
|
706
|
+
## Component. tomlkit
|
|
707
|
+
|
|
708
|
+
- Version requirement: `>=0.13`
|
|
709
|
+
- Upstream: https://github.com/python-poetry/tomlkit
|
|
710
|
+
- SPDX: `MIT`
|
|
711
|
+
|
|
712
|
+
### Open Source License/Copyright Notice.
|
|
713
|
+
|
|
714
|
+
_Copyright (c) 2018 Sébastien Eustace_
|
|
715
|
+
|
|
716
|
+
```
|
|
717
|
+
Copyright (c) 2018 Sébastien Eustace
|
|
718
|
+
|
|
719
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
|
720
|
+
a copy of this software and associated documentation files (the
|
|
721
|
+
"Software"), to deal in the Software without restriction, including
|
|
722
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
|
723
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
|
724
|
+
permit persons to whom the Software is furnished to do so, subject to
|
|
725
|
+
the following conditions:
|
|
726
|
+
|
|
727
|
+
The above copyright notice and this permission notice shall be
|
|
728
|
+
included in all copies or substantial portions of the Software.
|
|
729
|
+
|
|
730
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
731
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
732
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
733
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
734
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
735
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
736
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
737
|
+
```
|
|
738
|
+
|
|
739
|
+
---
|
|
740
|
+
|
|
706
741
|
## Component. rich
|
|
707
742
|
|
|
708
743
|
- Version requirement: `>=13.0.0`
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: apm-cli
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.25.0
|
|
4
4
|
Summary: MCP configuration tool
|
|
5
5
|
Author-email: Daniel Meppiel <user@example.com>
|
|
6
6
|
License: MIT License
|
|
@@ -46,6 +46,7 @@ Requires-Dist: llm>=0.28
|
|
|
46
46
|
Requires-Dist: llm-github-models>=0.18.0
|
|
47
47
|
Requires-Dist: tomli>=1.2.0; python_version < "3.11"
|
|
48
48
|
Requires-Dist: toml>=0.10.2
|
|
49
|
+
Requires-Dist: tomlkit>=0.13
|
|
49
50
|
Requires-Dist: rich>=13.0.0
|
|
50
51
|
Requires-Dist: rich-click>=1.7.0
|
|
51
52
|
Requires-Dist: watchdog>=3.0.0
|
|
@@ -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.25.0"
|
|
8
8
|
description = "MCP configuration tool"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.10"
|
|
@@ -31,6 +31,7 @@ dependencies = [
|
|
|
31
31
|
"llm-github-models>=0.18.0",
|
|
32
32
|
"tomli>=1.2.0; python_version<'3.11'",
|
|
33
33
|
"toml>=0.10.2",
|
|
34
|
+
"tomlkit>=0.13",
|
|
34
35
|
"rich>=13.0.0",
|
|
35
36
|
"rich-click>=1.7.0",
|
|
36
37
|
"watchdog>=3.0.0",
|
|
@@ -170,4 +171,3 @@ markers = [
|
|
|
170
171
|
"requires_inference: requires APM_RUN_INFERENCE_TESTS=1 + model API access",
|
|
171
172
|
"req: binds a test to one or more OpenAPM req-XXX ids (spec-conformance suite)",
|
|
172
173
|
]
|
|
173
|
-
|
|
@@ -210,6 +210,19 @@ class MCPClientAdapter(ABC):
|
|
|
210
210
|
return self._project_root
|
|
211
211
|
return Path(os.getcwd())
|
|
212
212
|
|
|
213
|
+
def render_server_config(self, server_info: dict) -> dict:
|
|
214
|
+
"""Render one native server entry for exact baseline comparisons."""
|
|
215
|
+
rendered = self._format_server_config(
|
|
216
|
+
server_info,
|
|
217
|
+
env_overrides={},
|
|
218
|
+
runtime_vars={},
|
|
219
|
+
)
|
|
220
|
+
if isinstance(rendered, tuple):
|
|
221
|
+
rendered = rendered[0]
|
|
222
|
+
if not isinstance(rendered, dict):
|
|
223
|
+
raise ValueError("Adapter did not produce a native MCP server mapping")
|
|
224
|
+
return rendered
|
|
225
|
+
|
|
213
226
|
@abstractmethod
|
|
214
227
|
def get_config_path(self):
|
|
215
228
|
"""Get the path to the MCP configuration file."""
|
|
@@ -4,11 +4,11 @@ Project scope: ``.mcp.json`` at the project root with top-level ``mcpServers``
|
|
|
4
4
|
(``--scope project`` in Claude Code). Writes are opt-in when ``.claude/`` exists,
|
|
5
5
|
mirroring the Cursor/OpenCode directory-presence convention.
|
|
6
6
|
|
|
7
|
-
User scope: top-level ``mcpServers`` in
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
on a multi-user host.
|
|
7
|
+
User scope: top-level ``mcpServers`` in ``$CLAUDE_CONFIG_DIR/.claude.json``
|
|
8
|
+
when configured, otherwise ``~/.claude.json`` (``--scope user``). Writes are
|
|
9
|
+
atomic and create the file with ``0o600`` permissions on first write so the
|
|
10
|
+
shared Claude Code config is not silently truncated by a concurrent writer
|
|
11
|
+
and cannot leak any embedded OAuth state to other users on a multi-user host.
|
|
12
12
|
|
|
13
13
|
Local scope (Claude Code's third scope -- the default for ``claude mcp add``,
|
|
14
14
|
storing per-project private config under ``~/.claude.json -> projects.<abs_path>
|
|
@@ -20,12 +20,17 @@ See https://code.claude.com/docs/en/mcp
|
|
|
20
20
|
"""
|
|
21
21
|
|
|
22
22
|
import json
|
|
23
|
+
import logging
|
|
24
|
+
import os
|
|
23
25
|
from pathlib import Path
|
|
24
26
|
|
|
25
27
|
from ...utils.atomic_io import atomic_write_text
|
|
26
28
|
from ...utils.console import _rich_error, _rich_success, _rich_warning
|
|
29
|
+
from ...utils.path_security import PathTraversalError
|
|
27
30
|
from .copilot import CopilotClientAdapter
|
|
28
31
|
|
|
32
|
+
_log = logging.getLogger(__name__)
|
|
33
|
+
|
|
29
34
|
|
|
30
35
|
class ClaudeClientAdapter(CopilotClientAdapter):
|
|
31
36
|
"""MCP configuration for Claude Code (``mcpServers`` schema).
|
|
@@ -141,6 +146,15 @@ class ClaudeClientAdapter(CopilotClientAdapter):
|
|
|
141
146
|
return self.project_root / ".mcp.json"
|
|
142
147
|
|
|
143
148
|
def _user_claude_json_path(self) -> Path:
|
|
149
|
+
config_dir = os.environ.get("CLAUDE_CONFIG_DIR", "").strip()
|
|
150
|
+
if config_dir:
|
|
151
|
+
config_path = Path(config_dir).expanduser()
|
|
152
|
+
if not config_path.is_absolute():
|
|
153
|
+
raise PathTraversalError(
|
|
154
|
+
"CLAUDE_CONFIG_DIR must be an absolute path for user-scope MCP "
|
|
155
|
+
"config; set an absolute path or unset it to use ~/.claude.json."
|
|
156
|
+
)
|
|
157
|
+
return config_path.resolve(strict=False) / ".claude.json"
|
|
144
158
|
return Path.home() / ".claude.json"
|
|
145
159
|
|
|
146
160
|
def _should_write_project(self) -> bool:
|
|
@@ -206,6 +220,7 @@ class ClaudeClientAdapter(CopilotClientAdapter):
|
|
|
206
220
|
payload = json.dumps(data, indent=2) + "\n"
|
|
207
221
|
path.parent.mkdir(parents=True, exist_ok=True)
|
|
208
222
|
atomic_write_text(path, payload, new_file_mode=0o600)
|
|
223
|
+
_log.debug("Claude user-scope MCP config written to %s", path)
|
|
209
224
|
return True
|
|
210
225
|
except OSError:
|
|
211
226
|
return False
|
|
@@ -5,10 +5,12 @@ import os
|
|
|
5
5
|
from pathlib import Path
|
|
6
6
|
from urllib.parse import urlparse
|
|
7
7
|
|
|
8
|
-
import
|
|
8
|
+
import tomlkit
|
|
9
|
+
from tomlkit.exceptions import TOMLKitError
|
|
9
10
|
|
|
10
11
|
from ...registry.client import SimpleRegistryClient
|
|
11
12
|
from ...registry.integration import RegistryIntegration
|
|
13
|
+
from ...utils.atomic_io import atomic_write_text
|
|
12
14
|
from ...utils.console import _rich_success, _rich_warning
|
|
13
15
|
from ...utils.path_security import PathTraversalError
|
|
14
16
|
from ._mcp_runtime_args import process_v01_value_hint_arg
|
|
@@ -94,9 +96,7 @@ class CodexClientAdapter(MCPClientAdapter):
|
|
|
94
96
|
# Ensure directory exists
|
|
95
97
|
config_path.parent.mkdir(parents=True, exist_ok=True)
|
|
96
98
|
|
|
97
|
-
|
|
98
|
-
toml.dump(current_config, f)
|
|
99
|
-
os.chmod(config_path, 0o600)
|
|
99
|
+
atomic_write_text(config_path, tomlkit.dumps(current_config), new_file_mode=0o600)
|
|
100
100
|
_log.debug("Codex config written to %s", config_path)
|
|
101
101
|
return True
|
|
102
102
|
|
|
@@ -104,8 +104,9 @@ class CodexClientAdapter(MCPClientAdapter):
|
|
|
104
104
|
"""Get the current Codex CLI MCP configuration.
|
|
105
105
|
|
|
106
106
|
Returns:
|
|
107
|
-
|
|
108
|
-
|
|
107
|
+
MutableMapping | None: Round-trip-preserving mapping when the file
|
|
108
|
+
exists, empty mapping if it does not exist, or None when an
|
|
109
|
+
existing config cannot be parsed safely.
|
|
109
110
|
"""
|
|
110
111
|
config_path = self.get_config_path()
|
|
111
112
|
|
|
@@ -113,12 +114,14 @@ class CodexClientAdapter(MCPClientAdapter):
|
|
|
113
114
|
return {}
|
|
114
115
|
|
|
115
116
|
try:
|
|
116
|
-
with open(config_path, encoding="utf-8") as
|
|
117
|
-
return
|
|
118
|
-
except
|
|
117
|
+
with open(config_path, encoding="utf-8") as config_file:
|
|
118
|
+
return tomlkit.load(config_file)
|
|
119
|
+
except (TOMLKitError, UnicodeDecodeError) as exc:
|
|
119
120
|
_log.debug("Failed to parse Codex config at %s", config_path, exc_info=True)
|
|
120
121
|
_rich_warning(
|
|
121
|
-
f"Could not parse {config_path}: {exc}
|
|
122
|
+
f"Could not read or parse {config_path}: {exc} "
|
|
123
|
+
"-- skipping config write to avoid data loss; inspect the file "
|
|
124
|
+
"or delete it to reset Codex configuration",
|
|
122
125
|
symbol="warning",
|
|
123
126
|
)
|
|
124
127
|
return None
|
|
@@ -93,7 +93,9 @@ def pack_bundle(
|
|
|
93
93
|
package = APMPackage.from_apm_yml(apm_yml_path)
|
|
94
94
|
pkg_name = package.name
|
|
95
95
|
pkg_version = package.version or "0.0.0"
|
|
96
|
-
|
|
96
|
+
from apm_cli.models.apm_package import package_target_selection
|
|
97
|
+
|
|
98
|
+
config_target = package_target_selection(package)
|
|
97
99
|
|
|
98
100
|
# HYBRID author guard: apm.yml.description and SKILL.md
|
|
99
101
|
# description serve different consumers (human-facing CLI/search
|
|
@@ -141,7 +143,7 @@ def pack_bundle(
|
|
|
141
143
|
# List from CLI (e.g. --target claude,copilot) passes through directly
|
|
142
144
|
effective_target = target
|
|
143
145
|
elif isinstance(config_target, list) and target is None:
|
|
144
|
-
#
|
|
146
|
+
# Canonical list from either apm.yml target spelling.
|
|
145
147
|
effective_target = config_target
|
|
146
148
|
else:
|
|
147
149
|
effective_target, _reason = detect_target(
|
|
@@ -30,8 +30,10 @@ from ..utils.archive import (
|
|
|
30
30
|
)
|
|
31
31
|
from ..utils.console import _rich_warning
|
|
32
32
|
from ..utils.path_security import PathTraversalError, ensure_path_within, safe_rmtree
|
|
33
|
+
from ..utils.paths import portable_relpath
|
|
33
34
|
from .attest import verify_attested_file
|
|
34
35
|
from .packer import PackResult
|
|
36
|
+
from .plugin_layout import PLUGIN_ROOT_DIRS, find_plugin_root_sources
|
|
35
37
|
|
|
36
38
|
# ---------------------------------------------------------------------------
|
|
37
39
|
# Path helpers
|
|
@@ -125,11 +127,49 @@ def _collect_root_plugin_components(project_root: Path) -> list[tuple[Path, str]
|
|
|
125
127
|
``skills/``, etc. at the repo root) have their files picked up here.
|
|
126
128
|
"""
|
|
127
129
|
components: list[tuple[Path, str]] = []
|
|
128
|
-
for dir_name in
|
|
130
|
+
for dir_name in PLUGIN_ROOT_DIRS:
|
|
131
|
+
if dir_name == "hooks":
|
|
132
|
+
continue
|
|
129
133
|
_collect_recursive(project_root / dir_name, dir_name, components)
|
|
130
134
|
return components
|
|
131
135
|
|
|
132
136
|
|
|
137
|
+
def _emit_pack_warning(message: str, logger=None) -> None:
|
|
138
|
+
"""Send a pack warning through the command logger when available."""
|
|
139
|
+
if logger:
|
|
140
|
+
logger.warning(message)
|
|
141
|
+
else:
|
|
142
|
+
_rich_warning(message, symbol="warning")
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
def _warn_skipped_root_components(project_root: Path, logger=None) -> None:
|
|
146
|
+
"""Explain why plugin-native root sources are not packed."""
|
|
147
|
+
for source in find_plugin_root_sources(project_root):
|
|
148
|
+
if source == "hooks.json":
|
|
149
|
+
message = (
|
|
150
|
+
"Skipping root-level hooks.json because .apm/ is present. "
|
|
151
|
+
"Move publishable hook configuration to .apm/hooks/ or remove "
|
|
152
|
+
"hooks.json to silence this warning."
|
|
153
|
+
)
|
|
154
|
+
else:
|
|
155
|
+
message = (
|
|
156
|
+
f"Skipping root-level {source}/ because .apm/ is present. "
|
|
157
|
+
f"Move publishable files to .apm/{source}/ or remove {source}/ "
|
|
158
|
+
"to silence this warning."
|
|
159
|
+
)
|
|
160
|
+
_emit_pack_warning(message, logger)
|
|
161
|
+
|
|
162
|
+
|
|
163
|
+
def _warn_no_local_primitives(logger=None) -> None:
|
|
164
|
+
"""Explain how to recover from an empty APM-native source layout."""
|
|
165
|
+
_emit_pack_warning(
|
|
166
|
+
"No local primitives found. Expected content under .apm/. "
|
|
167
|
+
"Move plugin-native content into .apm/, or remove .apm/ to restore "
|
|
168
|
+
"root convention discovery.",
|
|
169
|
+
logger,
|
|
170
|
+
)
|
|
171
|
+
|
|
172
|
+
|
|
133
173
|
def _collect_bare_skill(
|
|
134
174
|
install_path: Path,
|
|
135
175
|
dep: "LockedDependency",
|
|
@@ -178,7 +218,7 @@ def _collect_flat(
|
|
|
178
218
|
rename=None,
|
|
179
219
|
) -> None:
|
|
180
220
|
"""Add every regular non-symlink file directly inside *src_dir*."""
|
|
181
|
-
if not src_dir.is_dir():
|
|
221
|
+
if src_dir.is_symlink() or not src_dir.is_dir():
|
|
182
222
|
return
|
|
183
223
|
for f in sorted(src_dir.iterdir()):
|
|
184
224
|
if f.is_file() and not f.is_symlink():
|
|
@@ -194,7 +234,7 @@ def _collect_recursive(
|
|
|
194
234
|
rename=None,
|
|
195
235
|
) -> None:
|
|
196
236
|
"""Add every regular non-symlink file under *src_dir*, preserving hierarchy."""
|
|
197
|
-
if not src_dir.is_dir():
|
|
237
|
+
if src_dir.is_symlink() or not src_dir.is_dir():
|
|
198
238
|
return
|
|
199
239
|
for f in sorted(src_dir.rglob("*")):
|
|
200
240
|
if not f.is_file() or f.is_symlink():
|
|
@@ -483,6 +523,76 @@ def _plugin_rel_for_deployed_path(
|
|
|
483
523
|
return PurePosixPath(*plugin_parts).as_posix()
|
|
484
524
|
|
|
485
525
|
|
|
526
|
+
def _collect_explicit_local_components(
|
|
527
|
+
project_root: Path,
|
|
528
|
+
includes: list[str],
|
|
529
|
+
) -> tuple[list[tuple[Path, str]], dict]:
|
|
530
|
+
"""Collect only explicitly listed local paths and validate each path."""
|
|
531
|
+
components: list[tuple[Path, str]] = []
|
|
532
|
+
hooks: dict = {}
|
|
533
|
+
for declared_path in includes:
|
|
534
|
+
parts = _deployed_path_parts(declared_path)
|
|
535
|
+
candidate = project_root.joinpath(*parts)
|
|
536
|
+
if candidate.is_symlink():
|
|
537
|
+
raise ValueError(
|
|
538
|
+
f"includes path {declared_path!r} is a symlink. "
|
|
539
|
+
"Replace it with a regular file or directory."
|
|
540
|
+
)
|
|
541
|
+
try:
|
|
542
|
+
source = ensure_path_within(candidate, project_root)
|
|
543
|
+
except PathTraversalError as exc:
|
|
544
|
+
raise ValueError(
|
|
545
|
+
f"includes path {declared_path!r} escapes the project root. "
|
|
546
|
+
"Fix the path in apm.yml."
|
|
547
|
+
) from exc
|
|
548
|
+
if not source.exists():
|
|
549
|
+
raise ValueError(
|
|
550
|
+
f"includes path {declared_path!r} does not exist. "
|
|
551
|
+
"Fix the path in apm.yml or create it."
|
|
552
|
+
)
|
|
553
|
+
entries = [source] if source.is_file() else sorted(source.rglob("*"))
|
|
554
|
+
for entry in entries:
|
|
555
|
+
if entry.is_symlink():
|
|
556
|
+
raise ValueError(
|
|
557
|
+
f"Symlink found inside includes path {declared_path!r}: "
|
|
558
|
+
f"{entry.name}. Remove the symlink or list a regular path."
|
|
559
|
+
)
|
|
560
|
+
for file_path in (entry for entry in entries if entry.is_file()):
|
|
561
|
+
try:
|
|
562
|
+
file_path = ensure_path_within(file_path, project_root)
|
|
563
|
+
except PathTraversalError as exc:
|
|
564
|
+
raise ValueError(
|
|
565
|
+
f"A file inside includes path {declared_path!r} escapes the "
|
|
566
|
+
"project root. Remove the symlink or fix the path in apm.yml."
|
|
567
|
+
) from exc
|
|
568
|
+
repo_relative = portable_relpath(file_path, project_root)
|
|
569
|
+
is_hook = (
|
|
570
|
+
repo_relative == "hooks.json"
|
|
571
|
+
or repo_relative.startswith("hooks/")
|
|
572
|
+
or repo_relative.startswith(".apm/hooks/")
|
|
573
|
+
)
|
|
574
|
+
if is_hook:
|
|
575
|
+
try:
|
|
576
|
+
hook_data = json.loads(file_path.read_text(encoding="utf-8"))
|
|
577
|
+
except (OSError, ValueError, RecursionError) as exc:
|
|
578
|
+
raise ValueError(
|
|
579
|
+
f"Explicit hook include is not valid JSON: {repo_relative}"
|
|
580
|
+
) from exc
|
|
581
|
+
if not isinstance(hook_data, dict):
|
|
582
|
+
raise ValueError(
|
|
583
|
+
f"Explicit hook include must contain a JSON object: {repo_relative}"
|
|
584
|
+
)
|
|
585
|
+
_deep_merge(hooks, hook_data, overwrite=False)
|
|
586
|
+
continue
|
|
587
|
+
plugin_relative = _plugin_rel_for_deployed_path(repo_relative, None)
|
|
588
|
+
if plugin_relative is None:
|
|
589
|
+
raise ValueError(
|
|
590
|
+
f"Explicit include path is not a packable primitive: {repo_relative}"
|
|
591
|
+
)
|
|
592
|
+
components.append((file_path, plugin_relative))
|
|
593
|
+
return components, hooks
|
|
594
|
+
|
|
595
|
+
|
|
486
596
|
def _verify_attested_hash(
|
|
487
597
|
source: Path,
|
|
488
598
|
project_root: Path,
|
|
@@ -765,16 +875,34 @@ def export_plugin_bundle(
|
|
|
765
875
|
|
|
766
876
|
_merge_file_map(file_map, dep_components, dep_name, force, collisions)
|
|
767
877
|
|
|
768
|
-
# 6. Collect own components
|
|
878
|
+
# 6. Collect own components according to the local source authority.
|
|
769
879
|
own_apm_dir = project_root / ".apm"
|
|
770
|
-
|
|
771
|
-
|
|
880
|
+
if isinstance(package.includes, list):
|
|
881
|
+
own_components, root_hooks = _collect_explicit_local_components(
|
|
882
|
+
project_root,
|
|
883
|
+
package.includes,
|
|
884
|
+
)
|
|
885
|
+
else:
|
|
886
|
+
own_components = _collect_apm_components(own_apm_dir)
|
|
887
|
+
root_hooks = _collect_hooks_from_apm(own_apm_dir)
|
|
888
|
+
if own_apm_dir.is_dir():
|
|
889
|
+
_warn_skipped_root_components(project_root, logger)
|
|
890
|
+
else:
|
|
891
|
+
own_components.extend(_collect_root_plugin_components(project_root))
|
|
892
|
+
root_hooks_top = _collect_hooks_from_root(project_root)
|
|
893
|
+
_deep_merge(root_hooks, root_hooks_top, overwrite=False)
|
|
894
|
+
|
|
895
|
+
if (
|
|
896
|
+
not isinstance(package.includes, list)
|
|
897
|
+
and own_apm_dir.is_dir()
|
|
898
|
+
and not own_components
|
|
899
|
+
and not root_hooks
|
|
900
|
+
):
|
|
901
|
+
_warn_no_local_primitives(logger)
|
|
902
|
+
|
|
772
903
|
_merge_file_map(file_map, own_components, pkg_name, force, collisions)
|
|
773
904
|
|
|
774
905
|
# Hooks -- root package wins on key collision
|
|
775
|
-
root_hooks = _collect_hooks_from_apm(own_apm_dir)
|
|
776
|
-
root_hooks_top = _collect_hooks_from_root(project_root)
|
|
777
|
-
_deep_merge(root_hooks, root_hooks_top, overwrite=False)
|
|
778
906
|
_deep_merge(merged_hooks, root_hooks, overwrite=True)
|
|
779
907
|
|
|
780
908
|
# MCP -- root package wins on server-name collision
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
"""Plugin-native source-layout conventions."""
|
|
2
|
+
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
|
|
5
|
+
PLUGIN_ROOT_DIRS = (
|
|
6
|
+
"agents",
|
|
7
|
+
"skills",
|
|
8
|
+
"commands",
|
|
9
|
+
"instructions",
|
|
10
|
+
"extensions",
|
|
11
|
+
"hooks",
|
|
12
|
+
)
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def find_plugin_root_sources(project_root: Path) -> list[str]:
|
|
16
|
+
"""Return plugin-native root sources that exist."""
|
|
17
|
+
sources = [
|
|
18
|
+
name
|
|
19
|
+
for name in PLUGIN_ROOT_DIRS
|
|
20
|
+
if (project_root / name).is_dir() and not (project_root / name).is_symlink()
|
|
21
|
+
]
|
|
22
|
+
if (project_root / "hooks.json").is_file():
|
|
23
|
+
sources.append("hooks.json")
|
|
24
|
+
return sources
|
|
@@ -70,6 +70,7 @@ class HttpCache:
|
|
|
70
70
|
self._cache_dir.mkdir(parents=True, exist_ok=True)
|
|
71
71
|
os.chmod(str(self._cache_dir), 0o700)
|
|
72
72
|
cleanup_incomplete(self._cache_dir)
|
|
73
|
+
self._tracked_size: int | None = None
|
|
73
74
|
|
|
74
75
|
def get(self, url: str, headers: dict[str, str] | None = None) -> CacheEntry | None:
|
|
75
76
|
"""Look up a cached response for *url*.
|
|
@@ -233,6 +234,13 @@ class HttpCache:
|
|
|
233
234
|
with contextlib.suppress(OSError):
|
|
234
235
|
os.utime(str(entry_path), None)
|
|
235
236
|
|
|
237
|
+
# Update tracked size with an upper-bound estimate. Over-counting is
|
|
238
|
+
# intentional: it triggers a real scan sooner, correcting the estimate,
|
|
239
|
+
# rather than delaying eviction. The scan in _enforce_size_cap resets
|
|
240
|
+
# _tracked_size to the real total once it runs.
|
|
241
|
+
if self._tracked_size is not None:
|
|
242
|
+
self._tracked_size += len(body) + 512 # body + metadata upper-bound estimate
|
|
243
|
+
|
|
236
244
|
# Enforce size cap
|
|
237
245
|
self._enforce_size_cap()
|
|
238
246
|
|
|
@@ -321,10 +329,20 @@ class HttpCache:
|
|
|
321
329
|
return 300.0
|
|
322
330
|
|
|
323
331
|
def _enforce_size_cap(self) -> None:
|
|
324
|
-
"""Evict LRU entries if total cache size exceeds the cap.
|
|
332
|
+
"""Evict LRU entries if total cache size exceeds the cap.
|
|
333
|
+
|
|
334
|
+
Uses a tracked size estimate to skip the full directory scan
|
|
335
|
+
when we are clearly under the cap (fast path). Falls back to a
|
|
336
|
+
full scan when the tracked size exceeds the limit or has not
|
|
337
|
+
been computed yet.
|
|
338
|
+
"""
|
|
325
339
|
if not self._cache_dir.is_dir():
|
|
326
340
|
return
|
|
327
341
|
|
|
342
|
+
# Fast path: if we have a tracked size and it is under cap, skip scan
|
|
343
|
+
if self._tracked_size is not None and self._tracked_size <= MAX_HTTP_CACHE_BYTES:
|
|
344
|
+
return
|
|
345
|
+
|
|
328
346
|
entries: list[tuple[float, str, int]] = []
|
|
329
347
|
total_size = 0
|
|
330
348
|
|
|
@@ -343,6 +361,8 @@ class HttpCache:
|
|
|
343
361
|
except OSError:
|
|
344
362
|
continue
|
|
345
363
|
|
|
364
|
+
self._tracked_size = total_size
|
|
365
|
+
|
|
346
366
|
if total_size <= MAX_HTTP_CACHE_BYTES:
|
|
347
367
|
return
|
|
348
368
|
|
|
@@ -356,3 +376,5 @@ class HttpCache:
|
|
|
356
376
|
break
|
|
357
377
|
robust_rmtree(Path(path), ignore_errors=True)
|
|
358
378
|
total_size -= size
|
|
379
|
+
|
|
380
|
+
self._tracked_size = total_size
|
|
@@ -64,6 +64,14 @@ _CLI_EPILOG = (
|
|
|
64
64
|
)
|
|
65
65
|
|
|
66
66
|
|
|
67
|
+
class _OutputModeGroup(click.Group):
|
|
68
|
+
"""Capture full argv so root output mode precedes subcommand callbacks."""
|
|
69
|
+
|
|
70
|
+
def parse_args(self, ctx: click.Context, args: list[str]) -> list[str]:
|
|
71
|
+
ctx.meta["apm_raw_args"] = tuple(args)
|
|
72
|
+
return super().parse_args(ctx, args)
|
|
73
|
+
|
|
74
|
+
|
|
67
75
|
def _configure_logging(verbose: bool = False) -> None:
|
|
68
76
|
"""Configure stdlib logging for the ``apm_cli`` package.
|
|
69
77
|
|
|
@@ -102,11 +110,17 @@ def _configure_logging(verbose: bool = False) -> None:
|
|
|
102
110
|
# Install secret-redaction filter (idempotent: skip if already present).
|
|
103
111
|
from apm_cli.core.auth import SecretRedactionFilter
|
|
104
112
|
|
|
105
|
-
|
|
106
|
-
|
|
113
|
+
handlers = {
|
|
114
|
+
*logging.getLogger().handlers,
|
|
115
|
+
*apm_logger.handlers,
|
|
116
|
+
}
|
|
117
|
+
for handler in handlers:
|
|
118
|
+
if not any(isinstance(f, SecretRedactionFilter) for f in handler.filters):
|
|
119
|
+
handler.addFilter(SecretRedactionFilter())
|
|
107
120
|
|
|
108
121
|
|
|
109
122
|
@click.group(
|
|
123
|
+
cls=_OutputModeGroup,
|
|
110
124
|
help="Agent Package Manager (APM): The package manager for AI-Native Development",
|
|
111
125
|
epilog=_CLI_EPILOG,
|
|
112
126
|
)
|
|
@@ -130,6 +144,11 @@ def cli(ctx, verbose: bool) -> None:
|
|
|
130
144
|
"""Main entry point for the APM CLI."""
|
|
131
145
|
ctx.ensure_object(dict)
|
|
132
146
|
ctx.obj["verbose"] = verbose
|
|
147
|
+
from apm_cli.core.output_mode import configure_output_mode, detect_output_mode
|
|
148
|
+
|
|
149
|
+
output_mode = detect_output_mode(ctx.meta.get("apm_raw_args", sys.argv[1:]))
|
|
150
|
+
configure_output_mode(output_mode)
|
|
151
|
+
ctx.obj["output_mode"] = output_mode
|
|
133
152
|
|
|
134
153
|
if verbose:
|
|
135
154
|
# Upgrade to DEBUG when the flag is set; env-var path runs in main().
|
|
@@ -308,7 +308,7 @@ def _check_orphaned_packages():
|
|
|
308
308
|
from ..models.apm_package import APMPackage
|
|
309
309
|
|
|
310
310
|
apm_package = APMPackage.from_apm_yml(Path(APM_YML_FILENAME))
|
|
311
|
-
declared_deps = apm_package.
|
|
311
|
+
declared_deps = apm_package.get_all_apm_dependencies()
|
|
312
312
|
lockfile = LockFile.read(get_lockfile_path(Path.cwd()))
|
|
313
313
|
expected = _build_expected_install_paths(declared_deps, lockfile, apm_modules_dir)
|
|
314
314
|
except Exception:
|
|
@@ -474,7 +474,7 @@ def _check_and_notify_updates():
|
|
|
474
474
|
_rich_echo(get_update_hint_message(), color="yellow", bold=True)
|
|
475
475
|
|
|
476
476
|
# Add a blank line for visual separation
|
|
477
|
-
|
|
477
|
+
_rich_echo("")
|
|
478
478
|
except Exception:
|
|
479
479
|
# Silently fail - version checking should never block CLI usage
|
|
480
480
|
pass
|
|
@@ -706,12 +706,14 @@ def _create_minimal_apm_yml(config, plugin=False, target_path=None):
|
|
|
706
706
|
content = out_file.read_text(encoding="utf-8")
|
|
707
707
|
|
|
708
708
|
if "targets" in apm_yml_data:
|
|
709
|
+
from apm_cli.core.target_catalog import manifest_target_names
|
|
710
|
+
|
|
709
711
|
# Insert comment before the targets: line
|
|
712
|
+
accepted_targets = ", ".join(sorted(manifest_target_names()))
|
|
710
713
|
targets_comment = (
|
|
711
714
|
"# Which agent platforms to deploy to.\n"
|
|
712
715
|
"# Resolution order: --target flag > this field > auto-detect from filesystem.\n"
|
|
713
|
-
"# Accepted values:
|
|
714
|
-
"# gemini, antigravity, windsurf, kiro, agent-skills, all\n"
|
|
716
|
+
f"# Accepted values: {accepted_targets}\n"
|
|
715
717
|
)
|
|
716
718
|
content = content.replace("targets:", targets_comment + "targets:", 1)
|
|
717
719
|
else:
|
|
@@ -535,7 +535,7 @@ def _audit_ci_gate(
|
|
|
535
535
|
# Resolve policy source: explicit --policy wins; otherwise mirror
|
|
536
536
|
# install's auto-discovery (closes #827) so CI catches sideloaded
|
|
537
537
|
# files via unmanaged-files checks. --no-policy skips discovery.
|
|
538
|
-
from ..policy.discovery import
|
|
538
|
+
from ..policy.discovery import discover_policy_with_chain
|
|
539
539
|
from ..policy.project_config import (
|
|
540
540
|
read_project_fetch_failure_default,
|
|
541
541
|
)
|
|
@@ -543,7 +543,7 @@ def _audit_ci_gate(
|
|
|
543
543
|
fetch_result = None
|
|
544
544
|
auto_discovered = False
|
|
545
545
|
if policy_source and (not fail_fast or ci_result.passed):
|
|
546
|
-
fetch_result =
|
|
546
|
+
fetch_result = discover_policy_with_chain(
|
|
547
547
|
cfg.project_root,
|
|
548
548
|
policy_override=policy_source,
|
|
549
549
|
no_cache=no_cache,
|
|
@@ -576,6 +576,7 @@ def _audit_ci_gate(
|
|
|
576
576
|
"malformed",
|
|
577
577
|
"cache_miss_fetch_fail",
|
|
578
578
|
"garbage_response",
|
|
579
|
+
"incomplete_chain",
|
|
579
580
|
)
|
|
580
581
|
no_policy_outcomes = ("absent", "no_git_remote", "empty")
|
|
581
582
|
|
|
@@ -595,7 +596,7 @@ def _audit_ci_gate(
|
|
|
595
596
|
source = fetch_result.source
|
|
596
597
|
err_text = fetch_result.error or fetch_result.fetch_error or fetch_result.outcome
|
|
597
598
|
cause = _audit_outcome_cause(fetch_result.outcome, source, err_text)
|
|
598
|
-
if project_default == "block":
|
|
599
|
+
if fetch_result.outcome == "incomplete_chain" or project_default == "block":
|
|
599
600
|
click.echo(
|
|
600
601
|
f"[x] {cause} (policy.fetch_failure_default=block)",
|
|
601
602
|
err=True,
|
|
@@ -858,10 +859,16 @@ def _audit_content_scan(
|
|
|
858
859
|
else:
|
|
859
860
|
logger.start("Scanning all installed packages...")
|
|
860
861
|
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
862
|
+
from apm_cli.deps.lockfile import LockfileFormatError
|
|
863
|
+
|
|
864
|
+
try:
|
|
865
|
+
findings_by_file, files_scanned = scan_lockfile_packages(
|
|
866
|
+
project_root,
|
|
867
|
+
package_filter=package,
|
|
868
|
+
)
|
|
869
|
+
except LockfileFormatError as exc:
|
|
870
|
+
logger.error(f"Cannot audit invalid apm.lock.yaml: {exc}")
|
|
871
|
+
sys.exit(1)
|
|
865
872
|
|
|
866
873
|
if files_scanned == 0 and not external:
|
|
867
874
|
if package:
|