apm-cli 0.25.0__tar.gz → 0.26.0__tar.gz

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