apm-cli 0.12.1__tar.gz → 0.12.2__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 (299) hide show
  1. {apm_cli-0.12.1/src/apm_cli.egg-info → apm_cli-0.12.2}/PKG-INFO +2 -1
  2. {apm_cli-0.12.1 → apm_cli-0.12.2}/README.md +1 -0
  3. {apm_cli-0.12.1 → apm_cli-0.12.2}/pyproject.toml +1 -1
  4. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/commands/audit.py +144 -17
  5. apm_cli-0.12.2/src/apm_cli/deps/bare_cache.py +545 -0
  6. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/deps/github_downloader.py +190 -155
  7. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/deps/shared_clone_cache.py +29 -4
  8. apm_cli-0.12.2/src/apm_cli/install/cache_pin.py +233 -0
  9. apm_cli-0.12.2/src/apm_cli/install/drift.py +731 -0
  10. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/install/phases/lockfile.py +57 -0
  11. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/install/services.py +18 -0
  12. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/policy/ci_checks.py +94 -1
  13. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/utils/content_hash.py +11 -0
  14. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/utils/diagnostics.py +73 -0
  15. apm_cli-0.12.2/src/apm_cli/utils/guards.py +123 -0
  16. apm_cli-0.12.2/src/apm_cli/utils/normalization.py +57 -0
  17. {apm_cli-0.12.1 → apm_cli-0.12.2/src/apm_cli.egg-info}/PKG-INFO +2 -1
  18. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli.egg-info/SOURCES.txt +5 -0
  19. {apm_cli-0.12.1 → apm_cli-0.12.2}/AUTHORS +0 -0
  20. {apm_cli-0.12.1 → apm_cli-0.12.2}/LICENSE +0 -0
  21. {apm_cli-0.12.1 → apm_cli-0.12.2}/NOTICE +0 -0
  22. {apm_cli-0.12.1 → apm_cli-0.12.2}/setup.cfg +0 -0
  23. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/__init__.py +0 -0
  24. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/adapters/__init__.py +0 -0
  25. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/adapters/client/__init__.py +0 -0
  26. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/adapters/client/base.py +0 -0
  27. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/adapters/client/claude.py +0 -0
  28. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/adapters/client/codex.py +0 -0
  29. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/adapters/client/copilot.py +0 -0
  30. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/adapters/client/cursor.py +0 -0
  31. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/adapters/client/gemini.py +0 -0
  32. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/adapters/client/opencode.py +0 -0
  33. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/adapters/client/vscode.py +0 -0
  34. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/adapters/client/windsurf.py +0 -0
  35. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/adapters/package_manager/__init__.py +0 -0
  36. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/adapters/package_manager/base.py +0 -0
  37. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/adapters/package_manager/default_manager.py +0 -0
  38. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/bundle/__init__.py +0 -0
  39. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/bundle/local_bundle.py +0 -0
  40. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/bundle/lockfile_enrichment.py +0 -0
  41. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/bundle/packer.py +0 -0
  42. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/bundle/plugin_exporter.py +0 -0
  43. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/bundle/unpacker.py +0 -0
  44. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/cache/__init__.py +0 -0
  45. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/cache/git_cache.py +0 -0
  46. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/cache/http_cache.py +0 -0
  47. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/cache/integrity.py +0 -0
  48. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/cache/locking.py +0 -0
  49. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/cache/paths.py +0 -0
  50. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/cache/url_normalize.py +0 -0
  51. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/cli.py +0 -0
  52. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/commands/__init__.py +0 -0
  53. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/commands/_apm_yml_writer.py +0 -0
  54. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/commands/_helpers.py +0 -0
  55. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/commands/cache.py +0 -0
  56. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/commands/compile/__init__.py +0 -0
  57. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/commands/compile/cli.py +0 -0
  58. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/commands/compile/watcher.py +0 -0
  59. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/commands/config.py +0 -0
  60. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/commands/deps/__init__.py +0 -0
  61. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/commands/deps/_utils.py +0 -0
  62. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/commands/deps/cli.py +0 -0
  63. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/commands/experimental.py +0 -0
  64. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/commands/init.py +0 -0
  65. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/commands/install.py +0 -0
  66. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/commands/list_cmd.py +0 -0
  67. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/commands/marketplace/__init__.py +0 -0
  68. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/commands/marketplace/check.py +0 -0
  69. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/commands/marketplace/doctor.py +0 -0
  70. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/commands/marketplace/init.py +0 -0
  71. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/commands/marketplace/migrate.py +0 -0
  72. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/commands/marketplace/outdated.py +0 -0
  73. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/commands/marketplace/plugin/__init__.py +0 -0
  74. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/commands/marketplace/plugin/add.py +0 -0
  75. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/commands/marketplace/plugin/remove.py +0 -0
  76. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/commands/marketplace/plugin/set.py +0 -0
  77. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/commands/marketplace/publish.py +0 -0
  78. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/commands/marketplace/validate.py +0 -0
  79. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/commands/mcp.py +0 -0
  80. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/commands/outdated.py +0 -0
  81. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/commands/pack.py +0 -0
  82. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/commands/policy.py +0 -0
  83. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/commands/prune.py +0 -0
  84. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/commands/run.py +0 -0
  85. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/commands/runtime.py +0 -0
  86. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/commands/uninstall/__init__.py +0 -0
  87. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/commands/uninstall/cli.py +0 -0
  88. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/commands/uninstall/engine.py +0 -0
  89. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/commands/update.py +0 -0
  90. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/commands/view.py +0 -0
  91. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/compilation/__init__.py +0 -0
  92. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/compilation/agents_compiler.py +0 -0
  93. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/compilation/build_id.py +0 -0
  94. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/compilation/claude_formatter.py +0 -0
  95. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/compilation/constants.py +0 -0
  96. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/compilation/constitution.py +0 -0
  97. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/compilation/constitution_block.py +0 -0
  98. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/compilation/context_optimizer.py +0 -0
  99. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/compilation/distributed_compiler.py +0 -0
  100. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/compilation/gemini_formatter.py +0 -0
  101. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/compilation/injector.py +0 -0
  102. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/compilation/link_resolver.py +0 -0
  103. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/compilation/output_writer.py +0 -0
  104. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/compilation/template_builder.py +0 -0
  105. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/config.py +0 -0
  106. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/constants.py +0 -0
  107. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/core/__init__.py +0 -0
  108. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/core/auth.py +0 -0
  109. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/core/azure_cli.py +0 -0
  110. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/core/build_orchestrator.py +0 -0
  111. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/core/command_logger.py +0 -0
  112. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/core/conflict_detector.py +0 -0
  113. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/core/docker_args.py +0 -0
  114. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/core/experimental.py +0 -0
  115. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/core/null_logger.py +0 -0
  116. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/core/operations.py +0 -0
  117. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/core/safe_installer.py +0 -0
  118. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/core/scope.py +0 -0
  119. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/core/script_runner.py +0 -0
  120. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/core/target_detection.py +0 -0
  121. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/core/token_manager.py +0 -0
  122. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/deps/__init__.py +0 -0
  123. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/deps/aggregator.py +0 -0
  124. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/deps/apm_resolver.py +0 -0
  125. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/deps/artifactory_entry.py +0 -0
  126. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/deps/dependency_graph.py +0 -0
  127. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/deps/download_strategies.py +0 -0
  128. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/deps/git_remote_ops.py +0 -0
  129. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/deps/github_downloader_validation.py +0 -0
  130. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/deps/installed_package.py +0 -0
  131. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/deps/lockfile.py +0 -0
  132. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/deps/package_validator.py +0 -0
  133. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/deps/plugin_parser.py +0 -0
  134. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/deps/registry_proxy.py +0 -0
  135. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/deps/transport_selection.py +0 -0
  136. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/deps/verifier.py +0 -0
  137. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/drift.py +0 -0
  138. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/factory.py +0 -0
  139. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/install/__init__.py +0 -0
  140. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/install/context.py +0 -0
  141. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/install/errors.py +0 -0
  142. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/install/helpers/__init__.py +0 -0
  143. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/install/helpers/security_scan.py +0 -0
  144. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/install/insecure_policy.py +0 -0
  145. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/install/local_bundle_handler.py +0 -0
  146. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/install/mcp/__init__.py +0 -0
  147. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/install/mcp/args.py +0 -0
  148. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/install/mcp/command.py +0 -0
  149. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/install/mcp/conflicts.py +0 -0
  150. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/install/mcp/entry.py +0 -0
  151. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/install/mcp/registry.py +0 -0
  152. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/install/mcp/warnings.py +0 -0
  153. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/install/mcp/writer.py +0 -0
  154. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/install/phases/__init__.py +0 -0
  155. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/install/phases/cleanup.py +0 -0
  156. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/install/phases/download.py +0 -0
  157. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/install/phases/finalize.py +0 -0
  158. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/install/phases/integrate.py +0 -0
  159. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/install/phases/local_content.py +0 -0
  160. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/install/phases/policy_gate.py +0 -0
  161. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/install/phases/policy_target_check.py +0 -0
  162. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/install/phases/post_deps_local.py +0 -0
  163. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/install/phases/resolve.py +0 -0
  164. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/install/phases/targets.py +0 -0
  165. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/install/pipeline.py +0 -0
  166. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/install/presentation/__init__.py +0 -0
  167. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/install/presentation/dry_run.py +0 -0
  168. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/install/request.py +0 -0
  169. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/install/service.py +0 -0
  170. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/install/skill_path_migration.py +0 -0
  171. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/install/sources.py +0 -0
  172. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/install/summary.py +0 -0
  173. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/install/template.py +0 -0
  174. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/install/validation.py +0 -0
  175. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/integration/__init__.py +0 -0
  176. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/integration/agent_integrator.py +0 -0
  177. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/integration/base_integrator.py +0 -0
  178. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/integration/cleanup.py +0 -0
  179. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/integration/command_integrator.py +0 -0
  180. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/integration/copilot_cowork_paths.py +0 -0
  181. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/integration/coverage.py +0 -0
  182. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/integration/dispatch.py +0 -0
  183. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/integration/hook_integrator.py +0 -0
  184. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/integration/instruction_integrator.py +0 -0
  185. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/integration/mcp_integrator.py +0 -0
  186. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/integration/prompt_integrator.py +0 -0
  187. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/integration/skill_integrator.py +0 -0
  188. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/integration/skill_transformer.py +0 -0
  189. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/integration/targets.py +0 -0
  190. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/integration/utils.py +0 -0
  191. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/marketplace/__init__.py +0 -0
  192. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/marketplace/_git_utils.py +0 -0
  193. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/marketplace/_io.py +0 -0
  194. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/marketplace/builder.py +0 -0
  195. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/marketplace/client.py +0 -0
  196. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/marketplace/errors.py +0 -0
  197. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/marketplace/git_stderr.py +0 -0
  198. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/marketplace/init_template.py +0 -0
  199. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/marketplace/migration.py +0 -0
  200. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/marketplace/models.py +0 -0
  201. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/marketplace/pr_integration.py +0 -0
  202. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/marketplace/publisher.py +0 -0
  203. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/marketplace/ref_resolver.py +0 -0
  204. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/marketplace/registry.py +0 -0
  205. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/marketplace/resolver.py +0 -0
  206. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/marketplace/semver.py +0 -0
  207. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/marketplace/shadow_detector.py +0 -0
  208. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/marketplace/tag_pattern.py +0 -0
  209. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/marketplace/validator.py +0 -0
  210. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/marketplace/version_pins.py +0 -0
  211. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/marketplace/yml_editor.py +0 -0
  212. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/marketplace/yml_schema.py +0 -0
  213. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/models/__init__.py +0 -0
  214. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/models/apm_package.py +0 -0
  215. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/models/dependency/__init__.py +0 -0
  216. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/models/dependency/mcp.py +0 -0
  217. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/models/dependency/reference.py +0 -0
  218. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/models/dependency/types.py +0 -0
  219. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/models/plugin.py +0 -0
  220. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/models/results.py +0 -0
  221. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/models/validation.py +0 -0
  222. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/output/__init__.py +0 -0
  223. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/output/formatters.py +0 -0
  224. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/output/models.py +0 -0
  225. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/output/script_formatters.py +0 -0
  226. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/policy/__init__.py +0 -0
  227. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/policy/_help_text.py +0 -0
  228. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/policy/discovery.py +0 -0
  229. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/policy/inheritance.py +0 -0
  230. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/policy/install_preflight.py +0 -0
  231. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/policy/matcher.py +0 -0
  232. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/policy/models.py +0 -0
  233. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/policy/outcome_routing.py +0 -0
  234. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/policy/parser.py +0 -0
  235. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/policy/policy_checks.py +0 -0
  236. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/policy/project_config.py +0 -0
  237. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/policy/schema.py +0 -0
  238. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/primitives/__init__.py +0 -0
  239. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/primitives/discovery.py +0 -0
  240. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/primitives/models.py +0 -0
  241. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/primitives/parser.py +0 -0
  242. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/registry/__init__.py +0 -0
  243. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/registry/client.py +0 -0
  244. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/registry/integration.py +0 -0
  245. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/registry/operations.py +0 -0
  246. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/runtime/__init__.py +0 -0
  247. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/runtime/base.py +0 -0
  248. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/runtime/codex_runtime.py +0 -0
  249. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/runtime/copilot_runtime.py +0 -0
  250. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/runtime/factory.py +0 -0
  251. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/runtime/llm_runtime.py +0 -0
  252. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/runtime/manager.py +0 -0
  253. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/security/__init__.py +0 -0
  254. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/security/audit_report.py +0 -0
  255. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/security/content_scanner.py +0 -0
  256. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/security/file_scanner.py +0 -0
  257. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/security/gate.py +0 -0
  258. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/update_policy.py +0 -0
  259. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/utils/__init__.py +0 -0
  260. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/utils/atomic_io.py +0 -0
  261. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/utils/console.py +0 -0
  262. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/utils/exclude.py +0 -0
  263. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/utils/file_ops.py +0 -0
  264. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/utils/git_env.py +0 -0
  265. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/utils/github_host.py +0 -0
  266. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/utils/helpers.py +0 -0
  267. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/utils/install_tui.py +0 -0
  268. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/utils/path_security.py +0 -0
  269. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/utils/paths.py +0 -0
  270. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/utils/reflink.py +0 -0
  271. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/utils/short_sha.py +0 -0
  272. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/utils/subprocess_env.py +0 -0
  273. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/utils/version_checker.py +0 -0
  274. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/utils/yaml_io.py +0 -0
  275. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/version.py +0 -0
  276. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/workflow/__init__.py +0 -0
  277. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/workflow/discovery.py +0 -0
  278. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/workflow/parser.py +0 -0
  279. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli/workflow/runner.py +0 -0
  280. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli.egg-info/dependency_links.txt +0 -0
  281. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli.egg-info/entry_points.txt +0 -0
  282. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli.egg-info/requires.txt +0 -0
  283. {apm_cli-0.12.1 → apm_cli-0.12.2}/src/apm_cli.egg-info/top_level.txt +0 -0
  284. {apm_cli-0.12.1 → apm_cli-0.12.2}/tests/test_apm_package_models.py +0 -0
  285. {apm_cli-0.12.1 → apm_cli-0.12.2}/tests/test_apm_resolver.py +0 -0
  286. {apm_cli-0.12.1 → apm_cli-0.12.2}/tests/test_codex_docker_args_fix.py +0 -0
  287. {apm_cli-0.12.1 → apm_cli-0.12.2}/tests/test_codex_empty_string_and_defaults.py +0 -0
  288. {apm_cli-0.12.1 → apm_cli-0.12.2}/tests/test_collision_integration.py +0 -0
  289. {apm_cli-0.12.1 → apm_cli-0.12.2}/tests/test_console.py +0 -0
  290. {apm_cli-0.12.1 → apm_cli-0.12.2}/tests/test_distributed_compilation.py +0 -0
  291. {apm_cli-0.12.1 → apm_cli-0.12.2}/tests/test_empty_string_and_defaults.py +0 -0
  292. {apm_cli-0.12.1 → apm_cli-0.12.2}/tests/test_enhanced_discovery.py +0 -0
  293. {apm_cli-0.12.1 → apm_cli-0.12.2}/tests/test_github_downloader.py +0 -0
  294. {apm_cli-0.12.1 → apm_cli-0.12.2}/tests/test_github_downloader_token_precedence.py +0 -0
  295. {apm_cli-0.12.1 → apm_cli-0.12.2}/tests/test_lockfile.py +0 -0
  296. {apm_cli-0.12.1 → apm_cli-0.12.2}/tests/test_runnable_prompts.py +0 -0
  297. {apm_cli-0.12.1 → apm_cli-0.12.2}/tests/test_runtime_manager_token_precedence.py +0 -0
  298. {apm_cli-0.12.1 → apm_cli-0.12.2}/tests/test_token_manager.py +0 -0
  299. {apm_cli-0.12.1 → apm_cli-0.12.2}/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.12.1
