apm-cli 0.25.0__tar.gz → 0.26.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.25.0 → apm_cli-0.26.0}/NOTICE +37 -0
- {apm_cli-0.25.0/src/apm_cli.egg-info → apm_cli-0.26.0}/PKG-INFO +4 -1
- {apm_cli-0.25.0 → apm_cli-0.26.0}/pyproject.toml +51 -2
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/bundle/plugin_exporter.py +2 -1
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/cache/url_normalize.py +2 -5
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/cli.py +8 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/commands/approve.py +56 -31
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/commands/audit.py +65 -8
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/commands/doctor.py +2 -2
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/commands/install.py +1 -1
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/commands/marketplace/doctor.py +6 -3
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/commands/policy.py +8 -14
- apm_cli-0.26.0/src/apm_cli/commands/prune.py +354 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/commands/uninstall/cli.py +2 -1
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/commands/uninstall/engine.py +235 -46
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/commands/update.py +45 -8
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/compilation/link_resolver.py +23 -21
- apm_cli-0.26.0/src/apm_cli/core/_child_tls/__init__.py +15 -0
- apm_cli-0.26.0/src/apm_cli/core/_child_tls/_apm_tls.pth +1 -0
- apm_cli-0.26.0/src/apm_cli/core/_child_tls/_apm_tls_bootstrap.py +59 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/core/apm_yml.py +65 -6
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/core/deployment_ledger.py +274 -10
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/core/deployment_state.py +75 -4
- apm_cli-0.26.0/src/apm_cli/core/tls_trust.py +343 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/deps/apm_resolver.py +35 -3
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/deps/bare_cache.py +56 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/deps/clone_engine.py +1 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/deps/download_strategies.py +134 -86
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/deps/git_auth_env.py +18 -7
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/deps/git_file_transport.py +38 -3
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/deps/git_reference_resolver.py +39 -7
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/deps/git_semver_resolver.py +7 -1
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/deps/github_downloader.py +48 -23
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/deps/github_downloader_validation.py +12 -1
- apm_cli-0.26.0/src/apm_cli/deps/github_rate_limit.py +77 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/deps/lockfile.py +14 -16
- apm_cli-0.26.0/src/apm_cli/deps/reachability.py +245 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/deps/shared_clone_cache.py +57 -35
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/deps/tiered_ref_resolver.py +17 -8
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/drift.py +22 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/install/context.py +7 -1
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/install/drift.py +26 -1
- apm_cli-0.26.0/src/apm_cli/install/helpers/ref_reuse.py +264 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/install/helpers/ref_seed.py +7 -10
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/install/integrity.py +10 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/install/local_bundle_handler.py +80 -45
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/install/manifest_reconcile.py +236 -19
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/install/phases/cleanup.py +37 -11
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/install/phases/finalize.py +125 -19
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/install/phases/lockfile.py +115 -3
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/install/phases/post_deps_local.py +25 -47
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/install/phases/resolve.py +40 -136
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/install/pipeline.py +9 -2
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/install/plan.py +39 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/install/sources.py +10 -2
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/install/validation.py +61 -47
- apm_cli-0.26.0/src/apm_cli/integration/_hook_dropped_targets.py +129 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/integration/agent_integrator.py +85 -7
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/integration/base_integrator.py +3 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/integration/cleanup.py +14 -1
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/integration/hook_integrator.py +148 -51
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/integration/kiro_hook_integrator.py +11 -10
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/integration/mcp_config_view.py +18 -1
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/integration/opencode_frontmatter.py +4 -18
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/integration/skill_integrator.py +83 -36
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/marketplace/output_mappers.py +2 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/marketplace/ref_resolver.py +154 -16
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/marketplace/resolver.py +65 -45
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/marketplace/yml_schema.py +4 -4
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/models/apm_package.py +87 -3
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/models/dependency/identity.py +15 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/models/dependency/object_fields.py +31 -1
- apm_cli-0.26.0/src/apm_cli/models/dependency/provider_coordinates.py +54 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/models/dependency/reference.py +39 -38
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/models/dependency/subsets.py +28 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/models/validation.py +2 -6
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/policy/ci_checks.py +73 -9
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/policy/discovery.py +377 -63
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/policy/install_preflight.py +6 -1
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/policy/models.py +1 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/policy/outcome_routing.py +13 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/policy/parser.py +5 -1
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/policy/policy_checks.py +62 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/runtime/base.py +10 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/runtime/llm_runtime.py +15 -2
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/runtime/manager.py +38 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/security/audit_report.py +139 -23
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/security/file_scanner.py +7 -2
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/utils/diagnostics.py +40 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/utils/git_env.py +10 -15
- {apm_cli-0.25.0 → apm_cli-0.26.0/src/apm_cli.egg-info}/PKG-INFO +4 -1
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli.egg-info/SOURCES.txt +8 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli.egg-info/requires.txt +3 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/tests/test_github_downloader.py +75 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/tests/test_gitlab_git_transport.py +121 -21
- apm_cli-0.25.0/src/apm_cli/commands/prune.py +0 -168
- apm_cli-0.25.0/src/apm_cli/install/helpers/ref_reuse.py +0 -119
- {apm_cli-0.25.0 → apm_cli-0.26.0}/AUTHORS +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/LICENSE +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/README.md +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/setup.cfg +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/__init__.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/adapters/__init__.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/adapters/client/__init__.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/adapters/client/_mcp_runtime_args.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/adapters/client/antigravity.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/adapters/client/base.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/adapters/client/claude.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/adapters/client/codex.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/adapters/client/copilot.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/adapters/client/cursor.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/adapters/client/gemini.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/adapters/client/hermes.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/adapters/client/intellij.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/adapters/client/kiro.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/adapters/client/opencode.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/adapters/client/vscode.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/adapters/client/windsurf.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/adapters/package_manager/__init__.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/adapters/package_manager/base.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/adapters/package_manager/default_manager.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/bootstrap_mirror.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/bundle/__init__.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/bundle/attest.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/bundle/local_bundle.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/bundle/lockfile_enrichment.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/bundle/packer.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/bundle/plugin_layout.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/bundle/unpacker.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/cache/__init__.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/cache/git_cache.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/cache/http_cache.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/cache/integrity.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/cache/locking.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/cache/paths.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/commands/__init__.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/commands/_apm_yml_writer.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/commands/_helpers.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/commands/cache.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/commands/compile/__init__.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/commands/compile/cli.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/commands/compile/watcher.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/commands/config.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/commands/deps/__init__.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/commands/deps/_utils.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/commands/deps/cli.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/commands/deps/why.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/commands/experimental.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/commands/find.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/commands/init.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/commands/lifecycle.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/commands/list_cmd.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/commands/lock.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/commands/marketplace/__init__.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/commands/marketplace/audit.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/commands/marketplace/check.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/commands/marketplace/init.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/commands/marketplace/migrate.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/commands/marketplace/outdated.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/commands/marketplace/plugin/__init__.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/commands/marketplace/plugin/add.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/commands/marketplace/plugin/remove.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/commands/marketplace/plugin/set.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/commands/marketplace/validate.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/commands/mcp.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/commands/outdated.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/commands/pack.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/commands/plugin/__init__.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/commands/plugin/init.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/commands/publish.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/commands/run.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/commands/runtime.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/commands/self_update.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/commands/targets.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/commands/uninstall/__init__.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/commands/uninstall/lockfile_state.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/commands/view.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/compilation/__init__.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/compilation/agents_compiler.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/compilation/build_id.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/compilation/claude_formatter.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/compilation/constants.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/compilation/constitution.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/compilation/constitution_block.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/compilation/context_optimizer.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/compilation/distributed_compiler.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/compilation/gemini_formatter.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/compilation/injector.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/compilation/managed_section.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/compilation/output_writer.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/compilation/template_builder.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/compilation/user_root_context.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/config.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/constants.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/core/__init__.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/core/auth.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/core/azure_cli.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/core/build_orchestrator.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/core/command_logger.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/core/conflict_detector.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/core/docker_args.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/core/errors.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/core/experimental.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/core/host_providers.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/core/install_audit.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/core/lifecycle_scripts.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/core/null_logger.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/core/operations.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/core/output_mode.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/core/plugin_manifest.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/core/safe_installer.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/core/scope.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/core/script_executors.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/core/script_runner.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/core/script_trust.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/core/target_catalog.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/core/target_detection.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/core/token_manager.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/deps/__init__.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/deps/_shared.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/deps/aggregator.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/deps/artifactory_entry.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/deps/artifactory_orchestrator.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/deps/dependency_graph.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/deps/git_remote_ops.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/deps/host_backends.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/deps/installed_package.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/deps/outdated_ref_cache.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/deps/outdated_row.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/deps/package_validator.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/deps/path_anchoring.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/deps/plugin_parser.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/deps/registry/__init__.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/deps/registry/auth.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/deps/registry/client.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/deps/registry/config_loader.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/deps/registry/extractor.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/deps/registry/feature_gate.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/deps/registry/outdated.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/deps/registry/resolver.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/deps/registry/semver.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/deps/registry_proxy.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/deps/revision_pins.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/deps/transport_selection.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/deps/verifier.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/deps/why_walker.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/export/__init__.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/export/authoring.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/export/declared_license.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/export/formats.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/export/purl.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/export/sbom.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/export/spdx.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/export/spdx_data.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/factory.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/install/__init__.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/install/artifactory_resolver.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/install/cache_pin.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/install/deployed_paths.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/install/errors.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/install/exec_gate.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/install/gitlab_resolver.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/install/heals/__init__.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/install/heals/base.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/install/heals/branch_ref_drift.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/install/heals/buggy_lockfile_recovery.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/install/helpers/__init__.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/install/helpers/security_scan.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/install/insecure_policy.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/install/lsp/__init__.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/install/lsp/integration.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/install/mcp/__init__.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/install/mcp/args.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/install/mcp/command.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/install/mcp/conflicts.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/install/mcp/entry.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/install/mcp/integration.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/install/mcp/ownership.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/install/mcp/registry.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/install/mcp/warnings.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/install/mcp/writer.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/install/outcome.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/install/package_resolution.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/install/package_selection.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/install/phases/__init__.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/install/phases/_redownload.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/install/phases/_skip_logic.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/install/phases/audit.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/install/phases/download.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/install/phases/heal.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/install/phases/integrate.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/install/phases/local_content.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/install/phases/policy_gate.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/install/phases/policy_target_check.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/install/phases/targets.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/install/presentation/__init__.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/install/presentation/dry_run.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/install/registry_wiring.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/install/request.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/install/resolution_staging.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/install/root_redirect.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/install/service.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/install/services.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/install/skill_path_migration.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/install/summary.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/install/target_filter.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/install/target_warnings.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/install/template.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/install/transaction.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/integration/__init__.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/integration/_shared.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/integration/canvas_integrator.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/integration/command_integrator.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/integration/copilot_app_db.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/integration/copilot_app_project.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/integration/copilot_app_workflow_integrator.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/integration/copilot_app_ws.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/integration/copilot_cowork_paths.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/integration/coverage.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/integration/dispatch.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/integration/hook_bundle.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/integration/hook_file_routing.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/integration/hook_ir.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/integration/hook_native_formats.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/integration/instruction_integrator.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/integration/lsp_integrator.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/integration/mcp_integrator.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/integration/mcp_integrator_install.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/integration/prompt_integrator.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/integration/skill_transformer.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/integration/targets.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/integration/utils.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/marketplace/__init__.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/marketplace/_git_utils.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/marketplace/_io.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/marketplace/_shared.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/marketplace/audit.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/marketplace/auth_helpers.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/marketplace/builder.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/marketplace/client.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/marketplace/diagnostics.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/marketplace/drift_check.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/marketplace/errors.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/marketplace/git_stderr.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/marketplace/init_template.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/marketplace/migration.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/marketplace/models.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/marketplace/output_profiles.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/marketplace/registry.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/marketplace/semver.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/marketplace/shadow_detector.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/marketplace/tag_pattern.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/marketplace/validator.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/marketplace/version_check.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/marketplace/version_pins.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/marketplace/version_resolver.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/marketplace/yml_editor.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/models/__init__.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/models/dependency/__init__.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/models/dependency/lsp.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/models/dependency/mcp.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/models/dependency/types.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/models/format_detection.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/models/manifest_contract.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/models/plugin.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/models/results.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/output/__init__.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/output/formatters.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/output/models.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/output/script_formatters.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/policy/__init__.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/policy/_constraint_pinning.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/policy/_help_text.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/policy/_shared.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/policy/inheritance.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/policy/matcher.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/policy/project_config.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/policy/schema.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/primitives/__init__.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/primitives/discovery.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/primitives/models.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/primitives/parser.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/registry/__init__.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/registry/client.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/registry/integration.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/registry/operations.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/runtime/__init__.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/runtime/codex_runtime.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/runtime/copilot_runtime.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/runtime/factory.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/runtime/registry.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/runtime/utils.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/security/__init__.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/security/content_scanner.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/security/executables.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/security/external/__init__.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/security/external/base.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/security/external/gate.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/security/external/generic_sarif.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/security/external/options.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/security/external/registry.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/security/external/runner.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/security/external/sarif_ingest.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/security/external/skillspector.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/security/gate.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/update_policy.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/utils/__init__.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/utils/archive.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/utils/atomic_io.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/utils/console.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/utils/content_hash.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/utils/exclude.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/utils/file_ops.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/utils/git_sparse.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/utils/github_host.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/utils/guards.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/utils/helpers.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/utils/install_tui.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/utils/normalization.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/utils/path_security.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/utils/paths.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/utils/patterns.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/utils/perf_stats.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/utils/reflink.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/utils/short_sha.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/utils/subprocess_env.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/utils/version_checker.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/utils/yaml_io.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/version.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/workflow/__init__.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/workflow/discovery.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/workflow/parser.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli/workflow/runner.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli.egg-info/dependency_links.txt +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli.egg-info/entry_points.txt +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/src/apm_cli.egg-info/top_level.txt +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/tests/test_apm_package_models.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/tests/test_apm_resolver.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/tests/test_codex_docker_args_fix.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/tests/test_codex_empty_string_and_defaults.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/tests/test_collision_integration.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/tests/test_console.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/tests/test_distributed_compilation.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/tests/test_empty_string_and_defaults.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/tests/test_enhanced_discovery.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/tests/test_github_downloader_token_precedence.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/tests/test_lockfile.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/tests/test_runnable_prompts.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/tests/test_runtime_manager_token_precedence.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/tests/test_token_manager.py +0 -0
- {apm_cli-0.25.0 → apm_cli-0.26.0}/tests/test_virtual_package_multi_install.py +0 -0
|
@@ -334,6 +334,43 @@ Copyright 2019 Kenneth Reitz
|
|
|
334
334
|
|
|
335
335
|
---
|
|
336
336
|
|
|
337
|
+
## Component. truststore
|
|
338
|
+
|
|
339
|
+
- Version requirement: `>=0.10.0`
|
|
340
|
+
- Upstream: https://github.com/sethmlarson/truststore
|
|
341
|
+
- SPDX: `MIT`
|
|
342
|
+
- Notes: Verifies HTTPS against the operating-system trust store by default so `apm` works behind a corporate CA / TLS-inspecting proxy.
|
|
343
|
+
|
|
344
|
+
### Open Source License/Copyright Notice.
|
|
345
|
+
|
|
346
|
+
_Copyright (c) 2022 Seth Michael Larson_
|
|
347
|
+
|
|
348
|
+
```
|
|
349
|
+
The MIT License (MIT)
|
|
350
|
+
|
|
351
|
+
Copyright (c) 2022 Seth Michael Larson
|
|
352
|
+
|
|
353
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
354
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
355
|
+
in the Software without restriction, including without limitation the rights
|
|
356
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
357
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
358
|
+
furnished to do so, subject to the following conditions:
|
|
359
|
+
|
|
360
|
+
The above copyright notice and this permission notice shall be included in
|
|
361
|
+
all copies or substantial portions of the Software.
|
|
362
|
+
|
|
363
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
364
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
365
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
366
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
367
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
368
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
369
|
+
THE SOFTWARE.
|
|
370
|
+
```
|
|
371
|
+
|
|
372
|
+
---
|
|
373
|
+
|
|
337
374
|
## Component. python-frontmatter
|
|
338
375
|
|
|
339
376
|
- Version requirement: `>=1.0.0`
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: apm-cli
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.26.0
|
|
4
4
|
Summary: MCP configuration tool
|
|
5
5
|
Author-email: Daniel Meppiel <user@example.com>
|
|
6
6
|
License: MIT License
|
|
@@ -41,6 +41,7 @@ Requires-Dist: click>=8.0.0
|
|
|
41
41
|
Requires-Dist: colorama>=0.4.6
|
|
42
42
|
Requires-Dist: pyyaml>=6.0.0
|
|
43
43
|
Requires-Dist: requests>=2.31.0
|
|
44
|
+
Requires-Dist: truststore>=0.10.0
|
|
44
45
|
Requires-Dist: python-frontmatter>=1.0.0
|
|
45
46
|
Requires-Dist: llm>=0.28
|
|
46
47
|
Requires-Dist: llm-github-models>=0.18.0
|
|
@@ -63,6 +64,8 @@ Requires-Dist: ruff>=0.11.0; extra == "dev"
|
|
|
63
64
|
Requires-Dist: mypy>=1.0.0; extra == "dev"
|
|
64
65
|
Requires-Dist: jsonschema>=4.0.0; extra == "dev"
|
|
65
66
|
Requires-Dist: pylint>=3.0.0; extra == "dev"
|
|
67
|
+
Requires-Dist: hypothesis>=6.0.0; extra == "dev"
|
|
68
|
+
Requires-Dist: mutmut==3.6.0; extra == "dev"
|
|
66
69
|
Provides-Extra: build
|
|
67
70
|
Requires-Dist: pyinstaller>=6.0.0; extra == "build"
|
|
68
71
|
Dynamic: license-file
|
|
@@ -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.26.0"
|
|
8
8
|
description = "MCP configuration tool"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.10"
|
|
@@ -26,6 +26,7 @@ dependencies = [
|
|
|
26
26
|
"colorama>=0.4.6",
|
|
27
27
|
"pyyaml>=6.0.0",
|
|
28
28
|
"requests>=2.31.0",
|
|
29
|
+
"truststore>=0.10.0",
|
|
29
30
|
"python-frontmatter>=1.0.0",
|
|
30
31
|
"llm>=0.28",
|
|
31
32
|
"llm-github-models>=0.18.0",
|
|
@@ -51,6 +52,8 @@ dev = [
|
|
|
51
52
|
"mypy>=1.0.0",
|
|
52
53
|
"jsonschema>=4.0.0",
|
|
53
54
|
"pylint>=3.0.0",
|
|
55
|
+
"hypothesis>=6.0.0",
|
|
56
|
+
"mutmut==3.6.0",
|
|
54
57
|
]
|
|
55
58
|
build = [
|
|
56
59
|
"pyinstaller>=6.0.0",
|
|
@@ -63,6 +66,12 @@ apm = "apm_cli.cli:main"
|
|
|
63
66
|
where = ["src"]
|
|
64
67
|
include = ["apm_cli*"]
|
|
65
68
|
|
|
69
|
+
[tool.setuptools.package-data]
|
|
70
|
+
# Belt-and-suspenders: ship the child-TLS .pth alongside the bootstrap module.
|
|
71
|
+
# Delivery no longer depends on this (ensure_child_tls_bootstrap generates the
|
|
72
|
+
# .pth inline), but packaging it keeps the source tree and wheel in sync.
|
|
73
|
+
"apm_cli.core._child_tls" = ["*.pth"]
|
|
74
|
+
|
|
66
75
|
[tool.ruff]
|
|
67
76
|
line-length = 100
|
|
68
77
|
target-version = "py310"
|
|
@@ -152,22 +161,62 @@ exclude_lines = [
|
|
|
152
161
|
"@overload",
|
|
153
162
|
]
|
|
154
163
|
|
|
164
|
+
[tool.mutmut]
|
|
165
|
+
source_paths = ["src/"]
|
|
166
|
+
only_mutate = [
|
|
167
|
+
"src/apm_cli/models/dependency/subsets.py",
|
|
168
|
+
"src/apm_cli/install/plan.py",
|
|
169
|
+
"src/apm_cli/policy/discovery.py",
|
|
170
|
+
"src/apm_cli/compilation/link_resolver.py",
|
|
171
|
+
"src/apm_cli/deps/lockfile.py",
|
|
172
|
+
]
|
|
173
|
+
pytest_add_cli_args = [
|
|
174
|
+
"-n0",
|
|
175
|
+
"-p",
|
|
176
|
+
"no:cacheprovider",
|
|
177
|
+
"-o",
|
|
178
|
+
"addopts=",
|
|
179
|
+
]
|
|
180
|
+
pytest_add_cli_args_test_selection = [
|
|
181
|
+
"tests/unit/test_skill_subset_persistence.py",
|
|
182
|
+
"tests/unit/test_dep_targets_persistence.py",
|
|
183
|
+
"tests/unit/install/test_plan.py",
|
|
184
|
+
"tests/unit/policy/test_cache_merged_effective.py::test_policy_serializer_covers_every_dataclass_leaf",
|
|
185
|
+
"tests/unit/policy/test_cache_merged_effective.py::test_policy_serializer_preserves_sparse_bin_deploy_shapes",
|
|
186
|
+
"tests/unit/policy/test_cache_merged_effective.py::TestPolicyRoundTrip::test_all_effective_policy_fields_survive_cache_round_trip",
|
|
187
|
+
"tests/unit/compilation/test_link_resolver.py",
|
|
188
|
+
"tests/unit/compilation/test_link_resolver_phase3.py",
|
|
189
|
+
"tests/unit/compilation/test_link_resolver_resolution.py",
|
|
190
|
+
"tests/unit/deps/test_lockfile_field_properties.py",
|
|
191
|
+
]
|
|
192
|
+
timeout_constant = 1.0
|
|
193
|
+
timeout_multiplier = 5.0
|
|
194
|
+
use_setproctitle = false
|
|
195
|
+
|
|
155
196
|
[tool.pytest.ini_options]
|
|
156
|
-
addopts = "-m 'not benchmark and not live'"
|
|
197
|
+
addopts = "-m 'not benchmark and not live' --strict-markers"
|
|
198
|
+
testpaths = ["tests"]
|
|
157
199
|
markers = [
|
|
200
|
+
"unit: pure logic with no filesystem and no CLI",
|
|
201
|
+
"component: in-process behavior that touches a filesystem or one command boundary",
|
|
202
|
+
"e2e: a real installed CLI crossing at least one command boundary",
|
|
158
203
|
"integration: marks tests as integration tests that may require network access",
|
|
159
204
|
"live: marks tests that hit real GitHub repos (requires network + optional GITHUB_TOKEN)",
|
|
160
205
|
"slow: marks tests as slow running tests",
|
|
161
206
|
"benchmark: marks performance benchmark tests (deselected by default, run with -m benchmark)",
|
|
207
|
+
"windows_compat: load-bearing cross-platform regression contract family (CRLF-safe atomic writes, portable path formatting, git-executable resolution, socket/thread shutdown); runs on every OS and is additionally selected by the PR-time Windows Compatibility Gate -- NOT a requires_windows skip-gate, do not use requires_windows for this",
|
|
162
208
|
"requires_e2e_mode: requires APM_E2E_TESTS=1",
|
|
163
209
|
"requires_github_token: requires GITHUB_APM_PAT or GITHUB_TOKEN",
|
|
164
210
|
"requires_ado_pat: requires ADO_APM_PAT",
|
|
165
211
|
"requires_ado_bearer: requires az CLI logged in + APM_TEST_ADO_BEARER=1",
|
|
166
212
|
"requires_network_integration: requires APM_RUN_INTEGRATION_TESTS=1",
|
|
213
|
+
"requires_windows: requires a Windows host",
|
|
167
214
|
"requires_apm_binary: requires built apm binary on PATH (or APM_BINARY_PATH)",
|
|
168
215
|
"requires_runtime_codex: requires codex runtime installed",
|
|
169
216
|
"requires_runtime_copilot: requires GitHub Copilot CLI runtime installed",
|
|
170
217
|
"requires_runtime_llm: requires llm runtime installed",
|
|
171
218
|
"requires_inference: requires APM_RUN_INFERENCE_TESTS=1 + model API access",
|
|
172
219
|
"req: binds a test to one or more OpenAPM req-XXX ids (spec-conformance suite)",
|
|
220
|
+
"lifecycle_smoke: promoted to the required PR-time Lifecycle Smoke (Linux) job -- see ci.yml's lifecycle-smoke job and docs/src/content/docs/contributing/integration-testing.md",
|
|
221
|
+
"lifecycle_merge_group: unique lifecycle contracts retained in the full merge-group integration suite",
|
|
173
222
|
]
|
|
@@ -22,6 +22,7 @@ from ..deps.lockfile import (
|
|
|
22
22
|
migrate_lockfile_if_needed,
|
|
23
23
|
)
|
|
24
24
|
from ..models.apm_package import APMPackage, DependencyReference
|
|
25
|
+
from ..models.dependency.subsets import skill_subset_filter_tokens
|
|
25
26
|
from ..utils.archive import (
|
|
26
27
|
projected_archive_path,
|
|
27
28
|
validate_archive_format,
|
|
@@ -641,7 +642,7 @@ def _collect_deployed_components(
|
|
|
641
642
|
components: list[tuple[Path, str]] = []
|
|
642
643
|
missing: list[str] = []
|
|
643
644
|
seen_outputs: set[str] = set()
|
|
644
|
-
skill_subset =
|
|
645
|
+
skill_subset = skill_subset_filter_tokens(dep.skill_subset)
|
|
645
646
|
|
|
646
647
|
for rel_path in dep.deployed_files:
|
|
647
648
|
try:
|
|
@@ -108,8 +108,8 @@ def normalize_repo_url(url: str) -> str:
|
|
|
108
108
|
if port:
|
|
109
109
|
authority = f"{authority}:{port}"
|
|
110
110
|
|
|
111
|
-
# Step 1: Strip trailing .git from path
|
|
112
|
-
path = parsed.path or ""
|
|
111
|
+
# Step 1: Strip trailing slash and one trailing .git suffix from path.
|
|
112
|
+
path = (parsed.path or "").rstrip("/")
|
|
113
113
|
if path.endswith(".git"):
|
|
114
114
|
path = path[:-4]
|
|
115
115
|
|
|
@@ -122,9 +122,6 @@ def normalize_repo_url(url: str) -> str:
|
|
|
122
122
|
if hostname in _CASE_INSENSITIVE_HOSTS:
|
|
123
123
|
path = path.lower()
|
|
124
124
|
|
|
125
|
-
# Strip trailing slash from path
|
|
126
|
-
path = path.rstrip("/")
|
|
127
|
-
|
|
128
125
|
# Reconstruct normalized URL
|
|
129
126
|
return f"{scheme}://{authority}{path}"
|
|
130
127
|
|
|
@@ -3,6 +3,8 @@
|
|
|
3
3
|
Thin wiring layer -- all command logic lives in ``apm_cli.commands.*`` modules.
|
|
4
4
|
"""
|
|
5
5
|
|
|
6
|
+
# ruff: noqa: E402
|
|
7
|
+
|
|
6
8
|
import ctypes
|
|
7
9
|
import logging
|
|
8
10
|
import os
|
|
@@ -11,6 +13,10 @@ import warnings
|
|
|
11
13
|
|
|
12
14
|
import click
|
|
13
15
|
|
|
16
|
+
from apm_cli.core.tls_trust import configure_process_tls_trust, log_tls_trust_status
|
|
17
|
+
|
|
18
|
+
configure_process_tls_trust()
|
|
19
|
+
|
|
14
20
|
from apm_cli.commands._helpers import (
|
|
15
21
|
ERROR,
|
|
16
22
|
RESET,
|
|
@@ -153,6 +159,7 @@ def cli(ctx, verbose: bool) -> None:
|
|
|
153
159
|
if verbose:
|
|
154
160
|
# Upgrade to DEBUG when the flag is set; env-var path runs in main().
|
|
155
161
|
_configure_logging(verbose=True)
|
|
162
|
+
log_tls_trust_status()
|
|
156
163
|
|
|
157
164
|
# Suppress only the agents-target deprecation warning so CLI users see
|
|
158
165
|
# the formatted logger.warning() in the install phase, not a double print.
|
|
@@ -352,6 +359,7 @@ def main():
|
|
|
352
359
|
"""Main entry point for the CLI."""
|
|
353
360
|
_configure_logging() # honours APM_LOG_LEVEL env var; --verbose upgrades in cli()
|
|
354
361
|
_configure_encoding()
|
|
362
|
+
configure_process_tls_trust()
|
|
355
363
|
try:
|
|
356
364
|
cli(obj={})
|
|
357
365
|
except Exception as e:
|
|
@@ -23,8 +23,22 @@ from pathlib import Path
|
|
|
23
23
|
|
|
24
24
|
import click
|
|
25
25
|
|
|
26
|
+
from ..core.command_logger import CommandLogger
|
|
27
|
+
from ..policy import outcome_routing as policy_outcomes
|
|
28
|
+
from ..policy.outcome_routing import POLICY_RESOLUTION_FAILURE_OUTCOMES
|
|
29
|
+
from ..policy.schema import ApmPolicy
|
|
26
30
|
from ..utils.console import _rich_echo, _rich_error, _rich_info, _rich_success, _rich_warning
|
|
27
31
|
|
|
32
|
+
_POLICY_RESOLUTION_WARNING = (
|
|
33
|
+
"Org policy could not be resolved; approval is proceeding without org "
|
|
34
|
+
"restrictions. Run 'apm policy status --no-cache' to diagnose."
|
|
35
|
+
)
|
|
36
|
+
_POLICY_HASH_MISMATCH_WARNING = (
|
|
37
|
+
"Policy hash verification failed; this may indicate policy tampering. "
|
|
38
|
+
"Approval is proceeding without org restrictions. "
|
|
39
|
+
"Run 'apm policy status --no-cache' to verify the policy source."
|
|
40
|
+
)
|
|
41
|
+
|
|
28
42
|
|
|
29
43
|
def _find_manifest() -> Path:
|
|
30
44
|
"""Return the project's ``apm.yml`` path or exit."""
|
|
@@ -70,24 +84,29 @@ def _store_label(user_scope: bool) -> str:
|
|
|
70
84
|
return "~/.apm/config.json" if user_scope else "apm.yml executables block"
|
|
71
85
|
|
|
72
86
|
|
|
73
|
-
def _load_org_policy(project_root: Path):
|
|
87
|
+
def _load_org_policy(project_root: Path, logger: CommandLogger | None = None) -> ApmPolicy:
|
|
74
88
|
"""Best-effort load of the merged org policy. Returns a default on failure."""
|
|
75
|
-
|
|
76
|
-
|
|
89
|
+
warning: str | None = None
|
|
77
90
|
try:
|
|
78
|
-
from ..policy.discovery import
|
|
91
|
+
from ..policy.discovery import discover_policy_with_chain
|
|
79
92
|
|
|
80
|
-
result =
|
|
93
|
+
result = discover_policy_with_chain(project_root)
|
|
81
94
|
if getattr(result, "policy", None) is not None:
|
|
82
95
|
return result.policy
|
|
96
|
+
if result.outcome == policy_outcomes.POLICY_HASH_MISMATCH_OUTCOME:
|
|
97
|
+
warning = _POLICY_HASH_MISMATCH_WARNING
|
|
98
|
+
elif result.outcome in POLICY_RESOLUTION_FAILURE_OUTCOMES:
|
|
99
|
+
warning = _POLICY_RESOLUTION_WARNING
|
|
83
100
|
except Exception:
|
|
84
|
-
|
|
101
|
+
warning = _POLICY_RESOLUTION_WARNING
|
|
102
|
+
if warning is not None and logger is not None:
|
|
103
|
+
logger.warning(warning)
|
|
85
104
|
return ApmPolicy()
|
|
86
105
|
|
|
87
106
|
|
|
88
|
-
def load_org_policy(project_root: Path):
|
|
107
|
+
def load_org_policy(project_root: Path, logger: CommandLogger | None = None) -> ApmPolicy:
|
|
89
108
|
"""Public wrapper for best-effort merged org policy loading."""
|
|
90
|
-
return _load_org_policy(project_root)
|
|
109
|
+
return _load_org_policy(project_root, logger=logger)
|
|
91
110
|
|
|
92
111
|
|
|
93
112
|
@click.command("approve")
|
|
@@ -136,31 +155,35 @@ def approve_cmd(
|
|
|
136
155
|
|
|
137
156
|
apm approve --user owner/repo
|
|
138
157
|
"""
|
|
139
|
-
|
|
158
|
+
logger = CommandLogger("approve")
|
|
159
|
+
try:
|
|
160
|
+
manifest = _find_manifest()
|
|
140
161
|
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
162
|
+
if list_decisions:
|
|
163
|
+
_list_decisions(manifest, logger=logger)
|
|
164
|
+
return
|
|
144
165
|
|
|
145
|
-
|
|
166
|
+
allow, deny = _load_store(manifest, user_scope)
|
|
146
167
|
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
168
|
+
if pending:
|
|
169
|
+
_show_pending(manifest, allow)
|
|
170
|
+
return
|
|
150
171
|
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
172
|
+
if recommended:
|
|
173
|
+
_approve_recommended(manifest, user_scope, allow, deny, logger=logger)
|
|
174
|
+
return
|
|
154
175
|
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
176
|
+
if approve_all:
|
|
177
|
+
_approve_all_pending(manifest, user_scope, allow, deny)
|
|
178
|
+
return
|
|
158
179
|
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
180
|
+
if not packages:
|
|
181
|
+
_rich_error("Specify at least one package, or use --pending / --all / --recommended.")
|
|
182
|
+
sys.exit(1)
|
|
162
183
|
|
|
163
|
-
|
|
184
|
+
_approve_packages(manifest, user_scope, allow, deny, packages)
|
|
185
|
+
finally:
|
|
186
|
+
logger.render_summary()
|
|
164
187
|
|
|
165
188
|
|
|
166
189
|
@click.command("deny")
|
|
@@ -213,7 +236,7 @@ def deny_cmd(packages: tuple[str, ...], user_scope: bool) -> None:
|
|
|
213
236
|
_rich_info(f"Updated {_store_label(user_scope)} ({changed} denied).", symbol="info")
|
|
214
237
|
|
|
215
238
|
|
|
216
|
-
def explain_decision(package: str) -> None:
|
|
239
|
+
def explain_decision(package: str, *, logger: CommandLogger) -> None:
|
|
217
240
|
"""Explain the effective executable-trust decision for a package.
|
|
218
241
|
|
|
219
242
|
Shows, per executable type the package declares, whether it is allowed,
|
|
@@ -232,7 +255,7 @@ def explain_decision(package: str) -> None:
|
|
|
232
255
|
|
|
233
256
|
data = load_yaml(manifest)
|
|
234
257
|
project_data = data if isinstance(data, dict) else {}
|
|
235
|
-
policy = _load_org_policy(manifest.parent)
|
|
258
|
+
policy = _load_org_policy(manifest.parent, logger=logger)
|
|
236
259
|
ctx = build_exec_trust_context(policy=policy, project_data=project_data)
|
|
237
260
|
|
|
238
261
|
declarations = _scan_installed_packages(manifest)
|
|
@@ -275,14 +298,14 @@ def explain_decision(package: str) -> None:
|
|
|
275
298
|
)
|
|
276
299
|
|
|
277
300
|
|
|
278
|
-
def _list_decisions(manifest: Path) -> None:
|
|
301
|
+
def _list_decisions(manifest: Path, *, logger: CommandLogger) -> None:
|
|
279
302
|
"""Print the effective trust decision + deciding layer per installed package."""
|
|
280
303
|
from ..security.executables import build_exec_trust_context, resolve_exec_decision
|
|
281
304
|
from ..utils.yaml_io import load_yaml
|
|
282
305
|
|
|
283
306
|
data = load_yaml(manifest)
|
|
284
307
|
project_data = data if isinstance(data, dict) else {}
|
|
285
|
-
policy = _load_org_policy(manifest.parent)
|
|
308
|
+
policy = _load_org_policy(manifest.parent, logger=logger)
|
|
286
309
|
ctx = build_exec_trust_context(policy=policy, project_data=project_data)
|
|
287
310
|
|
|
288
311
|
declarations = [d for d in _scan_installed_packages(manifest) if d.has_executables]
|
|
@@ -364,9 +387,11 @@ def _approve_recommended(
|
|
|
364
387
|
user_scope: bool,
|
|
365
388
|
allow: dict[str, dict[str, bool]],
|
|
366
389
|
deny: dict[str, dict[str, bool]],
|
|
390
|
+
*,
|
|
391
|
+
logger: CommandLogger,
|
|
367
392
|
) -> None:
|
|
368
393
|
"""Bulk-approve the org ``executables.recommend`` set."""
|
|
369
|
-
policy = _load_org_policy(manifest.parent)
|
|
394
|
+
policy = _load_org_policy(manifest.parent, logger=logger)
|
|
370
395
|
recommend = set(getattr(getattr(policy, "executables", None), "recommend", ()) or ())
|
|
371
396
|
if not recommend:
|
|
372
397
|
_rich_info("No org-recommended executables to approve.", symbol="info")
|
|
@@ -17,6 +17,11 @@ from pathlib import Path
|
|
|
17
17
|
import click
|
|
18
18
|
|
|
19
19
|
from ..core.command_logger import CommandLogger
|
|
20
|
+
from ..core.deployment_ledger import (
|
|
21
|
+
DEPLOYMENT_OWNER_REMEDIATION,
|
|
22
|
+
DeploymentLedgerCodec,
|
|
23
|
+
DeploymentOwnerViolation,
|
|
24
|
+
)
|
|
20
25
|
from ..deps.lockfile import LockFile, get_lockfile_path
|
|
21
26
|
from ..policy._help_text import POLICY_SOURCE_FORMS_HELP
|
|
22
27
|
from ..security.content_scanner import ContentScanner, ScanFinding
|
|
@@ -313,6 +318,25 @@ def _render_summary(
|
|
|
313
318
|
logger.progress(f" Plus {info} info-level finding(s) (use --verbose to see)")
|
|
314
319
|
|
|
315
320
|
|
|
321
|
+
def _render_owner_violations(
|
|
322
|
+
violations: tuple[DeploymentOwnerViolation, ...],
|
|
323
|
+
logger: CommandLogger,
|
|
324
|
+
) -> None:
|
|
325
|
+
"""Render invalid canonical owner references with one remediation."""
|
|
326
|
+
if not violations:
|
|
327
|
+
return
|
|
328
|
+
logger.error(f"{len(violations)} invalid deployment ownership record(s) in apm.lock.yaml")
|
|
329
|
+
for violation in violations:
|
|
330
|
+
invalid = ", ".join(violation.invalid_owners)
|
|
331
|
+
active = (
|
|
332
|
+
f"; active owner={violation.invalid_active_owner}"
|
|
333
|
+
if violation.invalid_active_owner is not None
|
|
334
|
+
else ""
|
|
335
|
+
)
|
|
336
|
+
logger.error_detail(f" {violation.locator.key}: invalid owner(s)={invalid}{active}")
|
|
337
|
+
logger.error_detail(DEPLOYMENT_OWNER_REMEDIATION)
|
|
338
|
+
|
|
339
|
+
|
|
316
340
|
def _apply_strip(
|
|
317
341
|
findings_by_file: dict[str, list[ScanFinding]],
|
|
318
342
|
project_root: Path,
|
|
@@ -618,6 +642,7 @@ def _audit_ci_gate(
|
|
|
618
642
|
pass # Policy checks disabled
|
|
619
643
|
else:
|
|
620
644
|
from ..policy.models import CheckResult
|
|
645
|
+
from ..policy.policy_checks import FAIL_CLOSED_POLICY_CHECKS
|
|
621
646
|
|
|
622
647
|
policy_result = run_policy_checks(cfg.project_root, policy_obj, fail_fast=fail_fast)
|
|
623
648
|
if policy_obj.enforcement == "block":
|
|
@@ -625,6 +650,9 @@ def _audit_ci_gate(
|
|
|
625
650
|
else:
|
|
626
651
|
# enforcement == "warn": include results but don't fail
|
|
627
652
|
for check in policy_result.checks:
|
|
653
|
+
if check.name in FAIL_CLOSED_POLICY_CHECKS and not check.passed:
|
|
654
|
+
ci_result.checks.append(check)
|
|
655
|
+
continue
|
|
628
656
|
ci_result.checks.append(
|
|
629
657
|
CheckResult(
|
|
630
658
|
name=check.name,
|
|
@@ -840,6 +868,7 @@ def _audit_content_scan(
|
|
|
840
868
|
# -- File mode: scan a single arbitrary file --
|
|
841
869
|
findings_by_file, files_scanned = _scan_single_file(Path(file_path), logger)
|
|
842
870
|
scan_paths = [Path(file_path)]
|
|
871
|
+
owner_violations: tuple[DeploymentOwnerViolation, ...] = ()
|
|
843
872
|
else:
|
|
844
873
|
scan_paths = [project_root]
|
|
845
874
|
# -- Package mode: scan from lockfile --
|
|
@@ -854,23 +883,31 @@ def _audit_content_scan(
|
|
|
854
883
|
# empty native result set so their findings still surface.
|
|
855
884
|
findings_by_file, files_scanned = {}, 0
|
|
856
885
|
else:
|
|
857
|
-
if
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
886
|
+
if effective_format == "text":
|
|
887
|
+
if package:
|
|
888
|
+
logger.progress(f"Scanning package: {package}")
|
|
889
|
+
else:
|
|
890
|
+
logger.start("Scanning all installed packages...")
|
|
861
891
|
|
|
862
892
|
from apm_cli.deps.lockfile import LockfileFormatError
|
|
863
893
|
|
|
864
894
|
try:
|
|
895
|
+
lockfile = LockFile.read(lockfile_path)
|
|
896
|
+
owner_violations = (
|
|
897
|
+
DeploymentLedgerCodec.owner_reference_violations(lockfile)
|
|
898
|
+
if lockfile is not None
|
|
899
|
+
else ()
|
|
900
|
+
)
|
|
865
901
|
findings_by_file, files_scanned = scan_lockfile_packages(
|
|
866
902
|
project_root,
|
|
867
903
|
package_filter=package,
|
|
904
|
+
lockfile=lockfile,
|
|
868
905
|
)
|
|
869
906
|
except LockfileFormatError as exc:
|
|
870
907
|
logger.error(f"Cannot audit invalid apm.lock.yaml: {exc}")
|
|
871
908
|
sys.exit(1)
|
|
872
909
|
|
|
873
|
-
if files_scanned == 0 and not external:
|
|
910
|
+
if files_scanned == 0 and not external and not owner_violations:
|
|
874
911
|
if package:
|
|
875
912
|
logger.warning(
|
|
876
913
|
f"Package '{package}' not found in apm.lock.yaml or has no deployed files"
|
|
@@ -878,6 +915,8 @@ def _audit_content_scan(
|
|
|
878
915
|
else:
|
|
879
916
|
logger.progress("No deployed files found in apm.lock.yaml")
|
|
880
917
|
sys.exit(0)
|
|
918
|
+
if not lockfile_path.exists():
|
|
919
|
+
owner_violations = ()
|
|
881
920
|
|
|
882
921
|
# -- External scanners (opt-in, additive) -----------------------
|
|
883
922
|
if external:
|
|
@@ -895,6 +934,10 @@ def _audit_content_scan(
|
|
|
895
934
|
|
|
896
935
|
# -- Strip mode --
|
|
897
936
|
if strip:
|
|
937
|
+
if owner_violations:
|
|
938
|
+
_render_owner_violations(owner_violations, logger)
|
|
939
|
+
logger.error_detail("Content was not modified while lockfile ownership is invalid.")
|
|
940
|
+
sys.exit(1)
|
|
898
941
|
if not findings_by_file:
|
|
899
942
|
logger.progress("Nothing to clean -- no hidden characters found")
|
|
900
943
|
sys.exit(0)
|
|
@@ -971,6 +1014,8 @@ def _audit_content_scan(
|
|
|
971
1014
|
else:
|
|
972
1015
|
all_findings = [f for ff in findings_by_file.values() for f in ff]
|
|
973
1016
|
exit_code = 1 if ContentScanner.has_critical(all_findings) else 2
|
|
1017
|
+
if owner_violations:
|
|
1018
|
+
exit_code = 1
|
|
974
1019
|
|
|
975
1020
|
# Bare `apm audit` is advisory for drift by default: drift findings are
|
|
976
1021
|
# rendered (text/json/sarif) but DO NOT escalate the exit code. When
|
|
@@ -993,7 +1038,10 @@ def _audit_content_scan(
|
|
|
993
1038
|
sys.exit(1)
|
|
994
1039
|
if findings_by_file:
|
|
995
1040
|
_render_findings_table(findings_by_file, verbose=cfg.verbose)
|
|
996
|
-
|
|
1041
|
+
_render_summary(findings_by_file, files_scanned, logger)
|
|
1042
|
+
elif not owner_violations:
|
|
1043
|
+
_render_summary(findings_by_file, files_scanned, logger)
|
|
1044
|
+
_render_owner_violations(owner_violations, logger)
|
|
997
1045
|
if not file_path:
|
|
998
1046
|
_render_canvas_note(cfg.project_root, package, logger)
|
|
999
1047
|
if drift_findings:
|
|
@@ -1004,7 +1052,11 @@ def _audit_content_scan(
|
|
|
1004
1052
|
elif effective_format == "markdown":
|
|
1005
1053
|
from ..security.audit_report import findings_to_markdown
|
|
1006
1054
|
|
|
1007
|
-
md_report = findings_to_markdown(
|
|
1055
|
+
md_report = findings_to_markdown(
|
|
1056
|
+
findings_by_file,
|
|
1057
|
+
files_scanned=files_scanned,
|
|
1058
|
+
owner_violations=owner_violations,
|
|
1059
|
+
)
|
|
1008
1060
|
if cfg.output_path:
|
|
1009
1061
|
Path(cfg.output_path).parent.mkdir(parents=True, exist_ok=True)
|
|
1010
1062
|
Path(cfg.output_path).write_text(md_report, encoding="utf-8")
|
|
@@ -1020,12 +1072,17 @@ def _audit_content_scan(
|
|
|
1020
1072
|
)
|
|
1021
1073
|
|
|
1022
1074
|
if effective_format == "sarif":
|
|
1023
|
-
report = findings_to_sarif(
|
|
1075
|
+
report = findings_to_sarif(
|
|
1076
|
+
findings_by_file,
|
|
1077
|
+
files_scanned=files_scanned,
|
|
1078
|
+
owner_violations=owner_violations,
|
|
1079
|
+
)
|
|
1024
1080
|
else:
|
|
1025
1081
|
report = findings_to_json(
|
|
1026
1082
|
findings_by_file,
|
|
1027
1083
|
files_scanned=files_scanned,
|
|
1028
1084
|
exit_code=exit_code,
|
|
1085
|
+
owner_violations=owner_violations,
|
|
1029
1086
|
)
|
|
1030
1087
|
|
|
1031
1088
|
if cfg.output_path:
|
|
@@ -17,8 +17,8 @@ from .marketplace.doctor import run_doctor
|
|
|
17
17
|
|
|
18
18
|
@click.command(
|
|
19
19
|
help=(
|
|
20
|
-
"Run environment diagnostics (git, network, auth,
|
|
21
|
-
"
|
|
20
|
+
"Run environment diagnostics (git, network, auth, marketplace "
|
|
21
|
+
"config). Reports a pass/fail table and exits non-zero "
|
|
22
22
|
"if a critical check fails."
|
|
23
23
|
)
|
|
24
24
|
)
|
|
@@ -1226,6 +1226,7 @@ def install( # noqa: PLR0913
|
|
|
1226
1226
|
force=force,
|
|
1227
1227
|
dry_run=dry_run,
|
|
1228
1228
|
verbose=verbose,
|
|
1229
|
+
no_policy=no_policy,
|
|
1229
1230
|
alias=alias,
|
|
1230
1231
|
logger=logger,
|
|
1231
1232
|
legacy_skill_paths=legacy_skill_paths,
|
|
@@ -1246,7 +1247,6 @@ def install( # noqa: PLR0913
|
|
|
1246
1247
|
"--parallel-downloads": parallel_downloads != 4,
|
|
1247
1248
|
"--allow-insecure": allow_insecure,
|
|
1248
1249
|
"--allow-insecure-host": bool(allow_insecure_hosts),
|
|
1249
|
-
"--no-policy": no_policy,
|
|
1250
1250
|
},
|
|
1251
1251
|
)
|
|
1252
1252
|
# Local bundle install renders its own summary; mark
|
|
@@ -21,7 +21,9 @@ from . import (
|
|
|
21
21
|
)
|
|
22
22
|
|
|
23
23
|
|
|
24
|
-
def _executable_trust_drift_check(
|
|
24
|
+
def _executable_trust_drift_check(
|
|
25
|
+
project_root: Path, logger: CommandLogger | None = None
|
|
26
|
+
) -> _DoctorCheck | None:
|
|
25
27
|
"""Fleet-level executable-trust drift probe for ``apm doctor``.
|
|
26
28
|
|
|
27
29
|
Flags packages whose project/user *allow* is overridden by the org
|
|
@@ -48,7 +50,8 @@ def _executable_trust_drift_check(project_root: Path) -> _DoctorCheck | None:
|
|
|
48
50
|
data = load_yaml(apm_path)
|
|
49
51
|
project_data = data if isinstance(data, dict) else {}
|
|
50
52
|
ctx = build_exec_trust_context(
|
|
51
|
-
policy=load_org_policy(project_root
|
|
53
|
+
policy=load_org_policy(project_root, logger=logger),
|
|
54
|
+
project_data=project_data,
|
|
52
55
|
)
|
|
53
56
|
except Exception:
|
|
54
57
|
return None
|
|
@@ -313,7 +316,7 @@ def run_doctor(verbose: bool, *, logger_name: str = "doctor") -> int:
|
|
|
313
316
|
)
|
|
314
317
|
)
|
|
315
318
|
|
|
316
|
-
drift_check = _executable_trust_drift_check(Path.cwd())
|
|
319
|
+
drift_check = _executable_trust_drift_check(Path.cwd(), logger=logger)
|
|
317
320
|
if drift_check is not None:
|
|
318
321
|
checks.append(drift_check)
|
|
319
322
|
|
|
@@ -25,7 +25,6 @@ from ..policy.discovery import (
|
|
|
25
25
|
MAX_STALE_TTL,
|
|
26
26
|
PolicyFetchResult,
|
|
27
27
|
_read_cache_entry,
|
|
28
|
-
discover_policy,
|
|
29
28
|
discover_policy_with_chain,
|
|
30
29
|
)
|
|
31
30
|
from ..policy.schema import ApmPolicy
|
|
@@ -329,18 +328,11 @@ def status(policy_source, no_cache, as_json, output_format, check):
|
|
|
329
328
|
project_root = Path.cwd()
|
|
330
329
|
|
|
331
330
|
try:
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
)
|
|
338
|
-
elif no_cache:
|
|
339
|
-
# discover_policy_with_chain has no `no_cache` knob, so go
|
|
340
|
-
# through the lower-level entry point when the user opts out.
|
|
341
|
-
result = discover_policy(project_root, no_cache=True)
|
|
342
|
-
else:
|
|
343
|
-
result = discover_policy_with_chain(project_root)
|
|
331
|
+
result = discover_policy_with_chain(
|
|
332
|
+
project_root,
|
|
333
|
+
policy_override=policy_source,
|
|
334
|
+
no_cache=no_cache,
|
|
335
|
+
)
|
|
344
336
|
except Exception as e:
|
|
345
337
|
# Diagnostic must never exit non-zero; surface the failure as a
|
|
346
338
|
# synthetic ``cache_miss_fetch_fail`` report and continue.
|
|
@@ -393,4 +385,6 @@ def explain(package):
|
|
|
393
385
|
"""
|
|
394
386
|
from .approve import explain_decision
|
|
395
387
|
|
|
396
|
-
|
|
388
|
+
logger = CommandLogger("policy explain")
|
|
389
|
+
explain_decision(package, logger=logger)
|
|
390
|
+
logger.render_summary()
|