apm-cli 0.29.1__tar.gz → 0.30.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.
Files changed (508) hide show
  1. {apm_cli-0.29.1/src/apm_cli.egg-info → apm_cli-0.30.0}/PKG-INFO +19 -7
  2. {apm_cli-0.29.1 → apm_cli-0.30.0}/README.md +18 -6
  3. {apm_cli-0.29.1 → apm_cli-0.30.0}/pyproject.toml +2 -1
  4. apm_cli-0.30.0/src/apm_cli/cache/cleanup.py +51 -0
  5. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/cache/git_cache.py +51 -27
  6. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/cache/http_cache.py +12 -7
  7. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/commands/cache.py +41 -26
  8. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/commands/config.py +22 -3
  9. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/commands/prune.py +13 -0
  10. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/commands/self_update.py +18 -4
  11. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/commands/uninstall/cli.py +53 -19
  12. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/commands/uninstall/engine.py +87 -74
  13. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/compilation/context_optimizer.py +3 -5
  14. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/deps/github_rate_limit.py +15 -0
  15. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/policy/discovery.py +1 -3
  16. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/policy/policy_checks.py +28 -6
  17. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/policy/project_config.py +12 -4
  18. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/utils/version_checker.py +131 -18
  19. {apm_cli-0.29.1 → apm_cli-0.30.0/src/apm_cli.egg-info}/PKG-INFO +19 -7
  20. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli.egg-info/SOURCES.txt +1 -0
  21. {apm_cli-0.29.1 → apm_cli-0.30.0}/AUTHORS +0 -0
  22. {apm_cli-0.29.1 → apm_cli-0.30.0}/LICENSE +0 -0
  23. {apm_cli-0.29.1 → apm_cli-0.30.0}/NOTICE +0 -0
  24. {apm_cli-0.29.1 → apm_cli-0.30.0}/setup.cfg +0 -0
  25. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/__init__.py +0 -0
  26. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/adapters/__init__.py +0 -0
  27. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/adapters/client/__init__.py +0 -0
  28. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/adapters/client/_mcp_runtime_args.py +0 -0
  29. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/adapters/client/antigravity.py +0 -0
  30. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/adapters/client/base.py +0 -0
  31. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/adapters/client/claude.py +0 -0
  32. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/adapters/client/codex.py +0 -0
  33. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/adapters/client/copilot.py +0 -0
  34. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/adapters/client/cursor.py +0 -0
  35. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/adapters/client/gemini.py +0 -0
  36. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/adapters/client/hermes.py +0 -0
  37. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/adapters/client/intellij.py +0 -0
  38. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/adapters/client/kiro.py +0 -0
  39. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/adapters/client/opencode.py +0 -0
  40. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/adapters/client/vscode.py +0 -0
  41. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/adapters/client/windsurf.py +0 -0
  42. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/adapters/package_manager/__init__.py +0 -0
  43. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/adapters/package_manager/base.py +0 -0
  44. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/adapters/package_manager/default_manager.py +0 -0
  45. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/agent_plugins/__init__.py +0 -0
  46. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/agent_plugins/assets.py +0 -0
  47. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/agent_plugins/constants.py +0 -0
  48. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/agent_plugins/errors.py +0 -0
  49. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/agent_plugins/io.py +0 -0
  50. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/agent_plugins/ir.py +0 -0
  51. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/agent_plugins/loader.py +0 -0
  52. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/agent_plugins/projection.py +0 -0
  53. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/agent_plugins/validation.py +0 -0
  54. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/bootstrap_mirror.py +0 -0
  55. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/bundle/__init__.py +0 -0
  56. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/bundle/agent_plugin_exporter.py +0 -0
  57. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/bundle/attest.py +0 -0
  58. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/bundle/claude_plugin_exporter.py +0 -0
  59. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/bundle/export_common.py +0 -0
  60. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/bundle/formats.py +0 -0
  61. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/bundle/local_bundle.py +0 -0
  62. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/bundle/lockfile_enrichment.py +0 -0
  63. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/bundle/packer.py +0 -0
  64. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/bundle/plugin_exporter.py +0 -0
  65. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/bundle/plugin_layout.py +0 -0
  66. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/bundle/reproducible_archive.py +0 -0
  67. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/bundle/unpacker.py +0 -0
  68. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/cache/__init__.py +0 -0
  69. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/cache/integrity.py +0 -0
  70. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/cache/locking.py +0 -0
  71. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/cache/paths.py +0 -0
  72. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/cache/url_normalize.py +0 -0
  73. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/cli.py +0 -0
  74. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/commands/__init__.py +0 -0
  75. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/commands/_apm_yml_writer.py +0 -0
  76. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/commands/_helpers.py +0 -0
  77. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/commands/approve.py +0 -0
  78. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/commands/audit.py +0 -0
  79. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/commands/compile/__init__.py +0 -0
  80. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/commands/compile/cli.py +0 -0
  81. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/commands/compile/watcher.py +0 -0
  82. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/commands/deps/__init__.py +0 -0
  83. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/commands/deps/_utils.py +0 -0
  84. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/commands/deps/cli.py +0 -0
  85. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/commands/deps/why.py +0 -0
  86. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/commands/doctor.py +0 -0
  87. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/commands/experimental.py +0 -0
  88. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/commands/find.py +0 -0
  89. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/commands/init.py +0 -0
  90. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/commands/install.py +0 -0
  91. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/commands/lifecycle.py +0 -0
  92. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/commands/list_cmd.py +0 -0
  93. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/commands/lock.py +0 -0
  94. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/commands/marketplace/__init__.py +0 -0
  95. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/commands/marketplace/audit.py +0 -0
  96. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/commands/marketplace/check.py +0 -0
  97. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/commands/marketplace/doctor.py +0 -0
  98. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/commands/marketplace/init.py +0 -0
  99. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/commands/marketplace/migrate.py +0 -0
  100. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/commands/marketplace/outdated.py +0 -0
  101. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/commands/marketplace/plugin/__init__.py +0 -0
  102. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/commands/marketplace/plugin/add.py +0 -0
  103. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/commands/marketplace/plugin/remove.py +0 -0
  104. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/commands/marketplace/plugin/set.py +0 -0
  105. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/commands/marketplace/validate.py +0 -0
  106. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/commands/mcp.py +0 -0
  107. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/commands/outdated.py +0 -0
  108. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/commands/pack.py +0 -0
  109. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/commands/plugin/__init__.py +0 -0
  110. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/commands/plugin/init.py +0 -0
  111. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/commands/policy.py +0 -0
  112. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/commands/publish.py +0 -0
  113. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/commands/run.py +0 -0
  114. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/commands/runtime.py +0 -0
  115. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/commands/targets.py +0 -0
  116. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/commands/uninstall/__init__.py +0 -0
  117. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/commands/uninstall/lockfile_state.py +0 -0
  118. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/commands/update.py +0 -0
  119. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/commands/view.py +0 -0
  120. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/compilation/__init__.py +0 -0
  121. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/compilation/agents_compiler.py +0 -0
  122. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/compilation/build_id.py +0 -0
  123. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/compilation/claude_formatter.py +0 -0
  124. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/compilation/constants.py +0 -0
  125. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/compilation/constitution.py +0 -0
  126. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/compilation/constitution_block.py +0 -0
  127. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/compilation/distributed_compiler.py +0 -0
  128. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/compilation/footer.py +0 -0
  129. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/compilation/gemini_formatter.py +0 -0
  130. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/compilation/injector.py +0 -0
  131. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/compilation/inventory.py +0 -0
  132. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/compilation/link_resolver.py +0 -0
  133. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/compilation/managed_section.py +0 -0
  134. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/compilation/output_writer.py +0 -0
  135. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/compilation/root_context_protection.py +0 -0
  136. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/compilation/template_builder.py +0 -0
  137. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/compilation/user_root_context.py +0 -0
  138. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/config.py +0 -0
  139. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/constants.py +0 -0
  140. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/copilot_plugins/__init__.py +0 -0
  141. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/copilot_plugins/capability.py +0 -0
  142. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/copilot_plugins/catalog.py +0 -0
  143. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/copilot_plugins/constants.py +0 -0
  144. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/copilot_plugins/registrar.py +0 -0
  145. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/copilot_plugins/settings.py +0 -0
  146. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/core/__init__.py +0 -0
  147. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/core/_child_tls/__init__.py +0 -0
  148. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/core/_child_tls/_apm_tls.pth +0 -0
  149. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/core/_child_tls/_apm_tls_bootstrap.py +0 -0
  150. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/core/apm_yml.py +0 -0
  151. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/core/auth.py +0 -0
  152. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/core/azure_cli.py +0 -0
  153. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/core/build_orchestrator.py +0 -0
  154. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/core/command_logger.py +0 -0
  155. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/core/conflict_detector.py +0 -0
  156. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/core/deployment_ledger.py +0 -0
  157. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/core/deployment_state.py +0 -0
  158. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/core/docker_args.py +0 -0
  159. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/core/errors.py +0 -0
  160. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/core/experimental.py +0 -0
  161. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/core/host_providers.py +0 -0
  162. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/core/install_audit.py +0 -0
  163. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/core/lifecycle_scripts.py +0 -0
  164. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/core/null_logger.py +0 -0
  165. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/core/operations.py +0 -0
  166. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/core/output_mode.py +0 -0
  167. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/core/plugin_manifest.py +0 -0
  168. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/core/project_name.py +0 -0
  169. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/core/safe_installer.py +0 -0
  170. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/core/scope.py +0 -0
  171. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/core/script_executors.py +0 -0
  172. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/core/script_runner.py +0 -0
  173. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/core/script_trust.py +0 -0
  174. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/core/target_catalog.py +0 -0
  175. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/core/target_detection.py +0 -0
  176. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/core/tls_trust.py +0 -0
  177. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/core/token_manager.py +0 -0
  178. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/deps/__init__.py +0 -0
  179. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/deps/_shared.py +0 -0
  180. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/deps/aggregator.py +0 -0
  181. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/deps/apm_resolver.py +0 -0
  182. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/deps/artifactory_entry.py +0 -0
  183. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/deps/artifactory_orchestrator.py +0 -0
  184. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/deps/bare_cache.py +0 -0
  185. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/deps/clone_engine.py +0 -0
  186. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/deps/dependency_graph.py +0 -0
  187. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/deps/download_strategies.py +0 -0
  188. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/deps/git_auth_env.py +0 -0
  189. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/deps/git_file_transport.py +0 -0
  190. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/deps/git_reference_resolver.py +0 -0
  191. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/deps/git_remote_ops.py +0 -0
  192. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/deps/git_semver_resolver.py +0 -0
  193. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/deps/github_downloader.py +0 -0
  194. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/deps/github_downloader_validation.py +0 -0
  195. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/deps/host_backends.py +0 -0
  196. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/deps/installed_package.py +0 -0
  197. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/deps/lockfile.py +0 -0
  198. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/deps/outdated_ref_cache.py +0 -0
  199. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/deps/outdated_row.py +0 -0
  200. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/deps/package_validator.py +0 -0
  201. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/deps/path_anchoring.py +0 -0
  202. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/deps/plugin_parser.py +0 -0
  203. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/deps/reachability.py +0 -0
  204. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/deps/registry/__init__.py +0 -0
  205. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/deps/registry/auth.py +0 -0
  206. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/deps/registry/client.py +0 -0
  207. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/deps/registry/config_loader.py +0 -0
  208. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/deps/registry/extractor.py +0 -0
  209. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/deps/registry/feature_gate.py +0 -0
  210. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/deps/registry/outdated.py +0 -0
  211. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/deps/registry/resolver.py +0 -0
  212. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/deps/registry/semver.py +0 -0
  213. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/deps/registry_proxy.py +0 -0
  214. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/deps/revision_pins.py +0 -0
  215. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/deps/shared_clone_cache.py +0 -0
  216. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/deps/tiered_ref_resolver.py +0 -0
  217. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/deps/transport_selection.py +0 -0
  218. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/deps/verifier.py +0 -0
  219. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/deps/why_walker.py +0 -0
  220. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/drift.py +0 -0
  221. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/export/__init__.py +0 -0
  222. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/export/authoring.py +0 -0
  223. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/export/declared_license.py +0 -0
  224. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/export/formats.py +0 -0
  225. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/export/purl.py +0 -0
  226. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/export/sbom.py +0 -0
  227. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/export/spdx.py +0 -0
  228. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/export/spdx_data.py +0 -0
  229. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/factory.py +0 -0
  230. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/hook_contract.py +0 -0
  231. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/install/__init__.py +0 -0
  232. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/install/argv.py +0 -0
  233. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/install/artifactory_resolver.py +0 -0
  234. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/install/audit_replay.py +0 -0
  235. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/install/audit_target_roots.py +0 -0
  236. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/install/cache_pin.py +0 -0
  237. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/install/context.py +0 -0
  238. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/install/deployable_source_plan.py +0 -0
  239. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/install/deployed_paths.py +0 -0
  240. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/install/drift.py +0 -0
  241. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/install/drift_render.py +0 -0
  242. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/install/dry_run_plan.py +0 -0
  243. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/install/errors.py +0 -0
  244. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/install/exec_gate.py +0 -0
  245. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/install/finalization.py +0 -0
  246. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/install/gitlab_resolver.py +0 -0
  247. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/install/heals/__init__.py +0 -0
  248. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/install/heals/base.py +0 -0
  249. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/install/heals/branch_ref_drift.py +0 -0
  250. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/install/heals/buggy_lockfile_recovery.py +0 -0
  251. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/install/helpers/__init__.py +0 -0
  252. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/install/helpers/no_work.py +0 -0
  253. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/install/helpers/ref_reuse.py +0 -0
  254. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/install/helpers/ref_seed.py +0 -0
  255. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/install/helpers/security_scan.py +0 -0
  256. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/install/insecure_policy.py +0 -0
  257. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/install/integrity.py +0 -0
  258. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/install/legacy_plugin_compat.py +0 -0
  259. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/install/local_bundle_handler.py +0 -0
  260. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/install/local_bundle_paths.py +0 -0
  261. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/install/locking.py +0 -0
  262. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/install/lsp/__init__.py +0 -0
  263. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/install/lsp/integration.py +0 -0
  264. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/install/manifest_helpers.py +0 -0
  265. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/install/manifest_reconcile.py +0 -0
  266. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/install/mcp/__init__.py +0 -0
  267. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/install/mcp/args.py +0 -0
  268. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/install/mcp/command.py +0 -0
  269. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/install/mcp/conflicts.py +0 -0
  270. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/install/mcp/entry.py +0 -0
  271. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/install/mcp/integration.py +0 -0
  272. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/install/mcp/ownership.py +0 -0
  273. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/install/mcp/registry.py +0 -0
  274. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/install/mcp/warnings.py +0 -0
  275. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/install/mcp/writer.py +0 -0
  276. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/install/native_plugin_admission.py +0 -0
  277. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/install/outcome.py +0 -0
  278. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/install/package_resolution.py +0 -0
  279. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/install/package_selection.py +0 -0
  280. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/install/phases/__init__.py +0 -0
  281. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/install/phases/_redownload.py +0 -0
  282. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/install/phases/_skip_logic.py +0 -0
  283. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/install/phases/audit.py +0 -0
  284. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/install/phases/cleanup.py +0 -0
  285. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/install/phases/copilot_plugins.py +0 -0
  286. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/install/phases/download.py +0 -0
  287. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/install/phases/finalize.py +0 -0
  288. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/install/phases/heal.py +0 -0
  289. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/install/phases/integrate.py +0 -0
  290. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/install/phases/local_content.py +0 -0
  291. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/install/phases/lockfile.py +0 -0
  292. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/install/phases/policy_gate.py +0 -0
  293. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/install/phases/policy_target_check.py +0 -0
  294. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/install/phases/post_deps_local.py +0 -0
  295. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/install/phases/resolve.py +0 -0
  296. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/install/phases/targets.py +0 -0
  297. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/install/pipeline.py +0 -0
  298. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/install/plan.py +0 -0
  299. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/install/presentation/__init__.py +0 -0
  300. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/install/presentation/dry_run.py +0 -0
  301. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/install/primitive_classification.py +0 -0
  302. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/install/registry_wiring.py +0 -0
  303. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/install/request.py +0 -0
  304. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/install/resolution_staging.py +0 -0
  305. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/install/root_redirect.py +0 -0
  306. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/install/service.py +0 -0
  307. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/install/service_integration.py +0 -0
  308. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/install/services.py +0 -0
  309. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/install/skill_path_migration.py +0 -0
  310. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/install/source_helpers.py +0 -0
  311. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/install/sources.py +0 -0
  312. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/install/summary.py +0 -0
  313. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/install/target_filter.py +0 -0
  314. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/install/target_hints.py +0 -0
  315. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/install/target_warnings.py +0 -0
  316. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/install/template.py +0 -0
  317. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/install/transaction.py +0 -0
  318. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/install/validation.py +0 -0
  319. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/integration/__init__.py +0 -0
  320. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/integration/_hook_dropped_targets.py +0 -0
  321. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/integration/_shared.py +0 -0
  322. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/integration/agent_integrator.py +0 -0
  323. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/integration/base_integrator.py +0 -0
  324. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/integration/canvas_integrator.py +0 -0
  325. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/integration/cleanup.py +0 -0
  326. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/integration/command_integrator.py +0 -0
  327. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/integration/copilot_app_db.py +0 -0
  328. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/integration/copilot_app_project.py +0 -0
  329. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/integration/copilot_app_workflow_integrator.py +0 -0
  330. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/integration/copilot_app_ws.py +0 -0
  331. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/integration/copilot_cowork_paths.py +0 -0
  332. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/integration/coverage.py +0 -0
  333. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/integration/dispatch.py +0 -0
  334. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/integration/hook_bundle.py +0 -0
  335. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/integration/hook_command_paths.py +0 -0
  336. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/integration/hook_command_warnings.py +0 -0
  337. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/integration/hook_file_routing.py +0 -0
  338. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/integration/hook_integrator.py +0 -0
  339. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/integration/hook_ir.py +0 -0
  340. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/integration/hook_native_formats.py +0 -0
  341. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/integration/hook_ownership.py +0 -0
  342. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/integration/hook_reintegration.py +0 -0
  343. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/integration/hook_source_selection.py +0 -0
  344. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/integration/instruction_integrator.py +0 -0
  345. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/integration/kiro_hook_integrator.py +0 -0
  346. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/integration/lsp_integrator.py +0 -0
  347. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/integration/mcp_config_view.py +0 -0
  348. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/integration/mcp_integrator.py +0 -0
  349. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/integration/mcp_integrator_install.py +0 -0
  350. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/integration/opencode_frontmatter.py +0 -0
  351. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/integration/prompt_integrator.py +0 -0
  352. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/integration/skill_integrator.py +0 -0
  353. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/integration/skill_package_routing.py +0 -0
  354. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/integration/skill_support.py +0 -0
  355. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/integration/skill_transformer.py +0 -0
  356. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/integration/targets.py +0 -0
  357. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/integration/utils.py +0 -0
  358. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/marketplace/__init__.py +0 -0
  359. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/marketplace/_git_utils.py +0 -0
  360. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/marketplace/_io.py +0 -0
  361. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/marketplace/_shared.py +0 -0
  362. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/marketplace/audit.py +0 -0
  363. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/marketplace/auth_helpers.py +0 -0
  364. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/marketplace/builder.py +0 -0
  365. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/marketplace/client.py +0 -0
  366. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/marketplace/diagnostics.py +0 -0
  367. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/marketplace/drift_check.py +0 -0
  368. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/marketplace/errors.py +0 -0
  369. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/marketplace/git_stderr.py +0 -0
  370. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/marketplace/init_template.py +0 -0
  371. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/marketplace/migration.py +0 -0
  372. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/marketplace/models.py +0 -0
  373. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/marketplace/output_mappers.py +0 -0
  374. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/marketplace/output_profiles.py +0 -0
  375. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/marketplace/ref_resolver.py +0 -0
  376. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/marketplace/registry.py +0 -0
  377. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/marketplace/resolver.py +0 -0
  378. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/marketplace/semver.py +0 -0
  379. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/marketplace/shadow_detector.py +0 -0
  380. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/marketplace/source_identity.py +0 -0
  381. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/marketplace/tag_pattern.py +0 -0
  382. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/marketplace/validator.py +0 -0
  383. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/marketplace/version_check.py +0 -0
  384. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/marketplace/version_pins.py +0 -0
  385. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/marketplace/version_resolver.py +0 -0
  386. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/marketplace/yml_editor.py +0 -0
  387. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/marketplace/yml_schema.py +0 -0
  388. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/models/__init__.py +0 -0
  389. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/models/apm_package.py +0 -0
  390. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/models/dependency/__init__.py +0 -0
  391. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/models/dependency/host_virtual.py +0 -0
  392. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/models/dependency/identity.py +0 -0
  393. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/models/dependency/lsp.py +0 -0
  394. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/models/dependency/materialization.py +0 -0
  395. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/models/dependency/mcp.py +0 -0
  396. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/models/dependency/object_fields.py +0 -0
  397. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/models/dependency/provider_coordinates.py +0 -0
  398. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/models/dependency/reference.py +0 -0
  399. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/models/dependency/registry_entry.py +0 -0
  400. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/models/dependency/selection.py +0 -0
  401. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/models/dependency/subsets.py +0 -0
  402. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/models/dependency/types.py +0 -0
  403. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/models/format_detection.py +0 -0
  404. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/models/manifest_contract.py +0 -0
  405. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/models/plugin.py +0 -0
  406. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/models/results.py +0 -0
  407. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/models/validation.py +0 -0
  408. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/output/__init__.py +0 -0
  409. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/output/formatters.py +0 -0
  410. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/output/models.py +0 -0
  411. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/output/script_formatters.py +0 -0
  412. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/policy/__init__.py +0 -0
  413. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/policy/_constraint_pinning.py +0 -0
  414. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/policy/_gitlab.py +0 -0
  415. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/policy/_help_text.py +0 -0
  416. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/policy/_shared.py +0 -0
  417. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/policy/ci_checks.py +0 -0
  418. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/policy/inheritance.py +0 -0
  419. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/policy/install_preflight.py +0 -0
  420. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/policy/matcher.py +0 -0
  421. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/policy/models.py +0 -0
  422. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/policy/outcome_routing.py +0 -0
  423. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/policy/parser.py +0 -0
  424. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/policy/schema.py +0 -0
  425. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/primitives/__init__.py +0 -0
  426. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/primitives/discovery.py +0 -0
  427. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/primitives/models.py +0 -0
  428. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/primitives/parser.py +0 -0
  429. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/registry/__init__.py +0 -0
  430. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/registry/client.py +0 -0
  431. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/registry/integration.py +0 -0
  432. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/registry/operations.py +0 -0
  433. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/runtime/__init__.py +0 -0
  434. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/runtime/base.py +0 -0
  435. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/runtime/codex_runtime.py +0 -0
  436. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/runtime/copilot_runtime.py +0 -0
  437. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/runtime/factory.py +0 -0
  438. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/runtime/llm_runtime.py +0 -0
  439. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/runtime/manager.py +0 -0
  440. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/runtime/registry.py +0 -0
  441. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/runtime/utils.py +0 -0
  442. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/security/__init__.py +0 -0
  443. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/security/audit_report.py +0 -0
  444. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/security/content_scanner.py +0 -0
  445. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/security/executables.py +0 -0
  446. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/security/external/__init__.py +0 -0
  447. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/security/external/base.py +0 -0
  448. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/security/external/gate.py +0 -0
  449. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/security/external/generic_sarif.py +0 -0
  450. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/security/external/options.py +0 -0
  451. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/security/external/registry.py +0 -0
  452. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/security/external/runner.py +0 -0
  453. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/security/external/sarif_ingest.py +0 -0
  454. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/security/external/skillspector.py +0 -0
  455. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/security/file_scanner.py +0 -0
  456. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/security/gate.py +0 -0
  457. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/update_policy.py +0 -0
  458. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/utils/__init__.py +0 -0
  459. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/utils/archive.py +0 -0
  460. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/utils/atomic_io.py +0 -0
  461. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/utils/console.py +0 -0
  462. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/utils/content_hash.py +0 -0
  463. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/utils/diagnostics.py +0 -0
  464. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/utils/exclude.py +0 -0
  465. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/utils/file_ops.py +0 -0
  466. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/utils/git_env.py +0 -0
  467. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/utils/git_sparse.py +0 -0
  468. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/utils/github_host.py +0 -0
  469. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/utils/guards.py +0 -0
  470. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/utils/helpers.py +0 -0
  471. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/utils/install_tui.py +0 -0
  472. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/utils/net.py +0 -0
  473. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/utils/normalization.py +0 -0
  474. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/utils/path_security.py +0 -0
  475. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/utils/paths.py +0 -0
  476. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/utils/patterns.py +0 -0
  477. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/utils/perf_stats.py +0 -0
  478. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/utils/reflink.py +0 -0
  479. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/utils/short_sha.py +0 -0
  480. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/utils/staging_guard.py +0 -0
  481. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/utils/subprocess_env.py +0 -0
  482. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/utils/yaml_io.py +0 -0
  483. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/version.py +0 -0
  484. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/workflow/__init__.py +0 -0
  485. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/workflow/discovery.py +0 -0
  486. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/workflow/parser.py +0 -0
  487. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli/workflow/runner.py +0 -0
  488. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli.egg-info/dependency_links.txt +0 -0
  489. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli.egg-info/entry_points.txt +0 -0
  490. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli.egg-info/requires.txt +0 -0
  491. {apm_cli-0.29.1 → apm_cli-0.30.0}/src/apm_cli.egg-info/top_level.txt +0 -0
  492. {apm_cli-0.29.1 → apm_cli-0.30.0}/tests/test_apm_package_models.py +0 -0
  493. {apm_cli-0.29.1 → apm_cli-0.30.0}/tests/test_apm_resolver.py +0 -0
  494. {apm_cli-0.29.1 → apm_cli-0.30.0}/tests/test_codex_docker_args_fix.py +0 -0
  495. {apm_cli-0.29.1 → apm_cli-0.30.0}/tests/test_codex_empty_string_and_defaults.py +0 -0
  496. {apm_cli-0.29.1 → apm_cli-0.30.0}/tests/test_collision_integration.py +0 -0
  497. {apm_cli-0.29.1 → apm_cli-0.30.0}/tests/test_console.py +0 -0
  498. {apm_cli-0.29.1 → apm_cli-0.30.0}/tests/test_distributed_compilation.py +0 -0
  499. {apm_cli-0.29.1 → apm_cli-0.30.0}/tests/test_empty_string_and_defaults.py +0 -0
  500. {apm_cli-0.29.1 → apm_cli-0.30.0}/tests/test_enhanced_discovery.py +0 -0
  501. {apm_cli-0.29.1 → apm_cli-0.30.0}/tests/test_github_downloader.py +0 -0
  502. {apm_cli-0.29.1 → apm_cli-0.30.0}/tests/test_github_downloader_token_precedence.py +0 -0
  503. {apm_cli-0.29.1 → apm_cli-0.30.0}/tests/test_gitlab_git_transport.py +0 -0
  504. {apm_cli-0.29.1 → apm_cli-0.30.0}/tests/test_lockfile.py +0 -0
  505. {apm_cli-0.29.1 → apm_cli-0.30.0}/tests/test_runnable_prompts.py +0 -0
  506. {apm_cli-0.29.1 → apm_cli-0.30.0}/tests/test_runtime_manager_token_precedence.py +0 -0
  507. {apm_cli-0.29.1 → apm_cli-0.30.0}/tests/test_token_manager.py +0 -0
  508. {apm_cli-0.29.1 → apm_cli-0.30.0}/tests/test_virtual_package_multi_install.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: apm-cli