3
+ Version: 0.12.2
4
4
  Summary: MCP configuration tool
5
5
  Author-email: Daniel Meppiel <user@example.com>
6
6
  License: MIT License
@@ -146,6 +146,7 @@ Agent context is executable in effect — a prompt is a program for an LLM. APM
146
146
 
147
147
  - **[Content security](https://microsoft.github.io/apm/enterprise/security/)** — `apm install` blocks compromised packages before agents read them; `apm audit` runs the same checks on demand
148
148
  - **[Lockfile integrity](https://microsoft.github.io/apm/enterprise/governance/)** — `apm.lock` records resolved sources and content hashes for full provenance
149
+ - **[Drift detection](https://microsoft.github.io/apm/guides/drift-detection/)** — `apm audit` rebuilds your agent context in scratch and diffs it against your working tree to catch hand-edits before they ship
149
150
  - **[MCP trust boundaries](https://microsoft.github.io/apm/guides/mcp-servers/)** — transitive MCP servers require explicit consent
150
151
 
151
152
  ### 3. Governed by policy
@@ -81,6 +81,7 @@ Agent context is executable in effect — a prompt is a program for an LLM. APM
81
81
 
82
82
  - **[Content security](https://microsoft.github.io/apm/enterprise/security/)** — `apm install` blocks compromised packages before agents read them; `apm audit` runs the same checks on demand
83
83
  - **[Lockfile integrity](https://microsoft.github.io/apm/enterprise/governance/)** — `apm.lock` records resolved sources and content hashes for full provenance
84
+ - **[Drift detection](https://microsoft.github.io/apm/guides/drift-detection/)** — `apm audit` rebuilds your agent context in scratch and diffs it against your working tree to catch hand-edits before they ship
84
85
  - **[MCP trust boundaries](https://microsoft.github.io/apm/guides/mcp-servers/)** — transitive MCP servers require explicit consent
85
86
 
86
87
  ### 3. Governed by policy
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "apm-cli"
7
- version = "0.12.1"
7
+ version = "0.12.2"
8
8
  description = "MCP configuration tool"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.10"
@@ -19,7 +19,7 @@ from typing import Dict, List, Optional, Tuple # noqa: F401, UP035
19
19
  import click
20
20
 
21
21
  from ..core.command_logger import CommandLogger
22
- from ..deps.lockfile import LockFile, get_lockfile_path # noqa: F401
22
+ from ..deps.lockfile import LockFile, get_lockfile_path
23
23
  from ..policy._help_text import POLICY_SOURCE_FORMS_HELP
24
24
  from ..security.content_scanner import ContentScanner, ScanFinding
25
25
  from ..security.file_scanner import scan_lockfile_packages
@@ -398,16 +398,17 @@ def _audit_ci_gate(
398
398
  no_cache: bool,
399
399
  no_policy: bool,
400
400
  no_fail_fast: bool,
401
+ no_drift: bool = False,
401
402
  ) -> None:
402
403
  """Handle ``apm audit --ci`` -- lockfile consistency gate.
403
404
 
404
- Runs baseline lockfile checks and (optionally) org-policy checks,
405
- then emits a structured report and exits with 0 (clean) or 1
406
- (violations).
405
+ Runs baseline lockfile checks, drift detection (unless ``--no-drift``),
406
+ and (optionally) org-policy checks, then emits a structured report
407
+ and exits with 0 (clean) or 1 (violations).
407
408
  """
408
409
  logger = cfg.logger
409
410
 
410
- from ..policy.ci_checks import run_baseline_checks
411
+ from ..policy.ci_checks import _check_drift, run_baseline_checks
411
412
  from ..policy.policy_checks import run_policy_checks
412
413
 
413
414
  fail_fast = not no_fail_fast
@@ -484,6 +485,31 @@ def _audit_ci_gate(
484
485
  )
485
486
  )
486
487
 
488
+ # -- Drift detection (default-on per ADR-02) --------------------
489
+ drift_findings: list = []
490
+ if not no_drift and (cfg.project_root / "apm.yml").exists():
491
+ from ..deps.lockfile import LockFile, get_lockfile_path
492
+
493
+ lockfile_path = get_lockfile_path(cfg.project_root)
494
+ if lockfile_path.exists():
495
+ lockfile = LockFile.read(lockfile_path)
496
+ if lockfile is not None:
497
+ drift_check, drift_findings = _check_drift(
498
+ cfg.project_root,
499
+ lockfile,
500
+ cache_only=True,
501
+ verbose=cfg.verbose,
502
+ )
503
+ ci_result.checks.append(drift_check)
504
+ elif no_drift and cfg.output_format == "text":
505
+ # In structured output (json/sarif), --no-drift is implicit from
506
+ # the absence of the drift check entry; no need to pollute output.
507
+ click.echo(
508
+ f"{STATUS_SYMBOLS['warning']} drift detection skipped (--no-drift); "
509
+ "coverage reduced -- hand-edits and missing integrations will not be caught",
510
+ err=True,
511
+ )
512
+
487
513
  # Resolve effective format
488
514
  effective_format = cfg.output_format
489
515
  if cfg.output_path and effective_format == "text":
@@ -494,7 +520,17 @@ def _audit_ci_gate(
494
520
  if effective_format in ("json", "sarif"):
495
521
  import json as _json
496
522
 
497
- payload = ci_result.to_sarif() if effective_format == "sarif" else ci_result.to_json()
523
+ from ..install.drift import render_drift_json, render_drift_sarif
524
+
525
+ if effective_format == "sarif":
526
+ payload = ci_result.to_sarif()
527
+ if drift_findings:
528
+ payload["runs"][0]["results"].extend(render_drift_sarif(drift_findings))
529
+ else:
530
+ payload = ci_result.to_json()
531
+ if drift_findings or not no_drift:
532
+ payload["drift"] = render_drift_json(drift_findings)
533
+
498
534
  output = _json.dumps(payload, indent=2)
499
535
  if cfg.output_path:
500
536
  Path(cfg.output_path).parent.mkdir(parents=True, exist_ok=True)
@@ -504,6 +540,11 @@ def _audit_ci_gate(
504
540
  click.echo(output)
505
541
  else:
506
542
  _render_ci_results(ci_result)
543
+ if drift_findings:
544
+ from ..install.drift import render_drift_text
545
+
546
+ click.echo("")
547
+ click.echo(render_drift_text(drift_findings, verbose=cfg.verbose))
507
548
 
508
549
  sys.exit(0 if ci_result.passed else 1)
509
550
 
@@ -514,6 +555,7 @@ def _audit_content_scan(
514
555
  file_path: str | None,
515
556
  strip: bool,
516
557
  dry_run: bool,
558
+ no_drift: bool = False,
517
559
  ) -> None:
518
560
  """Handle default ``apm audit`` -- content integrity scanning.
519
561
 
@@ -585,6 +627,54 @@ def _audit_content_scan(
585
627
  logger.progress("Nothing to clean -- no strippable characters found")
586
628
  sys.exit(0)
587
629
 
630
+ # -- Drift detection (default-on per ADR-02) --------------------
631
+ # Drift only applies to whole-project audit (not --file or --strip
632
+ # modes; not single-package scoped). Mutex on no_drift+strip/file
633
+ # is enforced earlier via UsageError.
634
+ drift_findings: list = []
635
+ drift_failed = False
636
+ if (
637
+ not no_drift
638
+ and not strip
639
+ and not file_path
640
+ and not package
641
+ and (project_root / "apm.yml").exists()
642
+ ):
643
+ from ..policy.ci_checks import _check_drift
644
+
645
+ lockfile_path = get_lockfile_path(project_root)
646
+ if lockfile_path.exists():
647
+ lockfile = LockFile.read(lockfile_path)
648
+ if lockfile is not None:
649
+ drift_check, drift_findings = _check_drift(
650
+ project_root,
651
+ lockfile,
652
+ cache_only=True,
653
+ verbose=cfg.verbose,
654
+ )
655
+ drift_failed = not drift_check.passed
656
+ # Bare `apm audit` is advisory: drift_failed does not gate
657
+ # the exit code (that lives in --ci). But silence on a
658
+ # cache-pin / cache-miss failure is a UX trap: the user
659
+ # cannot tell whether drift was clean or whether it was
660
+ # never attempted. Surface the failure reason on stderr
661
+ # whenever the drift check failed without producing
662
+ # findings (CacheMissError, CachePinError, missing lockfile).
663
+ if drift_failed and not drift_findings:
664
+ click.echo(
665
+ f"{STATUS_SYMBOLS['warning']} drift check could not run: "
666
+ f"{drift_check.message}",
667
+ err=True,
668
+ )
669
+ elif no_drift and cfg.output_format == "text":
670
+ # In structured output (json/sarif), --no-drift is implicit from
671
+ # the absence of the drift check entry; no need to pollute output.
672
+ click.echo(
673
+ f"{STATUS_SYMBOLS['warning']} drift detection skipped (--no-drift); "
674
+ "coverage reduced -- hand-edits and missing integrations will not be caught",
675
+ err=True,
676
+ )
677
+
588
678
  # -- Display findings --
589
679
  # Determine exit code first (shared by all formats)
590
680
  if not findings_by_file or not _has_actionable_findings(findings_by_file):
@@ -593,6 +683,11 @@ def _audit_content_scan(
593
683
  all_findings = [f for ff in findings_by_file.values() for f in ff]
594
684
  exit_code = 1 if ContentScanner.has_critical(all_findings) else 2
595
685
 
686
+ # Note: bare `apm audit` is advisory for drift; drift findings are
687
+ # rendered (text/json/sarif) but DO NOT escalate the exit code. Use
688
+ # `apm audit --ci` (handled in _audit_ci_gate) to gate on drift.
689
+ _ = drift_failed # retained for symmetry; gate path lives in --ci.
690
+
596
691
  if effective_format == "text":
597
692
  if cfg.output_path:
598
693
  logger.error(
@@ -603,6 +698,11 @@ def _audit_content_scan(
603
698
  if findings_by_file:
604
699
  _render_findings_table(findings_by_file, verbose=cfg.verbose)
605
700
  _render_summary(findings_by_file, files_scanned, logger)
701
+ if drift_findings:
702
+ from ..install.drift import render_drift_text
703
+
704
+ click.echo("")
705
+ click.echo(render_drift_text(drift_findings, verbose=cfg.verbose))
606
706
  elif effective_format == "markdown":
607
707
  from ..security.audit_report import findings_to_markdown
608
708
 
@@ -717,6 +817,15 @@ def _audit_content_scan(
717
817
  is_flag=True,
718
818
  help="Run all checks even after a failure (default: stop at first failure).",
719
819
  )
820
+ @click.option(
821
+ "--no-drift",
822
+ "no_drift",
823
+ is_flag=True,
824
+ help=(
825
+ "Skip the install-replay drift check. Reduces coverage; "
826
+ "use only for performance-constrained CI loops."
827
+ ),
828
+ )
720
829
  @click.pass_context
721
830
  def audit(
722
831
  ctx,
@@ -732,6 +841,7 @@ def audit(
732
841
  no_cache,
733
842
  no_policy,
734
843
  no_fail_fast,
844
+ no_drift,
735
845
  ):
736
846
  """Scan deployed prompt files for hidden Unicode characters.
737
847
 
@@ -739,23 +849,31 @@ def audit(
739
849
  prompt, instruction, and rules files. Dangerous and suspicious
740
850
  characters can be removed with --strip.
741
851
 
742
- With --ci, runs lockfile consistency checks instead of content scanning.
743
- This validates that the on-disk state matches what the lockfile declares,
744
- suitable for CI/CD pipeline gates.
852
+ By default, also runs install-replay drift detection: catches
853
+ hand-edits to deployed files, missing integrations, and orphaned
854
+ files vs the lockfile. Use --no-drift to skip (reduces coverage).
855
+
856
+ With --ci, runs lockfile consistency checks AND drift in machine-
857
+ readable format, suitable for CI/CD pipeline gates.
745
858
 
746
859
  \b
747
860
  Exit codes:
748
- 0 Clean, info-only findings, or successful strip
749
- 1 Critical findings detected (or --ci with violations)
750
- 2 Warning-only findings (suspicious but not critical)
861
+ 0 Clean, info-only findings, or drift-only (advisory) in bare
862
+ audit, or successful strip
863
+ 1 Critical findings detected, or --ci with violations
864
+ (including drift in --ci mode)
865
+ 2 Warning-only findings (suspicious but not critical), or
866
+ usage error (mutually exclusive flags)
751
867
 
752
868
  \b
753
869
  Examples:
754
- apm audit # Scan all installed packages
870
+ apm audit # Scan + drift (all checks)
755
871
  apm audit my-package # Scan a specific package
756
- apm audit --file .cursorrules # Scan any file
872
+ apm audit --file .cursorrules # Scan any file (no drift)
757
873
  apm audit --strip # Remove dangerous/suspicious chars
758
- apm audit --ci # Lockfile consistency gate
874
+ apm audit --no-drift # Skip drift only (escape hatch)
875
+ apm audit --ci # CI gate (lockfile + drift)
876
+ apm audit --ci --no-drift # CI gate without drift (rare)
759
877
  apm audit --ci --policy org # CI gate with org policy checks
760
878
  apm audit --ci -f json # JSON CI report
761
879
  apm audit --ci -f sarif # SARIF for GitHub Code Scanning
@@ -772,6 +890,15 @@ def audit(
772
890
  output_path=output_path,
773
891
  )
774
892
 
893
+ # --no-drift is a different audit mode from --strip / --file (those
894
+ # are content-scanning operations unrelated to integration drift).
895
+ # Click-native UsageError gives exit code 2 with "Usage:" prefix.
896
+ if no_drift and (strip or file_path):
897
+ raise click.UsageError(
898
+ "--no-drift cannot be combined with --strip or --file "
899
+ "(those modes do not run drift detection)"
900
+ )
901
+
775
902
  # -- CI mode: lockfile consistency gate -------------------------
776
903
  if ci:
777
904
  if verbose:
@@ -783,7 +910,7 @@ def audit(
783
910
  logger.error("--ci does not support --format markdown. Use json or sarif.")
784
911
  sys.exit(1)
785
912
 
786
- _audit_ci_gate(cfg, policy_source, no_cache, no_policy, no_fail_fast)
913
+ _audit_ci_gate(cfg, policy_source, no_cache, no_policy, no_fail_fast, no_drift)
787
914
  return # _audit_ci_gate calls sys.exit; return guards against fall-through
788
915
 
789
916
  # -- Content scan mode ------------------------------------------
@@ -793,4 +920,4 @@ def audit(
793
920
  "Use 'apm audit --ci --policy <source>' to run policy checks."
794
921
  )
795
922
 
796
- _audit_content_scan(cfg, package, file_path, strip, dry_run)
923
+ _audit_content_scan(cfg, package, file_path, strip, dry_run, no_drift)