apm-cli 0.23.0__tar.gz → 0.24.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 (424) hide show
  1. {apm_cli-0.23.0/src/apm_cli.egg-info → apm_cli-0.24.0}/PKG-INFO +1 -1
  2. {apm_cli-0.23.0 → apm_cli-0.24.0}/pyproject.toml +1 -1
  3. apm_cli-0.24.0/src/apm_cli/bundle/attest.py +64 -0
  4. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/bundle/packer.py +43 -1
  5. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/bundle/plugin_exporter.py +261 -24
  6. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/cache/git_cache.py +35 -29
  7. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/commands/audit.py +6 -6
  8. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/commands/compile/cli.py +9 -3
  9. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/commands/config.py +76 -63
  10. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/commands/install.py +23 -22
  11. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/commands/mcp.py +3 -5
  12. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/commands/outdated.py +8 -0
  13. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/commands/uninstall/cli.py +3 -3
  14. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/compilation/agents_compiler.py +81 -24
  15. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/compilation/claude_formatter.py +4 -3
  16. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/compilation/context_optimizer.py +12 -2
  17. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/compilation/template_builder.py +16 -5
  18. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/core/apm_yml.py +1 -0
  19. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/core/target_detection.py +39 -15
  20. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/deps/download_strategies.py +97 -39
  21. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/deps/github_downloader.py +8 -2
  22. apm_cli-0.24.0/src/apm_cli/deps/outdated_ref_cache.py +107 -0
  23. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/deps/tiered_ref_resolver.py +33 -0
  24. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/install/context.py +5 -0
  25. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/install/drift.py +2 -0
  26. apm_cli-0.24.0/src/apm_cli/install/helpers/ref_reuse.py +96 -0
  27. apm_cli-0.24.0/src/apm_cli/install/helpers/ref_seed.py +66 -0
  28. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/install/package_resolution.py +83 -2
  29. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/install/phases/lockfile.py +21 -7
  30. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/install/phases/resolve.py +16 -17
  31. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/install/plan.py +23 -12
  32. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/install/template.py +22 -10
  33. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/install/validation.py +56 -0
  34. apm_cli-0.24.0/src/apm_cli/integration/hook_bundle.py +191 -0
  35. apm_cli-0.24.0/src/apm_cli/integration/hook_file_routing.py +217 -0
  36. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/integration/hook_integrator.py +69 -39
  37. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/integration/instruction_integrator.py +52 -11
  38. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/integration/kiro_hook_integrator.py +27 -23
  39. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/integration/mcp_integrator_install.py +4 -2
  40. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/integration/skill_integrator.py +19 -14
  41. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/integration/targets.py +2 -1
  42. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/marketplace/output_mappers.py +64 -4
  43. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/marketplace/ref_resolver.py +0 -4
  44. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/models/apm_package.py +1 -0
  45. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/models/dependency/identity.py +3 -0
  46. apm_cli-0.24.0/src/apm_cli/models/dependency/object_fields.py +63 -0
  47. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/models/dependency/reference.py +28 -39
  48. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/policy/schema.py +3 -2
  49. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/security/executables.py +22 -3
  50. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/utils/archive.py +11 -2
  51. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/utils/content_hash.py +55 -2
  52. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/utils/github_host.py +7 -1
  53. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/utils/yaml_io.py +67 -4
  54. {apm_cli-0.23.0 → apm_cli-0.24.0/src/apm_cli.egg-info}/PKG-INFO +1 -1
  55. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli.egg-info/SOURCES.txt +6 -0
  56. {apm_cli-0.23.0 → apm_cli-0.24.0}/tests/test_github_downloader_token_precedence.py +1 -1
  57. apm_cli-0.23.0/src/apm_cli/integration/hook_file_routing.py +0 -120
  58. {apm_cli-0.23.0 → apm_cli-0.24.0}/AUTHORS +0 -0
  59. {apm_cli-0.23.0 → apm_cli-0.24.0}/LICENSE +0 -0
  60. {apm_cli-0.23.0 → apm_cli-0.24.0}/NOTICE +0 -0
  61. {apm_cli-0.23.0 → apm_cli-0.24.0}/README.md +0 -0
  62. {apm_cli-0.23.0 → apm_cli-0.24.0}/setup.cfg +0 -0
  63. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/__init__.py +0 -0
  64. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/adapters/__init__.py +0 -0
  65. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/adapters/client/__init__.py +0 -0
  66. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/adapters/client/_mcp_runtime_args.py +0 -0
  67. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/adapters/client/antigravity.py +0 -0
  68. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/adapters/client/base.py +0 -0
  69. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/adapters/client/claude.py +0 -0
  70. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/adapters/client/codex.py +0 -0
  71. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/adapters/client/copilot.py +0 -0
  72. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/adapters/client/cursor.py +0 -0
  73. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/adapters/client/gemini.py +0 -0
  74. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/adapters/client/hermes.py +0 -0
  75. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/adapters/client/intellij.py +0 -0
  76. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/adapters/client/kiro.py +0 -0
  77. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/adapters/client/opencode.py +0 -0
  78. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/adapters/client/vscode.py +0 -0
  79. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/adapters/client/windsurf.py +0 -0
  80. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/adapters/package_manager/__init__.py +0 -0
  81. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/adapters/package_manager/base.py +0 -0
  82. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/adapters/package_manager/default_manager.py +0 -0
  83. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/bootstrap_mirror.py +0 -0
  84. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/bundle/__init__.py +0 -0
  85. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/bundle/local_bundle.py +0 -0
  86. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/bundle/lockfile_enrichment.py +0 -0
  87. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/bundle/unpacker.py +0 -0
  88. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/cache/__init__.py +0 -0
  89. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/cache/http_cache.py +0 -0
  90. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/cache/integrity.py +0 -0
  91. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/cache/locking.py +0 -0
  92. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/cache/paths.py +0 -0
  93. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/cache/url_normalize.py +0 -0
  94. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/cli.py +0 -0
  95. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/commands/__init__.py +0 -0
  96. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/commands/_apm_yml_writer.py +0 -0
  97. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/commands/_helpers.py +0 -0
  98. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/commands/approve.py +0 -0
  99. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/commands/cache.py +0 -0
  100. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/commands/compile/__init__.py +0 -0
  101. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/commands/compile/watcher.py +0 -0
  102. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/commands/deps/__init__.py +0 -0
  103. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/commands/deps/_utils.py +0 -0
  104. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/commands/deps/cli.py +0 -0
  105. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/commands/deps/why.py +0 -0
  106. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/commands/doctor.py +0 -0
  107. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/commands/experimental.py +0 -0
  108. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/commands/find.py +0 -0
  109. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/commands/init.py +0 -0
  110. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/commands/lifecycle.py +0 -0
  111. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/commands/list_cmd.py +0 -0
  112. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/commands/lock.py +0 -0
  113. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/commands/marketplace/__init__.py +0 -0
  114. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/commands/marketplace/audit.py +0 -0
  115. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/commands/marketplace/check.py +0 -0
  116. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/commands/marketplace/doctor.py +0 -0
  117. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/commands/marketplace/init.py +0 -0
  118. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/commands/marketplace/migrate.py +0 -0
  119. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/commands/marketplace/outdated.py +0 -0
  120. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/commands/marketplace/plugin/__init__.py +0 -0
  121. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/commands/marketplace/plugin/add.py +0 -0
  122. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/commands/marketplace/plugin/remove.py +0 -0
  123. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/commands/marketplace/plugin/set.py +0 -0
  124. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/commands/marketplace/validate.py +0 -0
  125. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/commands/pack.py +0 -0
  126. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/commands/plugin/__init__.py +0 -0
  127. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/commands/plugin/init.py +0 -0
  128. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/commands/policy.py +0 -0
  129. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/commands/prune.py +0 -0
  130. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/commands/publish.py +0 -0
  131. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/commands/run.py +0 -0
  132. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/commands/runtime.py +0 -0
  133. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/commands/self_update.py +0 -0
  134. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/commands/targets.py +0 -0
  135. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/commands/uninstall/__init__.py +0 -0
  136. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/commands/uninstall/engine.py +0 -0
  137. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/commands/update.py +0 -0
  138. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/commands/view.py +0 -0
  139. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/compilation/__init__.py +0 -0
  140. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/compilation/build_id.py +0 -0
  141. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/compilation/constants.py +0 -0
  142. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/compilation/constitution.py +0 -0
  143. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/compilation/constitution_block.py +0 -0
  144. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/compilation/distributed_compiler.py +0 -0
  145. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/compilation/gemini_formatter.py +0 -0
  146. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/compilation/injector.py +0 -0
  147. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/compilation/link_resolver.py +0 -0
  148. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/compilation/managed_section.py +0 -0
  149. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/compilation/output_writer.py +0 -0
  150. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/compilation/user_root_context.py +0 -0
  151. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/config.py +0 -0
  152. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/constants.py +0 -0
  153. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/core/__init__.py +0 -0
  154. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/core/auth.py +0 -0
  155. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/core/azure_cli.py +0 -0
  156. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/core/build_orchestrator.py +0 -0
  157. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/core/command_logger.py +0 -0
  158. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/core/conflict_detector.py +0 -0
  159. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/core/docker_args.py +0 -0
  160. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/core/errors.py +0 -0
  161. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/core/experimental.py +0 -0
  162. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/core/install_audit.py +0 -0
  163. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/core/lifecycle_scripts.py +0 -0
  164. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/core/null_logger.py +0 -0
  165. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/core/operations.py +0 -0
  166. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/core/plugin_manifest.py +0 -0
  167. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/core/safe_installer.py +0 -0
  168. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/core/scope.py +0 -0
  169. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/core/script_executors.py +0 -0
  170. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/core/script_runner.py +0 -0
  171. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/core/script_trust.py +0 -0
  172. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/core/token_manager.py +0 -0
  173. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/deps/__init__.py +0 -0
  174. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/deps/_shared.py +0 -0
  175. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/deps/aggregator.py +0 -0
  176. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/deps/apm_resolver.py +0 -0
  177. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/deps/artifactory_entry.py +0 -0
  178. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/deps/artifactory_orchestrator.py +0 -0
  179. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/deps/bare_cache.py +0 -0
  180. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/deps/clone_engine.py +0 -0
  181. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/deps/dependency_graph.py +0 -0
  182. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/deps/git_auth_env.py +0 -0
  183. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/deps/git_file_transport.py +0 -0
  184. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/deps/git_reference_resolver.py +0 -0
  185. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/deps/git_remote_ops.py +0 -0
  186. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/deps/git_semver_resolver.py +0 -0
  187. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/deps/github_downloader_validation.py +0 -0
  188. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/deps/host_backends.py +0 -0
  189. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/deps/installed_package.py +0 -0
  190. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/deps/lockfile.py +0 -0
  191. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/deps/outdated_row.py +0 -0
  192. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/deps/package_validator.py +0 -0
  193. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/deps/path_anchoring.py +0 -0
  194. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/deps/plugin_parser.py +0 -0
  195. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/deps/registry/__init__.py +0 -0
  196. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/deps/registry/auth.py +0 -0
  197. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/deps/registry/client.py +0 -0
  198. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/deps/registry/config_loader.py +0 -0
  199. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/deps/registry/extractor.py +0 -0
  200. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/deps/registry/feature_gate.py +0 -0
  201. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/deps/registry/outdated.py +0 -0
  202. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/deps/registry/resolver.py +0 -0
  203. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/deps/registry/semver.py +0 -0
  204. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/deps/registry_proxy.py +0 -0
  205. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/deps/revision_pins.py +0 -0
  206. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/deps/shared_clone_cache.py +0 -0
  207. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/deps/transport_selection.py +0 -0
  208. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/deps/verifier.py +0 -0
  209. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/deps/why_walker.py +0 -0
  210. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/drift.py +0 -0
  211. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/export/__init__.py +0 -0
  212. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/export/authoring.py +0 -0
  213. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/export/declared_license.py +0 -0
  214. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/export/formats.py +0 -0
  215. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/export/purl.py +0 -0
  216. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/export/sbom.py +0 -0
  217. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/export/spdx.py +0 -0
  218. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/export/spdx_data.py +0 -0
  219. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/factory.py +0 -0
  220. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/install/__init__.py +0 -0
  221. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/install/artifactory_resolver.py +0 -0
  222. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/install/cache_pin.py +0 -0
  223. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/install/deployed_paths.py +0 -0
  224. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/install/errors.py +0 -0
  225. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/install/exec_gate.py +0 -0
  226. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/install/gitlab_resolver.py +0 -0
  227. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/install/heals/__init__.py +0 -0
  228. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/install/heals/base.py +0 -0
  229. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/install/heals/branch_ref_drift.py +0 -0
  230. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/install/heals/buggy_lockfile_recovery.py +0 -0
  231. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/install/helpers/__init__.py +0 -0
  232. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/install/helpers/security_scan.py +0 -0
  233. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/install/insecure_policy.py +0 -0
  234. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/install/integrity.py +0 -0
  235. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/install/local_bundle_handler.py +0 -0
  236. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/install/lsp/__init__.py +0 -0
  237. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/install/lsp/integration.py +0 -0
  238. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/install/manifest_reconcile.py +0 -0
  239. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/install/mcp/__init__.py +0 -0
  240. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/install/mcp/args.py +0 -0
  241. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/install/mcp/command.py +0 -0
  242. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/install/mcp/conflicts.py +0 -0
  243. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/install/mcp/entry.py +0 -0
  244. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/install/mcp/registry.py +0 -0
  245. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/install/mcp/warnings.py +0 -0
  246. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/install/mcp/writer.py +0 -0
  247. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/install/package_selection.py +0 -0
  248. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/install/phases/__init__.py +0 -0
  249. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/install/phases/_redownload.py +0 -0
  250. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/install/phases/_skip_logic.py +0 -0
  251. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/install/phases/audit.py +0 -0
  252. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/install/phases/cleanup.py +0 -0
  253. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/install/phases/download.py +0 -0
  254. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/install/phases/finalize.py +0 -0
  255. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/install/phases/heal.py +0 -0
  256. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/install/phases/integrate.py +0 -0
  257. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/install/phases/local_content.py +0 -0
  258. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/install/phases/policy_gate.py +0 -0
  259. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/install/phases/policy_target_check.py +0 -0
  260. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/install/phases/post_deps_local.py +0 -0
  261. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/install/phases/targets.py +0 -0
  262. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/install/pipeline.py +0 -0
  263. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/install/presentation/__init__.py +0 -0
  264. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/install/presentation/dry_run.py +0 -0
  265. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/install/registry_wiring.py +0 -0
  266. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/install/request.py +0 -0
  267. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/install/root_redirect.py +0 -0
  268. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/install/service.py +0 -0
  269. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/install/services.py +0 -0
  270. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/install/skill_path_migration.py +0 -0
  271. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/install/sources.py +0 -0
  272. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/install/summary.py +0 -0
  273. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/install/target_filter.py +0 -0
  274. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/integration/__init__.py +0 -0
  275. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/integration/_shared.py +0 -0
  276. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/integration/agent_integrator.py +0 -0
  277. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/integration/base_integrator.py +0 -0
  278. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/integration/canvas_integrator.py +0 -0
  279. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/integration/cleanup.py +0 -0
  280. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/integration/command_integrator.py +0 -0
  281. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/integration/copilot_app_db.py +0 -0
  282. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/integration/copilot_app_project.py +0 -0
  283. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/integration/copilot_app_workflow_integrator.py +0 -0
  284. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/integration/copilot_app_ws.py +0 -0
  285. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/integration/copilot_cowork_paths.py +0 -0
  286. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/integration/coverage.py +0 -0
  287. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/integration/dispatch.py +0 -0
  288. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/integration/lsp_integrator.py +0 -0
  289. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/integration/mcp_integrator.py +0 -0
  290. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/integration/opencode_frontmatter.py +0 -0
  291. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/integration/prompt_integrator.py +0 -0
  292. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/integration/skill_transformer.py +0 -0
  293. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/integration/utils.py +0 -0
  294. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/marketplace/__init__.py +0 -0
  295. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/marketplace/_git_utils.py +0 -0
  296. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/marketplace/_io.py +0 -0
  297. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/marketplace/_shared.py +0 -0
  298. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/marketplace/audit.py +0 -0
  299. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/marketplace/auth_helpers.py +0 -0
  300. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/marketplace/builder.py +0 -0
  301. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/marketplace/client.py +0 -0
  302. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/marketplace/diagnostics.py +0 -0
  303. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/marketplace/drift_check.py +0 -0
  304. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/marketplace/errors.py +0 -0
  305. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/marketplace/git_stderr.py +0 -0
  306. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/marketplace/init_template.py +0 -0
  307. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/marketplace/migration.py +0 -0
  308. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/marketplace/models.py +0 -0
  309. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/marketplace/output_profiles.py +0 -0
  310. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/marketplace/registry.py +0 -0
  311. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/marketplace/resolver.py +0 -0
  312. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/marketplace/semver.py +0 -0
  313. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/marketplace/shadow_detector.py +0 -0
  314. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/marketplace/tag_pattern.py +0 -0
  315. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/marketplace/validator.py +0 -0
  316. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/marketplace/version_check.py +0 -0
  317. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/marketplace/version_pins.py +0 -0
  318. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/marketplace/version_resolver.py +0 -0
  319. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/marketplace/yml_editor.py +0 -0
  320. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/marketplace/yml_schema.py +0 -0
  321. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/models/__init__.py +0 -0
  322. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/models/dependency/__init__.py +0 -0
  323. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/models/dependency/lsp.py +0 -0
  324. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/models/dependency/mcp.py +0 -0
  325. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/models/dependency/subsets.py +0 -0
  326. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/models/dependency/types.py +0 -0
  327. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/models/format_detection.py +0 -0
  328. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/models/plugin.py +0 -0
  329. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/models/results.py +0 -0
  330. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/models/validation.py +0 -0
  331. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/output/__init__.py +0 -0
  332. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/output/formatters.py +0 -0
  333. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/output/models.py +0 -0
  334. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/output/script_formatters.py +0 -0
  335. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/policy/__init__.py +0 -0
  336. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/policy/_constraint_pinning.py +0 -0
  337. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/policy/_help_text.py +0 -0
  338. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/policy/_shared.py +0 -0
  339. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/policy/ci_checks.py +0 -0
  340. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/policy/discovery.py +0 -0
  341. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/policy/inheritance.py +0 -0
  342. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/policy/install_preflight.py +0 -0
  343. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/policy/matcher.py +0 -0
  344. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/policy/models.py +0 -0
  345. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/policy/outcome_routing.py +0 -0
  346. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/policy/parser.py +0 -0
  347. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/policy/policy_checks.py +0 -0
  348. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/policy/project_config.py +0 -0
  349. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/primitives/__init__.py +0 -0
  350. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/primitives/discovery.py +0 -0
  351. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/primitives/models.py +0 -0
  352. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/primitives/parser.py +0 -0
  353. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/registry/__init__.py +0 -0
  354. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/registry/client.py +0 -0
  355. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/registry/integration.py +0 -0
  356. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/registry/operations.py +0 -0
  357. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/runtime/__init__.py +0 -0
  358. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/runtime/base.py +0 -0
  359. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/runtime/codex_runtime.py +0 -0
  360. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/runtime/copilot_runtime.py +0 -0
  361. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/runtime/factory.py +0 -0
  362. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/runtime/llm_runtime.py +0 -0
  363. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/runtime/manager.py +0 -0
  364. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/runtime/utils.py +0 -0
  365. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/security/__init__.py +0 -0
  366. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/security/audit_report.py +0 -0
  367. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/security/content_scanner.py +0 -0
  368. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/security/external/__init__.py +0 -0
  369. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/security/external/base.py +0 -0
  370. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/security/external/gate.py +0 -0
  371. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/security/external/generic_sarif.py +0 -0
  372. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/security/external/options.py +0 -0
  373. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/security/external/registry.py +0 -0
  374. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/security/external/runner.py +0 -0
  375. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/security/external/sarif_ingest.py +0 -0
  376. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/security/external/skillspector.py +0 -0
  377. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/security/file_scanner.py +0 -0
  378. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/security/gate.py +0 -0
  379. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/update_policy.py +0 -0
  380. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/utils/__init__.py +0 -0
  381. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/utils/atomic_io.py +0 -0
  382. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/utils/console.py +0 -0
  383. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/utils/diagnostics.py +0 -0
  384. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/utils/exclude.py +0 -0
  385. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/utils/file_ops.py +0 -0
  386. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/utils/git_env.py +0 -0
  387. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/utils/git_sparse.py +0 -0
  388. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/utils/guards.py +0 -0
  389. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/utils/helpers.py +0 -0
  390. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/utils/install_tui.py +0 -0
  391. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/utils/normalization.py +0 -0
  392. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/utils/path_security.py +0 -0
  393. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/utils/paths.py +0 -0
  394. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/utils/patterns.py +0 -0
  395. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/utils/perf_stats.py +0 -0
  396. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/utils/reflink.py +0 -0
  397. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/utils/short_sha.py +0 -0
  398. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/utils/subprocess_env.py +0 -0
  399. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/utils/version_checker.py +0 -0
  400. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/version.py +0 -0
  401. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/workflow/__init__.py +0 -0
  402. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/workflow/discovery.py +0 -0
  403. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/workflow/parser.py +0 -0
  404. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli/workflow/runner.py +0 -0
  405. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli.egg-info/dependency_links.txt +0 -0
  406. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli.egg-info/entry_points.txt +0 -0
  407. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli.egg-info/requires.txt +0 -0
  408. {apm_cli-0.23.0 → apm_cli-0.24.0}/src/apm_cli.egg-info/top_level.txt +0 -0
  409. {apm_cli-0.23.0 → apm_cli-0.24.0}/tests/test_apm_package_models.py +0 -0
  410. {apm_cli-0.23.0 → apm_cli-0.24.0}/tests/test_apm_resolver.py +0 -0
  411. {apm_cli-0.23.0 → apm_cli-0.24.0}/tests/test_codex_docker_args_fix.py +0 -0
  412. {apm_cli-0.23.0 → apm_cli-0.24.0}/tests/test_codex_empty_string_and_defaults.py +0 -0
  413. {apm_cli-0.23.0 → apm_cli-0.24.0}/tests/test_collision_integration.py +0 -0
  414. {apm_cli-0.23.0 → apm_cli-0.24.0}/tests/test_console.py +0 -0
  415. {apm_cli-0.23.0 → apm_cli-0.24.0}/tests/test_distributed_compilation.py +0 -0
  416. {apm_cli-0.23.0 → apm_cli-0.24.0}/tests/test_empty_string_and_defaults.py +0 -0
  417. {apm_cli-0.23.0 → apm_cli-0.24.0}/tests/test_enhanced_discovery.py +0 -0
  418. {apm_cli-0.23.0 → apm_cli-0.24.0}/tests/test_github_downloader.py +0 -0
  419. {apm_cli-0.23.0 → apm_cli-0.24.0}/tests/test_gitlab_git_transport.py +0 -0
  420. {apm_cli-0.23.0 → apm_cli-0.24.0}/tests/test_lockfile.py +0 -0
  421. {apm_cli-0.23.0 → apm_cli-0.24.0}/tests/test_runnable_prompts.py +0 -0
  422. {apm_cli-0.23.0 → apm_cli-0.24.0}/tests/test_runtime_manager_token_precedence.py +0 -0
  423. {apm_cli-0.23.0 → apm_cli-0.24.0}/tests/test_token_manager.py +0 -0
  424. {apm_cli-0.23.0 → apm_cli-0.24.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.23.0
3
+ Version: 0.24.0
4
4
  Summary: MCP configuration tool
5
5
  Author-email: Daniel Meppiel <user@example.com>
6
6
  License: MIT License
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "apm-cli"
7
- version = "0.23.0"
7
+ version = "0.24.0"
8
8
  description = "MCP configuration tool"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.10"
@@ -0,0 +1,64 @@
1
+ """Shared per-file provenance verification for the pack pipelines (#2013).
2
+
3
+ Both pack formats copy dependency files that ``apm install`` recorded in
4
+ ``apm.lock.yaml`` under ``deployed_files`` + ``deployed_file_hashes``:
5
+
6
+ * ``--format plugin`` (:mod:`apm_cli.bundle.plugin_exporter`)
7
+ * ``--format apm`` (:mod:`apm_cli.bundle.packer`)
8
+
9
+ Before a byte enters a bundle its on-disk copy is verified against the
10
+ attested SHA-256 recorded at install time. A file that was tampered or
11
+ corrupted after ``apm install`` must never enter a bundle silently. Keeping
12
+ the check in ONE place gives both pack paths identical semantics and avoids a
13
+ copy-pasted block that would trip the pylint R0801 duplication gate.
14
+
15
+ Tolerance rule (forward-compat): a file with *no* recorded hash -- either an
16
+ older lockfile with an empty ``deployed_file_hashes`` or a specific path with
17
+ no recorded entry -- is packed without verification. Absence of an attestation
18
+ is tolerated; a *mismatched* attestation is a hard error. The unverified gap
19
+ is surfaced as a debug diagnostic so ``apm audit``-minded users can see it.
20
+ """
21
+
22
+ import logging
23
+ from pathlib import Path
24
+
25
+ from ..utils.content_hash import compute_file_hash
26
+
27
+ _logger = logging.getLogger(__name__)
28
+
29
+
30
+ def verify_attested_file(
31
+ source: Path,
32
+ expected_hash: str | None,
33
+ dep_label: str,
34
+ rel_display: str,
35
+ ) -> None:
36
+ """Fail loudly when *source* diverges from its attested SHA-256.
37
+
38
+ Args:
39
+ source: On-disk file being packed.
40
+ expected_hash: The ``"sha256:<hex>"`` recorded in
41
+ ``deployed_file_hashes``, or ``None`` when no hash was recorded.
42
+ dep_label: Dependency identifier (``repo_url``) for the error message.
43
+ rel_display: Human-readable path shown in diagnostics / errors.
44
+
45
+ Raises:
46
+ ValueError: When a recorded hash exists and the on-disk content does
47
+ not match it.
48
+ """
49
+ if not expected_hash:
50
+ _logger.debug(
51
+ "no attested hash for %r from %s; packed without integrity "
52
+ "verification (older lockfile)",
53
+ rel_display,
54
+ dep_label,
55
+ )
56
+ return
57
+ actual = compute_file_hash(source)
58
+ if actual != expected_hash:
59
+ raise ValueError(
60
+ f"Cannot pack dependency {dep_label}: installed file {rel_display!r} "
61
+ "does not match the hash recorded in apm.lock.yaml. The installed "
62
+ "copy may be stale or tampered. Run 'apm install' to restore "
63
+ "attested content, then pack again."
64
+ )
@@ -13,6 +13,7 @@ from ..utils.archive import (
13
13
  write_tar_archive,
14
14
  write_zip_archive,
15
15
  )
16
+ from .attest import verify_attested_file
16
17
  from .lockfile_enrichment import _filter_files_by_target, enrich_lockfile_for_pack
17
18
 
18
19
 
@@ -158,10 +159,19 @@ def pack_bundle(
158
159
  # not portable and is bundled separately via the project's own files
159
160
  # (or rejected outright at L89-97 for manifest-declared local deps).
160
161
  all_deployed: list[str] = []
162
+ # Provenance map: deployed-path -> (attested SHA-256, dependency label).
163
+ # ``deployed_file_hashes`` is keyed by the on-disk deployed path recorded
164
+ # at install time (see install/phases/lockfile.compute_deployed_hashes), so
165
+ # verification below must look up the on-disk path, not the bundle path.
166
+ deployed_hashes: dict[str, str] = {}
167
+ hash_dep_labels: dict[str, str] = {}
161
168
  for dep in lockfile.get_all_dependencies():
162
169
  if dep.source == "local":
163
170
  continue
164
171
  all_deployed.extend(dep.deployed_files)
172
+ for _dpath, _dhash in dep.deployed_file_hashes.items():
173
+ deployed_hashes[_dpath] = _dhash
174
+ hash_dep_labels[_dpath] = dep.repo_url
165
175
 
166
176
  filtered_files, path_mappings = _filter_files_by_target(all_deployed, effective_target)
167
177
  # Deduplicate while preserving order
@@ -250,7 +260,12 @@ def pack_bundle(
250
260
  bundle_dir.mkdir(parents=True, exist_ok=True)
251
261
  bundle_dir_resolved = bundle_dir.resolve()
252
262
 
253
- # 7. Copy files preserving directory structure
263
+ # 7. Copy files preserving directory structure.
264
+ # Provenance gate (#2013): each dependency file recorded in the lockfile
265
+ # is verified against its attested SHA-256 before it enters the bundle --
266
+ # the same integrity guarantee the plugin format enforces, applied to the
267
+ # default/most-used ``apm`` format. Files with no recorded hash (older
268
+ # lockfiles) pack without verification; a mismatch fails loud.
254
269
  for rel_path in unique_files:
255
270
  # For cross-target mapped files, read from the original disk path
256
271
  disk_path = path_mappings.get(rel_path, rel_path)
@@ -264,8 +279,35 @@ def pack_bundle(
264
279
  if src.is_dir():
265
280
  from ..security.gate import ignore_non_content
266
281
 
282
+ # Verify each contained file's attested hash and re-assert
283
+ # containment per child. copytree already drops symlinks via
284
+ # ignore_non_content, but the walk guards against a directory
285
+ # symlink whose target escapes the project root regardless of the
286
+ # walker's version-specific symlink-following behaviour.
287
+ disk_base = disk_path.rstrip("/")
288
+ for child in sorted(src.rglob("*")):
289
+ if not child.is_file() or child.is_symlink():
290
+ continue
291
+ if not child.resolve().is_relative_to(project_root_resolved):
292
+ raise ValueError(
293
+ f"Refusing to pack path that escapes project root: "
294
+ f"{child.relative_to(project_root)!r}"
295
+ )
296
+ child_key = f"{disk_base}/{child.relative_to(src).as_posix()}"
297
+ verify_attested_file(
298
+ child,
299
+ deployed_hashes.get(child_key),
300
+ hash_dep_labels.get(child_key, "dependency"),
301
+ child_key,
302
+ )
267
303
  shutil.copytree(src, dest, dirs_exist_ok=True, ignore=ignore_non_content)
268
304
  else:
305
+ verify_attested_file(
306
+ src,
307
+ deployed_hashes.get(disk_path),
308
+ hash_dep_labels.get(disk_path, "dependency"),
309
+ disk_path,
310
+ )
269
311
  dest.parent.mkdir(parents=True, exist_ok=True)
270
312
  shutil.copy2(src, dest, follow_symlinks=False)
271
313
 
@@ -11,7 +11,7 @@ import hashlib
11
11
  import json
12
12
  import re
13
13
  import shutil
14
- from pathlib import Path, PurePosixPath
14
+ from pathlib import Path, PurePosixPath, PureWindowsPath
15
15
 
16
16
  import yaml
17
17
 
@@ -30,6 +30,7 @@ from ..utils.archive import (
30
30
  )
31
31
  from ..utils.console import _rich_warning
32
32
  from ..utils.path_security import PathTraversalError, ensure_path_within, safe_rmtree
33
+ from .attest import verify_attested_file
33
34
  from .packer import PackResult
34
35
 
35
36
  # ---------------------------------------------------------------------------
@@ -417,6 +418,217 @@ def _dep_install_path(dep: LockedDependency, apm_modules_dir: Path) -> Path:
417
418
  return dep_ref.get_install_path(apm_modules_dir)
418
419
 
419
420
 
421
+ def _deployed_path_parts(rel_path: str) -> tuple[str, ...]:
422
+ """Return safe POSIX path parts for a lockfile deployed_files entry."""
423
+ rel = rel_path.replace("\\", "/")
424
+ pure = PurePosixPath(rel)
425
+ if pure.is_absolute() or PureWindowsPath(rel).is_absolute():
426
+ raise ValueError(f"Refusing to pack absolute deployed file path: {rel_path!r}")
427
+ parts = pure.parts
428
+ if any(part in ("", ".", "..") for part in parts):
429
+ raise ValueError(f"Refusing to pack unsafe deployed file path: {rel_path!r}")
430
+ return parts
431
+
432
+
433
+ def _skill_name_from_deployed_parts(parts: tuple[str, ...]) -> str | None:
434
+ """Return the deployed skill name when *parts* point inside a skills dir."""
435
+ if len(parts) >= 3 and parts[0].startswith(".") and parts[1] == "skills":
436
+ return parts[2]
437
+ if len(parts) >= 2 and parts[0] == "skills":
438
+ return parts[1]
439
+ return None
440
+
441
+
442
+ def _plugin_rel_for_deployed_path(
443
+ rel_path: str,
444
+ skill_subset: set[str] | None,
445
+ ) -> str | None:
446
+ """Map an installed deployed_files path back to plugin-native output layout."""
447
+ parts = _deployed_path_parts(rel_path)
448
+ if not parts:
449
+ return None
450
+
451
+ if parts[0] == "skills":
452
+ skill_name = _skill_name_from_deployed_parts(parts)
453
+ if skill_subset and (skill_name is None or skill_name not in skill_subset):
454
+ return None
455
+ plugin_parts = list(parts)
456
+ elif parts[0] in {"agents", "commands", "instructions", "extensions"}:
457
+ plugin_parts = list(parts)
458
+ elif len(parts) >= 3 and parts[0].startswith("."):
459
+ skill_name = _skill_name_from_deployed_parts(parts)
460
+ if skill_name is not None:
461
+ if skill_subset and skill_name not in skill_subset:
462
+ return None
463
+ plugin_parts = ["skills", *parts[2:]]
464
+ elif parts[1] == "agents":
465
+ plugin_parts = ["agents", *parts[2:]]
466
+ elif parts[1] in {"commands", "prompts"}:
467
+ plugin_parts = ["commands", *parts[2:]]
468
+ elif parts[1] in {"instructions", "rules", "steering"}:
469
+ plugin_parts = ["instructions", *parts[2:]]
470
+ elif parts[1] == "extensions":
471
+ plugin_parts = ["extensions", *parts[2:]]
472
+ elif parts[1] == "hooks":
473
+ plugin_parts = ["hooks", *parts[2:]]
474
+ else:
475
+ return None
476
+ elif len(parts) >= 2 and parts[0].startswith(".") and parts[1] == "hooks.json":
477
+ plugin_parts = ["hooks.json"]
478
+ else:
479
+ return None
480
+
481
+ if plugin_parts[0] == "commands" and plugin_parts[-1].endswith(".prompt.md"):
482
+ plugin_parts[-1] = _rename_prompt(plugin_parts[-1])
483
+ return PurePosixPath(*plugin_parts).as_posix()
484
+
485
+
486
+ def _verify_attested_hash(
487
+ source: Path,
488
+ project_root: Path,
489
+ dep: LockedDependency,
490
+ ) -> None:
491
+ """Fail loudly when a packed deployed file diverges from its attested hash.
492
+
493
+ ``deployed_file_hashes`` records the SHA-256 (``"sha256:<hex>"``) of each
494
+ file at install time. Verifying the on-disk copy before packing closes the
495
+ integrity half of the provenance hole: a deployed file that was tampered
496
+ or corrupted after ``apm install`` must never enter the bundle silently.
497
+
498
+ Files with no recorded hash (older lockfiles predating
499
+ ``deployed_file_hashes``) are packed without verification -- absence of an
500
+ attestation is forward-compat tolerated, presence of a *mismatched* one is
501
+ a hard error. Delegates to the shared :func:`verify_attested_file` helper so
502
+ the plugin and archive pack paths share one implementation.
503
+ """
504
+ rel = source.relative_to(project_root).as_posix()
505
+ expected = dep.deployed_file_hashes.get(rel) if dep.deployed_file_hashes else None
506
+ verify_attested_file(source, expected, dep.repo_url, rel)
507
+
508
+
509
+ def _append_deployed_component(
510
+ components: list[tuple[Path, str]],
511
+ source: Path,
512
+ output_rel: str,
513
+ seen_outputs: set[str],
514
+ project_root: Path,
515
+ dep: LockedDependency,
516
+ ) -> None:
517
+ """Append one deployed component unless it is unsafe or already mapped."""
518
+ if output_rel in seen_outputs or not _validate_output_rel(output_rel):
519
+ return
520
+ if source.is_file() and not source.is_symlink():
521
+ _verify_attested_hash(source, project_root, dep)
522
+ components.append((source, output_rel))
523
+ seen_outputs.add(output_rel)
524
+
525
+
526
+ def _collect_deployed_components(
527
+ project_root: Path,
528
+ dep: LockedDependency,
529
+ ) -> list[tuple[Path, str]]:
530
+ """Collect dependency components from lockfile deployed_files entries."""
531
+ components: list[tuple[Path, str]] = []
532
+ missing: list[str] = []
533
+ seen_outputs: set[str] = set()
534
+ skill_subset = set(dep.skill_subset) if dep.skill_subset else None
535
+
536
+ for rel_path in dep.deployed_files:
537
+ try:
538
+ plugin_rel = _plugin_rel_for_deployed_path(rel_path, skill_subset)
539
+ except ValueError as exc:
540
+ raise ValueError(f"Cannot pack dependency {dep.repo_url}: {exc}") from exc
541
+ if plugin_rel is None:
542
+ continue
543
+ source = project_root / rel_path
544
+ try:
545
+ source = ensure_path_within(source, project_root)
546
+ except PathTraversalError as exc:
547
+ raise ValueError(
548
+ f"Cannot pack dependency {dep.repo_url}: deployed file path "
549
+ f"escapes the project root: {rel_path!r}"
550
+ ) from exc
551
+ if not source.exists():
552
+ missing.append(rel_path)
553
+ continue
554
+ if source.is_symlink():
555
+ continue
556
+ if source.is_dir():
557
+ for child in sorted(source.rglob("*")):
558
+ if not child.is_file() or child.is_symlink():
559
+ continue
560
+ # Defense-in-depth: rglob's symlink-following behaviour is
561
+ # Python-version dependent, so re-assert containment on every
562
+ # expanded child rather than trusting the walk. A planted
563
+ # directory symlink whose target escapes ``project_root`` is
564
+ # rejected here even if an intermediate component was a symlink.
565
+ try:
566
+ ensure_path_within(child, project_root)
567
+ except PathTraversalError:
568
+ continue
569
+ child_rel = child.relative_to(source).as_posix()
570
+ child_output = (PurePosixPath(plugin_rel) / child_rel).as_posix()
571
+ _append_deployed_component(
572
+ components, child, child_output, seen_outputs, project_root, dep
573
+ )
574
+ else:
575
+ _append_deployed_component(
576
+ components, source, plugin_rel, seen_outputs, project_root, dep
577
+ )
578
+
579
+ if missing:
580
+ shown_missing = missing[:10]
581
+ remaining = len(missing) - len(shown_missing)
582
+ suffix = f"\n ... and {remaining} more" if remaining else ""
583
+ raise ValueError(
584
+ f"Cannot pack dependency {dep.repo_url}: installed files recorded "
585
+ "in apm.lock.yaml are missing on disk. Run 'apm install' to "
586
+ "restore them, then pack again:\n"
587
+ + "\n".join(f" - {path}" for path in shown_missing)
588
+ + suffix
589
+ )
590
+ return components
591
+
592
+
593
+ def _cache_would_contribute_primitives(install_path: Path, dep: LockedDependency) -> bool:
594
+ """Return True if the unattested apm_modules cache holds packable primitives.
595
+
596
+ Used ONLY to decide whether to fail loudly when a locked dependency records
597
+ no ``deployed_files``. This reads the cache to DETECT a provenance gap; it
598
+ never copies cache bytes into the bundle. A dependency that installed
599
+ real components but recorded none of them in the lockfile is a stale or
600
+ partial install -- packing its cache would leak unattested content, so we
601
+ refuse rather than silently pack it.
602
+ """
603
+ if not install_path.is_dir():
604
+ return False
605
+ probe = _collect_apm_components(install_path / ".apm")
606
+ probe.extend(_collect_root_plugin_components(install_path))
607
+ _collect_bare_skill(install_path, dep, probe)
608
+ return bool(probe)
609
+
610
+
611
+ def _cache_would_contribute_hooks_or_mcp(install_path: Path) -> bool:
612
+ """Return True if the unattested cache holds hooks-config or MCP-config.
613
+
614
+ Hooks/MCP *configuration* (``.apm/hooks/*.json``, root ``hooks.json`` /
615
+ ``hooks/``, ``.mcp.json``) is merged into shared host settings by
616
+ ``apm install`` and is never recorded in the lockfile ``deployed_files``.
617
+ Because plugin pack now emits only lockfile-attested content, such config
618
+ is dropped from the bundle. This probe drives a transition warning that
619
+ names the dependency whose cached config will NOT be packed; it never
620
+ copies cache bytes. Hook *scripts* recorded in ``deployed_files`` are
621
+ unaffected and still pack.
622
+ """
623
+ if not install_path.is_dir():
624
+ return False
625
+ if _collect_mcp(install_path):
626
+ return True
627
+ if _collect_hooks_from_apm(install_path / ".apm"):
628
+ return True
629
+ return bool(_collect_hooks_from_root(install_path))
630
+
631
+
420
632
  # ---------------------------------------------------------------------------
421
633
  # Main exporter
422
634
  # ---------------------------------------------------------------------------
@@ -500,34 +712,59 @@ def export_plugin_bundle(
500
712
  ):
501
713
  continue
502
714
 
503
- install_path = _dep_install_path(dep, apm_modules_dir)
504
- if not install_path.is_dir():
505
- continue
506
-
507
715
  dep_name = dep.repo_url
508
716
 
509
- # Collect from .apm/
510
- dep_apm_dir = install_path / ".apm"
511
- dep_components = _collect_apm_components(dep_apm_dir)
512
-
513
- # Also collect root-level plugin-native dirs from the dep
514
- dep_components.extend(_collect_root_plugin_components(install_path))
515
-
516
- # Bare Claude skills: SKILL.md at dep root with no skills/ subdir
517
- _collect_bare_skill(install_path, dep, dep_components)
717
+ # Provenance rule (issue #1999 follow-up): a dependency's content
718
+ # is packed EXCLUSIVELY from what the lockfile attests via
719
+ # ``deployed_files`` (+ per-file ``deployed_file_hashes``).
720
+ # ``apm_modules`` is an unattested cache -- it carries no integrity
721
+ # or provenance guarantee, so no bytes from it may reach the bundle.
722
+ install_path = _dep_install_path(dep, apm_modules_dir)
723
+ if dep.deployed_files:
724
+ dep_components = _collect_deployed_components(project_root, dep)
725
+ if dep.skill_subset and not dep_components:
726
+ declared_skills = ", ".join(dep.skill_subset)
727
+ raise ValueError(
728
+ f"Cannot pack dependency {dep.repo_url}: the skills "
729
+ f"recorded in apm.lock.yaml (skill_subset: {declared_skills}) "
730
+ "were not found among its installed files. Run 'apm install' "
731
+ "to re-deploy the expected skills, then pack again."
732
+ )
733
+ elif _cache_would_contribute_primitives(install_path, dep):
734
+ # Unattested primitives sit in the cache but the lockfile
735
+ # recorded none of them: a stale or partial install. Refuse
736
+ # to pack the cache -- fail loudly with a fix.
737
+ raise ValueError(
738
+ f"Cannot pack dependency {dep.repo_url}: the lockfile records "
739
+ "no deployed files for it, but installed content that cannot "
740
+ "be verified exists in the apm_modules cache (a stale or "
741
+ "partial install). Run 'apm install' to record provenance in "
742
+ "apm.lock.yaml, then pack again."
743
+ )
744
+ else:
745
+ # No attested content and nothing packable in the cache: the
746
+ # dependency contributes no plugin primitives (e.g. an
747
+ # MCP-only or hooks-config-only package). Skip it cleanly.
748
+ dep_components = []
749
+
750
+ # Transition warning (#2013): dependency hooks/MCP *config* lives in
751
+ # the unattested cache and is never packed. Name the dependency so
752
+ # an author who relied on it merging into shared settings is not
753
+ # surprised by the silent exclusion. Attested primitives are packed
754
+ # regardless of this warning.
755
+ if _cache_would_contribute_hooks_or_mcp(install_path):
756
+ _warn = (
757
+ f"dependency {dep.repo_url} contributed hooks/MCP config that "
758
+ "is not attested in apm.lock.yaml; it will NOT be packed. "
759
+ "Attested primitives (skills/agents/etc.) are unaffected."
760
+ )
761
+ if logger:
762
+ logger.warning(_warn)
763
+ else:
764
+ _rich_warning(_warn, symbol="warning")
518
765
 
519
766
  _merge_file_map(file_map, dep_components, dep_name, force, collisions)
520
767
 
521
- # Hooks -- deps merge (first wins among deps)
522
- dep_hooks = _collect_hooks_from_apm(dep_apm_dir)
523
- dep_hooks_root = _collect_hooks_from_root(install_path)
524
- _deep_merge(dep_hooks, dep_hooks_root, overwrite=False)
525
- _deep_merge(merged_hooks, dep_hooks, overwrite=False)
526
-
527
- # MCP -- deps merge (first wins among deps)
528
- dep_mcp = _collect_mcp(install_path)
529
- _deep_merge(merged_mcp, dep_mcp, overwrite=False)
530
-
531
768
  # 6. Collect own components (.apm/ and root-level)
532
769
  own_apm_dir = project_root / ".apm"
533
770
  own_components = _collect_apm_components(own_apm_dir)
@@ -535,7 +535,12 @@ class GitCache:
535
535
  subprocess_env = env if env is not None else git_subprocess_env()
536
536
 
537
537
  try:
538
- # Clone from local bare repo (fast, no network)
538
+ # Clone from local bare repo (fast, no network).
539
+ # ``promisor`` and ``partialclonefilter`` ride on the clone
540
+ # via ``-c key=val`` (one spawn). ``remote.origin.url``
541
+ # needs a separate post-clone ``git config`` because git
542
+ # clone always rewrites it to the clone source after
543
+ # applying ``-c`` overrides.
539
544
  subprocess.run(
540
545
  [
541
546
  git_exe,
@@ -545,6 +550,16 @@ class GitCache:
545
550
  "--shared",
546
551
  "--no-checkout",
547
552
  "--no-recurse-submodules",
553
+ *(
554
+ [
555
+ "-c",
556
+ "remote.origin.promisor=true",
557
+ "-c",
558
+ "remote.origin.partialclonefilter=blob:none",
559
+ ]
560
+ if promisor_url
561
+ else []
562
+ ),
548
563
  str(bare_dir),
549
564
  str(staged),
550
565
  ],
@@ -555,34 +570,25 @@ class GitCache:
555
570
  check=True,
556
571
  )
557
572
  if promisor_url:
558
- # Configure consumer as a promisor pointing at the
559
- # real upstream URL so missing blobs (the partial
560
- # bare only carries trees) are lazy-fetched during
561
- # checkout. Without this, ``git checkout`` would
562
- # fail with "fatal: unable to read tree/blob" for
563
- # any object missing from the local alternates.
564
- # The fetch goes to ``promisor_url`` directly; auth
565
- # comes from the inherited subprocess_env.
566
- for cfg_args in (
567
- ["remote.origin.url", promisor_url],
568
- ["remote.origin.promisor", "true"],
569
- ["remote.origin.partialclonefilter", "blob:none"],
570
- ):
571
- subprocess.run(
572
- [
573
- git_exe,
574
- *_safe_git_args(),
575
- "-C",
576
- str(staged),
577
- "config",
578
- *cfg_args,
579
- ],
580
- capture_output=True,
581
- text=True,
582
- timeout=10,
583
- env=subprocess_env,
584
- check=True,
585
- )
573
+ # Point origin at the real upstream (clone set it to the
574
+ # local bare). Single config call; the other two promisor
575
+ # keys were already applied via ``-c`` above.
576
+ subprocess.run(
577
+ [
578
+ git_exe,
579
+ *_safe_git_args(),
580
+ "-C",
581
+ str(staged),
582
+ "config",
583
+ "remote.origin.url",
584
+ promisor_url,
585
+ ],
586
+ capture_output=True,
587
+ text=True,
588
+ timeout=10,
589
+ env=subprocess_env,
590
+ check=True,
591
+ )
586
592
  if sparse_paths:
587
593
  # Sparse-cone setup BEFORE checkout. Failures raise
588
594
  # (not silently fallen back to full checkout) because
@@ -1,9 +1,7 @@
1
- """APM audit command -- content integrity scanning for prompt files.
1
+ """APM audit command -- content integrity scanning for installed primitives.
2
2
 
3
- Scans installed APM packages (or arbitrary files) for hidden Unicode
4
- characters that could embed invisible instructions. This is the first
5
- pillar of ``apm audit``; lock-file consistency (``--ci``) and drift
6
- detection (``--drift``) are planned as future modes.
3
+ Scans installed APM primitives (or arbitrary files) for hidden Unicode
4
+ characters, drift, and lockfile/policy violations.
7
5
 
8
6
  Exit codes:
9
7
  0 -- clean (no findings, or info-only)
@@ -1036,7 +1034,9 @@ def _audit_content_scan(
1036
1034
  # -- Command --------------------------------------------------------
1037
1035
 
1038
1036
 
1039
- @click.command(help="Scan installed packages for hidden Unicode characters")
1037
+ @click.command(
1038
+ help="Scan installed primitives for hidden Unicode, drift, and lockfile/policy violations"
1039
+ )
1040
1040
  @click.argument("package", required=False)
1041
1041
  @click.option(
1042
1042
  "--file",
@@ -250,6 +250,11 @@ def _resolve_compile_target(target):
250
250
  if not has_non_vscode_agents:
251
251
  return "vscode"
252
252
  return frozenset(families)
253
+ if families == {"agents"} and "antigravity" in target_set and len(target_set) > 1:
254
+ # Mixed Antigravity + AGENTS.md-only consumers share AGENTS.md but
255
+ # do not all read .agents/rules/. Preserve mixed-target context so
256
+ # downstream dedup stays disabled for AGENTS.md-only consumers.
257
+ return frozenset({"agents"})
253
258
  if "claude" in families:
254
259
  return "claude"
255
260
  if "gemini" in families:
@@ -957,9 +962,10 @@ def _run_compilation(
957
962
  help=(
958
963
  "Include the instructions section in CLAUDE.md even when .claude/rules/ is "
959
964
  "already populated, and in AGENTS.md even when .github/instructions/ is "
960
- "already populated. Overrides the default deduplication that normally omits "
961
- "these sections to avoid duplicate context. Affects both the Claude and "
962
- "Copilot (AGENTS.md) deduplication paths. Alias: --no-dedup."
965
+ "already populated, or .agents/rules/ for Antigravity. Overrides the "
966
+ "default deduplication that normally omits these sections to avoid "
967
+ "duplicate context. Affects the Claude, Copilot, and Antigravity "
968
+ "deduplication paths. Alias: --no-dedup."
963
969
  ),
964
970
  )
965
971
  @click.option(