3
- Version: 0.29.1
3
+ Version: 0.30.0
4
4
  Summary: MCP configuration tool
5
5
  Author-email: Daniel Meppiel <user@example.com>
6
6
  License: MIT License
@@ -170,7 +170,16 @@ apm-policy.yml governs what gets installed; your agent harness governs what runs
170
170
 
171
171
  ## Get Started
172
172
 
173
- #### Linux / macOS
173
+ #### macOS with Homebrew
174
+
175
+ ```bash
176
+ brew install apm
177
+ ```
178
+
179
+ No custom tap is required. Homebrew manages installation and updates:
180
+ use `brew upgrade apm`, not `apm self-update`.
181
+
182
+ #### Linux / macOS without Homebrew
174
183
 
175
184
  ```bash
176
185
  curl -sSL https://aka.ms/apm-unix | sh
@@ -182,17 +191,17 @@ curl -sSL https://aka.ms/apm-unix | sh
182
191
  irm https://aka.ms/apm-windows | iex
183
192
  ```
184
193
 
185
- Native release binaries are published for macOS, Linux, and Windows x86_64. `apm self-update` reuses the matching platform installer.
194
+ Native release binaries are published for macOS, Linux, and Windows x86_64.
195
+ For standalone installations, `apm self-update` reuses the matching platform installer.
196
+ You do not need Homebrew to use APM.
186
197
 
187
198
  <details>
188
- <summary>Other install methods</summary>
199
+ <summary>Other install methods: pip and Scoop</summary>
189
200
 
190
201
  #### Linux / macOS
191
202
 
192
203
  ```bash
193
- # Homebrew
194
- brew install microsoft/apm/apm
195
- # pip
204
+ # pip (Python 3.10+)
196
205
  pip install apm-cli
197
206
  ```
198
207
 
@@ -208,6 +217,9 @@ pip install apm-cli
208
217
 
209
218
  </details>
210
219
 
220
+ Already using the Microsoft Homebrew tap? See the
221
+ [migration guide](https://microsoft.github.io/apm/getting-started/installation/#migrate-from-the-microsoft-tap).
222
+
211
223
  Then start adding packages:
212
224
 
213
225
  ```bash
@@ -98,7 +98,16 @@ apm-policy.yml governs what gets installed; your agent harness governs what runs
98
98
 
99
99
  ## Get Started
100
100
 
101
- #### Linux / macOS
101
+ #### macOS with Homebrew
102
+
103
+ ```bash
104
+ brew install apm
105
+ ```
106
+
107
+ No custom tap is required. Homebrew manages installation and updates:
108
+ use `brew upgrade apm`, not `apm self-update`.
109
+
110
+ #### Linux / macOS without Homebrew
102
111
 
103
112
  ```bash
104
113
  curl -sSL https://aka.ms/apm-unix | sh
@@ -110,17 +119,17 @@ curl -sSL https://aka.ms/apm-unix | sh
110
119
  irm https://aka.ms/apm-windows | iex
111
120
  ```
112
121
 
113
- Native release binaries are published for macOS, Linux, and Windows x86_64. `apm self-update` reuses the matching platform installer.
122
+ Native release binaries are published for macOS, Linux, and Windows x86_64.
123
+ For standalone installations, `apm self-update` reuses the matching platform installer.
124
+ You do not need Homebrew to use APM.
114
125
 
115
126
  <details>
116
- <summary>Other install methods</summary>
127
+ <summary>Other install methods: pip and Scoop</summary>
117
128
 
118
129
  #### Linux / macOS
119
130
 
120
131
  ```bash
121
- # Homebrew
122
- brew install microsoft/apm/apm
123
- # pip
132
+ # pip (Python 3.10+)
124
133
  pip install apm-cli
125
134
  ```
126
135
 
@@ -136,6 +145,9 @@ pip install apm-cli
136
145
 
137
146
  </details>
138
147
 
148
+ Already using the Microsoft Homebrew tap? See the
149
+ [migration guide](https://microsoft.github.io/apm/getting-started/installation/#migrate-from-the-microsoft-tap).
150
+
139
151
  Then start adding packages:
140
152
 
141
153
  ```bash
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "apm-cli"
7
- version = "0.29.1"
7
+ version = "0.30.0"
8
8
  description = "MCP configuration tool"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.10"
@@ -219,4 +219,5 @@ markers = [
219
219
  "req: binds a test to one or more OpenAPM req-XXX ids (spec-conformance suite)",
220
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
221
  "lifecycle_merge_group: unique lifecycle contracts retained in the full merge-group integration suite",
222
+ "xdist_group(name): assigns HOME-mutating tests to one pytest-xdist loadgroup for process-level serialization",
222
223
  ]
@@ -0,0 +1,51 @@
1
+ """Verified, best-effort removal outcomes for explicit cache cleaning."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import os
6
+ from collections.abc import Iterable
7
+ from pathlib import Path
8
+
9
+ from ..utils import file_ops
10
+
11
+
12
+ def clean_cache_buckets(buckets: Iterable[Path]) -> list[str]:
13
+ """Remove bucket children without following links; return all failure details.
14
+
15
+ Successful removals are not rolled back. The residual check is essential:
16
+ the read-only recovery callback in robust_rmtree can swallow OS errors.
17
+ """
18
+ failures: list[str] = []
19
+ for bucket in buckets:
20
+ try:
21
+ if bucket.is_symlink():
22
+ failures.append(f"{bucket}: refusing to traverse a symlinked cache bucket")
23
+ continue
24
+ with os.scandir(bucket) as entries:
25
+ for entry in entries:
26
+ path = Path(entry.path)
27
+ try:
28
+ if entry.is_dir(follow_symlinks=False):
29
+ file_ops.robust_rmtree(path)
30
+ else:
31
+ path.unlink()
32
+ except FileNotFoundError:
33
+ pass
34
+ except OSError as exc:
35
+ failures.append(f"{path}: {exc}")
36
+ continue
37
+ try:
38
+ # lstat distinguishes a removed entry from an unreadable
39
+ # one and also detects dangling symlinks.
40
+ path.lstat()
41
+ except FileNotFoundError:
42
+ continue
43
+ except OSError as exc:
44
+ failures.append(f"{path}: {exc}")
45
+ else:
46
+ failures.append(f"{path}: entry remains after deletion")
47
+ except FileNotFoundError:
48
+ continue
49
+ except OSError as exc:
50
+ failures.append(f"{bucket}: {exc}")
51
+ return failures
@@ -16,6 +16,7 @@ Resolution flow:
16
16
  On every cache HIT:
17
17
  - Run integrity check (verify HEAD == expected SHA)
18
18
  - Mismatch -> evict shard, fall through to fresh fetch, log warning
19
+ - Refresh the SHA directory's access timestamp after successful validation
19
20
 
20
21
  Concurrency:
21
22
  - Per-shard file locks (via filelock) for atomic operations
@@ -24,7 +25,6 @@ Concurrency:
24
25
 
25
26
  from __future__ import annotations
26
27
 
27
- import contextlib
28
28
  import hashlib
29
29
  import json
30
30
  import logging
@@ -50,6 +50,15 @@ _FALLBACK_REFSPECS = (
50
50
  )
51
51
 
52
52
 
53
+ class CachePruneError(OSError):
54
+ """Incomplete prune with completed-removal count and per-entry failures."""
55
+
56
+ def __init__(self, pruned: int, failures: list[tuple[Path, OSError]]) -> None:
57
+ self.pruned = pruned
58
+ self.failures = tuple(failures)
59
+ super().__init__(f"Pruned {pruned} SHA group(s); {len(failures)} failed.")
60
+
61
+
53
62
  def _safe_git_args() -> list[str]:
54
63
  """Return hardening ``-c`` args prepended to every git subprocess.
55
64
 
@@ -195,11 +204,8 @@ class GitCache:
195
204
  if verify_checkout_sha(checkout_dir, sha):
196
205
  _log.debug("Cache HIT: %s @ %s [%s]", _sanitize_url(url), sha[:12], variant)
197
206
  with shard_lock(checkout_dir):
198
- return self._finalize_sparse_checkout(
199
- url,
200
- checkout_dir,
201
- sparse_paths,
202
- env=env,
207
+ return self._record_checkout_access(
208
+ self._finalize_sparse_checkout(url, checkout_dir, sparse_paths, env=env)
203
209
  )
204
210
  else:
205
211
  # Integrity failure -- evict
@@ -226,6 +232,21 @@ class GitCache:
226
232
  promisor_url=url if use_partial else None,
227
233
  )
228
234
 
235
+ def _record_checkout_access(self, checkout_dir: Path) -> Path:
236
+ """Record successful reuse of a finalized checkout under its shard lock."""
237
+ # Pruning ages the shared SHA root, not individual checkout variants.
238
+ try:
239
+ os.utime(checkout_dir.parent, None)
240
+ except PermissionError as exc:
241
+ _log.warning(
242
+ "[!] Cannot update Git cache recency for %s: %s. "
243
+ "Continuing with validated checkout; cache prune may evict it. "
244
+ "Check cache permissions or set APM_CACHE_DIR to a writable directory.",
245
+ checkout_dir.parent,
246
+ exc,
247
+ )
248
+ return checkout_dir
249
+
229
250
  def _finalize_sparse_checkout(
230
251
  self,
231
252
  url: str,
@@ -600,11 +621,8 @@ class GitCache:
600
621
  sha[:12],
601
622
  variant,
602
623
  )
603
- return self._finalize_sparse_checkout(
604
- url,
605
- final_dir,
606
- sparse_paths,
607
- env=env,
624
+ return self._record_checkout_access(
625
+ self._finalize_sparse_checkout(url, final_dir, sparse_paths, env=env)
608
626
  )
609
627
 
610
628
  staged = stage_path(final_dir)
@@ -873,33 +891,37 @@ class GitCache:
873
891
  "total_size_bytes": total_size,
874
892
  }
875
893
 
876
- def clean_all(self) -> None:
877
- """Remove ALL cache content (db + checkouts). Used by ``apm cache clean``."""
878
- from ..utils.file_ops import robust_rmtree
894
+ def clean_all(self) -> list[str]:
895
+ """Remove db and checkouts, returning details of every incomplete removal."""
896
+ from .cleanup import clean_cache_buckets
879
897
 
880
- for bucket in (self._db_root, self._checkouts_root):
881
- if bucket.is_dir():
882
- for entry in os.scandir(str(bucket)):
883
- if entry.is_dir(follow_symlinks=False):
884
- robust_rmtree(Path(entry.path), ignore_errors=True)
885
- elif entry.is_file(follow_symlinks=False):
886
- with contextlib.suppress(OSError):
887
- os.unlink(entry.path)
898
+ return clean_cache_buckets((self._db_root, self._checkouts_root))
888
899
 
889
900
  def prune(self, *, max_age_days: int = 30) -> int:
890
901
  """Remove checkout entries older than *max_age_days*.
891
902
 
892
- Uses mtime of the checkout directory as the access indicator.
903
+ Uses mtime of the shared SHA directory as the access indicator.
904
+ Successfully reusing any checkout variant refreshes that timestamp.
893
905
 
894
906
  Returns:
895
- Number of entries pruned.
907
+ Number of SHA groups successfully removed.
908
+
909
+ Raises:
910
+ ValueError: If max_age_days is negative.
911
+ CachePruneError: Some entries could not be inspected or removed.
912
+ Other stale entries are still attempted. Completed removals
913
+ and partially deleted entries are not rolled back.
896
914
  """
897
915
  import time
898
916
 
899
917
  from ..utils.file_ops import robust_rmtree
900
918
 
919
+ if max_age_days < 0:
920
+ raise ValueError("max_age_days must be nonnegative; use 0 or a positive number of days")
921
+
901
922
  cutoff = time.time() - (max_age_days * 86400)
902
923
  pruned = 0
924
+ failures: list[tuple[Path, OSError]] = []
903
925
 
904
926
  if not self._checkouts_root.is_dir():
905
927
  return 0
@@ -913,11 +935,13 @@ class GitCache:
913
935
  try:
914
936
  stat = sha_entry.stat(follow_symlinks=False)
915
937
  if stat.st_mtime < cutoff:
916
- robust_rmtree(Path(sha_entry.path), ignore_errors=True)
938
+ robust_rmtree(Path(sha_entry.path))
917
939
  pruned += 1
918
- except OSError:
919
- continue
940
+ except OSError as exc:
941
+ failures.append((Path(sha_entry.path), exc))
920
942
 
943
+ if failures:
944
+ raise CachePruneError(pruned, failures)
921
945
  return pruned
922
946
 
923
947
 
@@ -121,6 +121,13 @@ class HttpCache:
121
121
  robust_rmtree(entry_path, ignore_errors=True)
122
122
  return None
123
123
 
124
+ # Recency is independent of TTL. A concurrent eviction or read-only
125
+ # cache must not discard the response we have already verified.
126
+ try:
127
+ os.utime(str(entry_path), None)
128
+ except OSError as exc:
129
+ _log.debug("Failed to update HTTP cache recency for %s: %s", url, exc)
130
+
124
131
  return CacheEntry(
125
132
  body=body,
126
133
  etag=meta.get("etag"),
@@ -270,14 +277,12 @@ class HttpCache:
270
277
  except (json.JSONDecodeError, OSError) as exc:
271
278
  _log.debug("Failed to refresh HTTP cache entry for %s: %s", url, exc)
272
279
 
273
- def clean_all(self) -> None:
274
- """Remove all HTTP cache entries."""
275
- from ..utils.file_ops import robust_rmtree
280
+ def clean_all(self) -> list[str]:
281
+ """Remove HTTP entries, returning details of every incomplete removal."""
282
+ from .cleanup import clean_cache_buckets
276
283
 
277
- if self._cache_dir.is_dir():
278
- for entry in os.scandir(str(self._cache_dir)):
279
- if entry.is_dir(follow_symlinks=False):
280
- robust_rmtree(Path(entry.path), ignore_errors=True)
284
+ self._tracked_size = None
285
+ return clean_cache_buckets((self._cache_dir,))
281
286
 
282
287
  def get_stats(self) -> dict[str, int]:
283
288
  """Return cache statistics.
@@ -60,43 +60,51 @@ def info() -> None:
60
60
  def clean(force: bool, yes: bool) -> None:
61
61
  """Remove all cache content (git repos, checkouts, HTTP responses)."""
62
62
  from ..cache.paths import get_cache_root
63
- from ..utils.console import _rich_info, _rich_success
63
+ from ..core.command_logger import CommandLogger
64
64
 
65
+ logger = CommandLogger("cache clean")
65
66
  try:
66
67
  root = get_cache_root()
67
68
  except (ValueError, OSError) as exc:
68
- from ..utils.console import _rich_error
69
-
70
- _rich_error(f"Cannot resolve cache root: {exc}", symbol="error")
69
+ logger.error(f"Cannot resolve cache root: {exc}")
71
70
  raise SystemExit(1) from exc
72
71
 
73
72
  if not force and not yes:
74
73
  confirmed = click.confirm(f"Remove all cache content in {root}?", default=False)
75
74
  if not confirmed:
76
- _rich_info("Aborted.", symbol="info")
75
+ logger.progress("Aborted.")
77
76
  return
78
77
 
79
- _rich_info("Cleaning cache...", symbol="gear")
78
+ logger.start("Cleaning cache...", symbol="gear")
80
79
 
81
80
  from ..cache.git_cache import GitCache
82
81
  from ..cache.http_cache import HttpCache
83
82
 
84
- git_cache = GitCache(root)
85
- git_cache.clean_all()
86
-
87
- http_cache = HttpCache(root)
88
- http_cache.clean_all()
89
-
90
- _rich_success("Cache cleaned.", symbol="check")
91
-
92
-
93
- @cache.command(help="Remove cache entries older than N days")
83
+ failures: list[str] = []
84
+ for cache_type in (GitCache, HttpCache):
85
+ try:
86
+ failures.extend(cache_type(root).clean_all())
87
+ except OSError as exc:
88
+ failures.append(f"{cache_type.__name__}: {exc}")
89
+ if failures:
90
+ logger.error("Cache cleanup incomplete; some cached content could not be removed.")
91
+ for failure in failures:
92
+ logger.error(failure)
93
+ logger.error(
94
+ "Close processes using the cache, check permissions, then retry apm cache clean."
95
+ )
96
+ raise SystemExit(1)
97
+
98
+ logger.success("Cache cleaned.", symbol="check")
99
+
100
+
101
+ @cache.command(help="Remove Git checkout SHA groups older than N days")
94
102
  @click.option(
95
103
  "--days",
96
- type=int,
104
+ type=click.IntRange(min=0),
97
105
  default=30,
98
106
  show_default=True,
99
- help="Remove entries not accessed within this many days",
107
+ help="Remove SHA groups not accessed within this many days",
100
108
  )
101
109
  def prune(days: int) -> None:
102
110
  """Remove stale cache entries based on last access time.
@@ -105,24 +113,31 @@ def prune(days: int) -> None:
105
113
  referenced by project lockfiles are NOT exempt -- freshness is
106
114
  determined solely by filesystem timestamps.
107
115
  """
108
- from ..cache.git_cache import GitCache
116
+ from ..cache.git_cache import CachePruneError, GitCache
109
117
  from ..cache.paths import get_cache_root
110
- from ..utils.console import _rich_info, _rich_success
118
+ from ..core.command_logger import CommandLogger
119
+
120
+ logger = CommandLogger("cache prune")
111
121
 
112
122
  try:
113
123
  root = get_cache_root()
114
124
  except (ValueError, OSError) as exc:
115
- from ..utils.console import _rich_error
116
-
117
- _rich_error(f"Cannot resolve cache root: {exc}", symbol="error")
125
+ logger.error(f"Cannot resolve cache root: {exc}")
118
126
  raise SystemExit(1) from exc
119
127
 
120
- _rich_info(f"Pruning entries older than {days} days...", symbol="gear")
128
+ logger.start(f"Pruning SHA groups older than {days} days...", symbol="gear")
121
129
 
122
130
  git_cache = GitCache(root)
123
- pruned = git_cache.prune(max_age_days=days)
131
+ try:
132
+ pruned = git_cache.prune(max_age_days=days)
133
+ except CachePruneError as exc:
134
+ logger.error(str(exc))
135
+ for path, error in exc.failures:
136
+ logger.error(f"Could not prune {path}: {error}")
137
+ logger.error("Check permissions or close programs using the cache, then retry.")
138
+ raise SystemExit(1) from exc
124
139
 
125
- _rich_success(f"Pruned {pruned} checkout(s).", symbol="check")
140
+ logger.success(f"Pruned {pruned} SHA group(s).", symbol="check")
126
141
 
127
142
 
128
143
  def _format_size(size_bytes: int) -> str:
@@ -12,6 +12,7 @@ from ..constants import APM_YML_FILENAME
12
12
  from ..core.command_logger import CommandLogger
13
13
  from ..install.locking import serialized_lifecycle
14
14
  from ..version import get_version
15
+ from . import self_update as self_update_command
15
16
  from ._helpers import HIGHLIGHT, RESET, _get_console, _load_apm_config
16
17
 
17
18
  # Restore builtin since a subcommand is named ``set``
@@ -473,7 +474,13 @@ def set(key, value): # noqa: F811
473
474
 
474
475
  try:
475
476
  install_dir = set_self_update_install_dir(value)
476
- logger.success(f"Self-update install directory saved: {install_dir}")
477
+ if self_update_command._is_windows_platform():
478
+ logger.success(f"Self-update install directory saved: {install_dir}")
479
+ else:
480
+ logger.success(
481
+ f"Self-update launcher directory preference saved: {install_dir} "
482
+ "(must match the existing Unix installation)"
483
+ )
477
484
  except ValueError as exc:
478
485
  logger.error(str(exc))
479
486
  sys.exit(1)
@@ -636,7 +643,13 @@ def get(key):
636
643
 
637
644
  value = get_self_update_install_dir()
638
645
  if value is None:
639
- click.echo("self-update.install-dir: Not set (using installer default)")
646
+ if self_update_command._is_windows_platform():
647
+ click.echo("self-update.install-dir: Not set (using installer default)")
648
+ else:
649
+ click.echo(
650
+ "self-update.install-dir: Not set "
651
+ "(preserving the detected Unix installation)"
652
+ )
640
653
  else:
641
654
  click.echo(f"self-update.install-dir: {value}")
642
655
  return
@@ -766,7 +779,13 @@ def unset(key):
766
779
  from ..config import unset_self_update_install_dir
767
780
 
768
781
  unset_self_update_install_dir()
769
- logger.success("Self-update install directory removed (will use installer default)")
782
+ if self_update_command._is_windows_platform():
783
+ logger.success("Self-update install directory removed (will use installer default)")
784
+ else:
785
+ logger.success(
786
+ "Self-update launcher directory preference removed "
787
+ "(will preserve the detected Unix installation)"
788
+ )
770
789
  return
771
790
 
772
791
  if key == "mcp-registry-url":
@@ -241,6 +241,7 @@ def prune(ctx, dry_run):
241
241
  return
242
242
 
243
243
  removed_count = 0
244
+ failed_count = 0
244
245
  removed_packages: list[str] = []
245
246
  pruned_keys = list(missing_orphaned_keys)
246
247
  pruned_key_set = set(pruned_keys)
@@ -263,6 +264,7 @@ def prune(ctx, dry_run):
263
264
  pruned_key_set.add(dep_key)
264
265
  deleted_pkg_paths.append(pkg_path)
265
266
  except Exception as e:
267
+ failed_count += 1
266
268
  logger.error(f"Failed to remove {org_repo_name}: {e}")
267
269
 
268
270
  BaseIntegrator.cleanup_empty_parents(deleted_pkg_paths, stop_at=apm_modules_dir)
@@ -397,6 +399,17 @@ def prune(ctx, dry_run):
397
399
  "stale -- run 'apm install' to rebuild hook configuration."
398
400
  )
399
401
 
402
+ if failed_count:
403
+ logger.error(
404
+ f"Prune incomplete: removed {removed_count} orphaned package(s); "
405
+ f"failed to remove {failed_count} package(s)."
406
+ )
407
+ logger.error_detail(
408
+ "Filesystem cleanup may be partial. Resolve the removal errors, "
409
+ "then rerun 'apm prune'."
410
+ )
411
+ sys.exit(1)
412
+
400
413
  if removed_count > 0:
401
414
  message = f"Pruned {removed_count} orphaned package(s)"
402
415
  if owner_violations:
@@ -170,7 +170,9 @@ def get_latest_version_for_self_update(channel: str) -> str | None:
170
170
  """Return the latest version for a supported self-update channel."""
171
171
  from ..utils.version_checker import get_latest_version_from_github
172
172
 
173
- return get_latest_version_from_github(include_prerelease=(channel == "prerelease"))
173
+ return get_latest_version_from_github(
174
+ include_prerelease=(channel == "prerelease"), raise_errors=True
175
+ )
174
176
 
175
177
 
176
178
  def _build_self_update_installer_env(
@@ -194,6 +196,11 @@ def _build_self_update_installer_env(
194
196
  if _ENV_SELF_UPDATE_CHANNEL not in env:
195
197
  env[_ENV_SELF_UPDATE_CHANNEL] = channel
196
198
  env[_ENV_VERSION] = release.tag
199
+ if not _is_windows_platform():
200
+ # Pass identity, not a second destination policy: install.sh owns routing.
201
+ env["APM_SELF_UPDATE_SOURCE"] = os.path.abspath(
202
+ sys.executable if getattr(sys, "frozen", False) else sys.argv[0]
203
+ )
197
204
  return env
198
205
 
199
206
 
@@ -266,7 +273,13 @@ def self_update(check: bool) -> None:
266
273
  sys.exit(1)
267
274
 
268
275
  # Check for latest version
269
- latest_version = get_latest_version_for_self_update(_channel)
276
+ from ..utils.version_checker import ReleaseMetadataError
277
+
278
+ try:
279
+ latest_version = get_latest_version_for_self_update(_channel)
280
+ except ReleaseMetadataError as exc:
281
+ logger.error(str(exc))
282
+ sys.exit(1)
270
283
 
271
284
  if not latest_version:
272
285
  if _pinned:
@@ -352,7 +365,7 @@ def self_update(check: bool) -> None:
352
365
 
353
366
  # Note: We don't capture output so the installer can prompt when needed.
354
367
  # Sanitise the environment so the installer (and the system binaries
355
- # it spawns -- curl, tar, sudo) do not inherit the PyInstaller
368
+ # it spawns -- curl and tar) do not inherit the PyInstaller
356
369
  # bootloader's LD_LIBRARY_PATH / DYLD_* overrides, which would
357
370
  # otherwise redirect system linkers at this binary's bundled
358
371
  # _internal directory. See issue #894.
@@ -373,7 +386,8 @@ def self_update(check: bool) -> None:
373
386
  logger.success(
374
387
  f"Successfully updated to version {release.version}!",
375
388
  )
376
- logger.progress("Please restart your terminal or run 'apm --version' to verify")
389
+ if _is_windows_platform():
390
+ logger.progress("Please restart your terminal or run 'apm --version' to verify")
377
391
  else:
378
392
  logger.error("Installation failed - see output above for details")
379
393
  sys.exit(1)