apm-cli 0.34.0__tar.gz → 0.35.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 (544) hide show
  1. {apm_cli-0.34.0/src/apm_cli.egg-info → apm_cli-0.35.0}/PKG-INFO +4 -2
  2. {apm_cli-0.34.0 → apm_cli-0.35.0}/README.md +3 -1
  3. {apm_cli-0.34.0 → apm_cli-0.35.0}/pyproject.toml +2 -2
  4. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/adapters/client/base.py +46 -3
  5. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/adapters/client/claude.py +74 -10
  6. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/adapters/client/codex.py +132 -12
  7. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/adapters/client/cursor.py +1 -14
  8. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/adapters/client/opencode.py +41 -5
  9. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/bundle/plugin_exporter.py +78 -15
  10. apm_cli-0.35.0/src/apm_cli/bundle/plugin_hooks.py +236 -0
  11. apm_cli-0.35.0/src/apm_cli/codex_plugins/__init__.py +1 -0
  12. apm_cli-0.35.0/src/apm_cli/codex_plugins/admission.py +138 -0
  13. apm_cli-0.35.0/src/apm_cli/codex_plugins/client.py +270 -0
  14. apm_cli-0.35.0/src/apm_cli/codex_plugins/manifest.py +84 -0
  15. apm_cli-0.35.0/src/apm_cli/codex_plugins/registrar.py +561 -0
  16. apm_cli-0.35.0/src/apm_cli/codex_plugins/snapshot.py +190 -0
  17. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/commands/_helpers.py +2 -45
  18. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/commands/audit.py +71 -5
  19. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/commands/deps/cli.py +26 -2
  20. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/commands/deps/why.py +8 -1
  21. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/commands/install.py +35 -65
  22. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/commands/lock.py +5 -5
  23. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/commands/outdated.py +45 -8
  24. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/commands/uninstall/cli.py +42 -13
  25. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/commands/uninstall/engine.py +108 -90
  26. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/commands/uninstall/lockfile_state.py +10 -2
  27. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/commands/update.py +3 -3
  28. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/core/command_logger.py +20 -0
  29. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/core/conflict_detector.py +8 -5
  30. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/core/deployment_ledger.py +468 -6
  31. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/core/deployment_state.py +121 -0
  32. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/core/operations.py +4 -0
  33. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/core/safe_installer.py +8 -0
  34. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/core/target_detection.py +35 -0
  35. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/deps/apm_resolver.py +152 -9
  36. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/deps/github_downloader.py +15 -74
  37. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/deps/github_downloader_validation.py +20 -7
  38. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/deps/immutable_requirements.py +17 -4
  39. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/deps/lockfile.py +238 -12
  40. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/deps/package_validator.py +3 -3
  41. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/deps/path_anchoring.py +16 -3
  42. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/deps/reachability.py +40 -5
  43. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/deps/revision_pins.py +3 -1
  44. apm_cli-0.35.0/src/apm_cli/deps/virtual_file.py +73 -0
  45. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/deps/why_walker.py +39 -88
  46. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/drift.py +94 -10
  47. apm_cli-0.35.0/src/apm_cli/entrypoint.py +34 -0
  48. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/hook_contract.py +9 -0
  49. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/install/audit_replay.py +16 -9
  50. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/install/audit_target_roots.py +52 -0
  51. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/install/context.py +9 -1
  52. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/install/deployable_source_plan.py +103 -26
  53. apm_cli-0.35.0/src/apm_cli/install/deployment_plan.py +114 -0
  54. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/install/drift.py +229 -211
  55. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/install/drift_render.py +21 -4
  56. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/install/dry_run_plan.py +117 -5
  57. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/install/errors.py +34 -1
  58. apm_cli-0.35.0/src/apm_cli/install/helpers/absence_observation.py +56 -0
  59. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/install/helpers/no_work.py +35 -9
  60. apm_cli-0.35.0/src/apm_cli/install/helpers/plan_inputs.py +28 -0
  61. apm_cli-0.35.0/src/apm_cli/install/helpers/reconciliation_scope.py +92 -0
  62. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/install/helpers/ref_reuse.py +2 -0
  63. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/install/helpers/ref_seed.py +9 -1
  64. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/install/lsp/integration.py +112 -63
  65. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/install/manifest_reconcile.py +181 -143
  66. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/install/mcp/command.py +54 -20
  67. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/install/mcp/integration.py +180 -58
  68. apm_cli-0.35.0/src/apm_cli/install/mcp/ownership.py +278 -0
  69. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/install/native_plugin_admission.py +45 -0
  70. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/install/outcome.py +4 -0
  71. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/install/package_resolution.py +62 -13
  72. apm_cli-0.35.0/src/apm_cli/install/package_selection.py +108 -0
  73. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/install/phases/cleanup.py +40 -7
  74. apm_cli-0.35.0/src/apm_cli/install/phases/codex_plugins.py +49 -0
  75. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/install/phases/integrate.py +37 -14
  76. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/install/phases/local_content.py +134 -27
  77. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/install/phases/lockfile.py +98 -7
  78. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/install/phases/resolve.py +64 -84
  79. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/install/pipeline.py +63 -76
  80. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/install/plan.py +64 -13
  81. apm_cli-0.35.0/src/apm_cli/install/presentation/__init__.py +27 -0
  82. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/install/presentation/dry_run.py +14 -4
  83. apm_cli-0.35.0/src/apm_cli/install/presentation/resolution.py +48 -0
  84. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/install/resolution_staging.py +120 -38
  85. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/install/service.py +328 -102
  86. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/install/service_integration.py +79 -0
  87. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/install/services.py +72 -71
  88. apm_cli-0.35.0/src/apm_cli/install/source_helpers.py +122 -0
  89. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/install/sources.py +36 -8
  90. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/install/template.py +100 -1
  91. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/install/transaction.py +63 -22
  92. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/install/validation.py +14 -31
  93. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/integration/base_integrator.py +128 -0
  94. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/integration/cleanup.py +15 -0
  95. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/integration/hook_bundle.py +3 -1
  96. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/integration/hook_command_paths.py +33 -2
  97. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/integration/hook_integrator.py +8 -9
  98. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/integration/hook_native_formats.py +36 -6
  99. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/integration/hook_source_selection.py +25 -2
  100. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/integration/mcp_config_view.py +327 -52
  101. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/integration/mcp_integrator.py +59 -11
  102. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/integration/mcp_integrator_install.py +257 -49
  103. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/integration/prompt_integrator.py +107 -20
  104. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/integration/skill_integrator.py +377 -366
  105. apm_cli-0.35.0/src/apm_cli/integration/skill_preflight.py +198 -0
  106. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/integration/skill_support.py +12 -1
  107. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/integration/targets.py +65 -0
  108. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/marketplace/resolver.py +43 -6
  109. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/models/apm_package.py +46 -0
  110. apm_cli-0.35.0/src/apm_cli/models/dependency/__init__.py +51 -0
  111. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/models/dependency/materialization.py +2 -0
  112. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/models/dependency/reference.py +26 -6
  113. apm_cli-0.35.0/src/apm_cli/models/dependency/replacement.py +674 -0
  114. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/models/format_detection.py +2 -0
  115. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/models/manifest_contract.py +15 -2
  116. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/models/results.py +2 -0
  117. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/models/validation.py +78 -12
  118. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/policy/ci_checks.py +62 -26
  119. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/policy/discovery.py +29 -2
  120. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/registry/operations.py +3 -1
  121. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/security/file_scanner.py +5 -7
  122. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/utils/atomic_io.py +11 -1
  123. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/utils/content_hash.py +37 -19
  124. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/utils/file_ops.py +13 -2
  125. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/utils/helpers.py +6 -1
  126. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/utils/yaml_io.py +10 -7
  127. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/version.py +38 -6
  128. apm_cli-0.35.0/src/apm_cli/version_output.py +57 -0
  129. {apm_cli-0.34.0 → apm_cli-0.35.0/src/apm_cli.egg-info}/PKG-INFO +4 -2
  130. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli.egg-info/SOURCES.txt +18 -0
  131. apm_cli-0.35.0/src/apm_cli.egg-info/entry_points.txt +2 -0
  132. {apm_cli-0.34.0 → apm_cli-0.35.0}/tests/test_apm_package_models.py +11 -7
  133. {apm_cli-0.34.0 → apm_cli-0.35.0}/tests/test_distributed_compilation.py +2 -1
  134. {apm_cli-0.34.0 → apm_cli-0.35.0}/tests/test_empty_string_and_defaults.py +68 -12
  135. {apm_cli-0.34.0 → apm_cli-0.35.0}/tests/test_github_downloader.py +20 -2
  136. {apm_cli-0.34.0 → apm_cli-0.35.0}/tests/test_lockfile.py +34 -9
  137. {apm_cli-0.34.0 → apm_cli-0.35.0}/tests/test_token_manager.py +1 -1
  138. apm_cli-0.34.0/src/apm_cli/install/mcp/ownership.py +0 -114
  139. apm_cli-0.34.0/src/apm_cli/install/package_selection.py +0 -45
  140. apm_cli-0.34.0/src/apm_cli/install/presentation/__init__.py +0 -1
  141. apm_cli-0.34.0/src/apm_cli/install/source_helpers.py +0 -56
  142. apm_cli-0.34.0/src/apm_cli/models/dependency/__init__.py +0 -23
  143. apm_cli-0.34.0/src/apm_cli.egg-info/entry_points.txt +0 -2
  144. {apm_cli-0.34.0 → apm_cli-0.35.0}/AUTHORS +0 -0
  145. {apm_cli-0.34.0 → apm_cli-0.35.0}/LICENSE +0 -0
  146. {apm_cli-0.34.0 → apm_cli-0.35.0}/NOTICE +0 -0
  147. {apm_cli-0.34.0 → apm_cli-0.35.0}/setup.cfg +0 -0
  148. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/__init__.py +0 -0
  149. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/adapters/__init__.py +0 -0
  150. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/adapters/client/__init__.py +0 -0
  151. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/adapters/client/_mcp_runtime_args.py +0 -0
  152. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/adapters/client/antigravity.py +0 -0
  153. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/adapters/client/copilot.py +0 -0
  154. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/adapters/client/gemini.py +0 -0
  155. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/adapters/client/hermes.py +0 -0
  156. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/adapters/client/intellij.py +0 -0
  157. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/adapters/client/kiro.py +0 -0
  158. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/adapters/client/vscode.py +0 -0
  159. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/adapters/client/windsurf.py +0 -0
  160. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/adapters/package_manager/__init__.py +0 -0
  161. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/adapters/package_manager/base.py +0 -0
  162. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/adapters/package_manager/default_manager.py +0 -0
  163. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/adopt/__init__.py +0 -0
  164. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/adopt/discovery.py +0 -0
  165. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/adopt/manifest_edit.py +0 -0
  166. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/adopt/materialize.py +0 -0
  167. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/adopt/render.py +0 -0
  168. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/adopt/safety.py +0 -0
  169. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/agent_plugins/__init__.py +0 -0
  170. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/agent_plugins/assets.py +0 -0
  171. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/agent_plugins/constants.py +0 -0
  172. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/agent_plugins/errors.py +0 -0
  173. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/agent_plugins/io.py +0 -0
  174. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/agent_plugins/ir.py +0 -0
  175. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/agent_plugins/loader.py +0 -0
  176. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/agent_plugins/projection.py +0 -0
  177. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/agent_plugins/validation.py +0 -0
  178. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/bootstrap_mirror.py +0 -0
  179. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/bundle/__init__.py +0 -0
  180. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/bundle/agent_plugin_exporter.py +0 -0
  181. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/bundle/attest.py +0 -0
  182. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/bundle/claude_plugin_exporter.py +0 -0
  183. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/bundle/export_common.py +0 -0
  184. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/bundle/formats.py +0 -0
  185. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/bundle/local_bundle.py +0 -0
  186. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/bundle/lockfile_enrichment.py +0 -0
  187. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/bundle/packer.py +0 -0
  188. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/bundle/plugin_layout.py +0 -0
  189. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/bundle/reproducible_archive.py +0 -0
  190. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/bundle/unpacker.py +0 -0
  191. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/cache/__init__.py +0 -0
  192. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/cache/cleanup.py +0 -0
  193. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/cache/git_cache.py +0 -0
  194. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/cache/http_cache.py +0 -0
  195. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/cache/integrity.py +0 -0
  196. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/cache/locking.py +0 -0
  197. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/cache/paths.py +0 -0
  198. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/cache/url_normalize.py +0 -0
  199. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/cli.py +0 -0
  200. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/commands/__init__.py +0 -0
  201. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/commands/_apm_yml_writer.py +0 -0
  202. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/commands/approve.py +0 -0
  203. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/commands/auth.py +0 -0
  204. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/commands/cache.py +0 -0
  205. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/commands/compile/__init__.py +0 -0
  206. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/commands/compile/cli.py +0 -0
  207. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/commands/compile/watcher.py +0 -0
  208. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/commands/config.py +0 -0
  209. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/commands/deps/__init__.py +0 -0
  210. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/commands/deps/_utils.py +0 -0
  211. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/commands/discover.py +0 -0
  212. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/commands/doctor.py +0 -0
  213. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/commands/experimental.py +0 -0
  214. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/commands/find.py +0 -0
  215. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/commands/init.py +0 -0
  216. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/commands/lifecycle.py +0 -0
  217. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/commands/list_cmd.py +0 -0
  218. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/commands/marketplace/__init__.py +0 -0
  219. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/commands/marketplace/audit.py +0 -0
  220. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/commands/marketplace/check.py +0 -0
  221. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/commands/marketplace/doctor.py +0 -0
  222. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/commands/marketplace/init.py +0 -0
  223. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/commands/marketplace/migrate.py +0 -0
  224. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/commands/marketplace/outdated.py +0 -0
  225. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/commands/marketplace/plugin/__init__.py +0 -0
  226. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/commands/marketplace/plugin/add.py +0 -0
  227. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/commands/marketplace/plugin/remove.py +0 -0
  228. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/commands/marketplace/plugin/set.py +0 -0
  229. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/commands/marketplace/validate.py +0 -0
  230. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/commands/mcp.py +0 -0
  231. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/commands/pack.py +0 -0
  232. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/commands/plugin/__init__.py +0 -0
  233. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/commands/plugin/init.py +0 -0
  234. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/commands/policy.py +0 -0
  235. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/commands/prune.py +0 -0
  236. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/commands/publish.py +0 -0
  237. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/commands/run.py +0 -0
  238. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/commands/runtime.py +0 -0
  239. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/commands/self_update.py +0 -0
  240. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/commands/targets.py +0 -0
  241. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/commands/uninstall/__init__.py +0 -0
  242. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/commands/view.py +0 -0
  243. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/compilation/__init__.py +0 -0
  244. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/compilation/agents_compiler.py +0 -0
  245. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/compilation/build_id.py +0 -0
  246. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/compilation/claude_formatter.py +0 -0
  247. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/compilation/constants.py +0 -0
  248. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/compilation/constitution.py +0 -0
  249. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/compilation/constitution_block.py +0 -0
  250. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/compilation/context_optimizer.py +0 -0
  251. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/compilation/distributed_compiler.py +0 -0
  252. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/compilation/footer.py +0 -0
  253. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/compilation/gemini_formatter.py +0 -0
  254. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/compilation/injector.py +0 -0
  255. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/compilation/inventory.py +0 -0
  256. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/compilation/link_resolver.py +0 -0
  257. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/compilation/managed_section.py +0 -0
  258. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/compilation/output_writer.py +0 -0
  259. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/compilation/root_context_protection.py +0 -0
  260. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/compilation/template_builder.py +0 -0
  261. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/compilation/user_root_context.py +0 -0
  262. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/config.py +0 -0
  263. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/constants.py +0 -0
  264. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/copilot_plugins/__init__.py +0 -0
  265. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/copilot_plugins/capability.py +0 -0
  266. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/copilot_plugins/catalog.py +0 -0
  267. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/copilot_plugins/constants.py +0 -0
  268. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/copilot_plugins/registrar.py +0 -0
  269. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/copilot_plugins/settings.py +0 -0
  270. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/core/__init__.py +0 -0
  271. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/core/_child_tls/__init__.py +0 -0
  272. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/core/_child_tls/_apm_tls.pth +0 -0
  273. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/core/_child_tls/_apm_tls_bootstrap.py +0 -0
  274. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/core/apm_yml.py +0 -0
  275. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/core/auth.py +0 -0
  276. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/core/azure_cli.py +0 -0
  277. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/core/build_orchestrator.py +0 -0
  278. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/core/docker_args.py +0 -0
  279. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/core/errors.py +0 -0
  280. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/core/experimental.py +0 -0
  281. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/core/host_providers.py +0 -0
  282. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/core/install_audit.py +0 -0
  283. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/core/lifecycle_scripts.py +0 -0
  284. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/core/null_logger.py +0 -0
  285. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/core/output_mode.py +0 -0
  286. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/core/plugin_manifest.py +0 -0
  287. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/core/project_name.py +0 -0
  288. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/core/scope.py +0 -0
  289. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/core/script_executors.py +0 -0
  290. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/core/script_runner.py +0 -0
  291. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/core/script_trust.py +0 -0
  292. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/core/target_catalog.py +0 -0
  293. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/core/tls_trust.py +0 -0
  294. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/core/token_manager.py +0 -0
  295. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/deps/__init__.py +0 -0
  296. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/deps/_shared.py +0 -0
  297. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/deps/aggregator.py +0 -0
  298. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/deps/artifactory_entry.py +0 -0
  299. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/deps/artifactory_orchestrator.py +0 -0
  300. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/deps/bare_cache.py +0 -0
  301. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/deps/clone_engine.py +0 -0
  302. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/deps/dependency_graph.py +0 -0
  303. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/deps/download_strategies.py +0 -0
  304. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/deps/git_auth_env.py +0 -0
  305. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/deps/git_file_transport.py +0 -0
  306. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/deps/git_reference_resolver.py +0 -0
  307. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/deps/git_remote_ops.py +0 -0
  308. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/deps/git_semver_resolver.py +0 -0
  309. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/deps/github_rate_limit.py +0 -0
  310. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/deps/host_backends.py +0 -0
  311. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/deps/installed_package.py +0 -0
  312. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/deps/outdated_ref_cache.py +0 -0
  313. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/deps/outdated_row.py +0 -0
  314. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/deps/plugin_parser.py +0 -0
  315. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/deps/registry/__init__.py +0 -0
  316. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/deps/registry/auth.py +0 -0
  317. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/deps/registry/client.py +0 -0
  318. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/deps/registry/config_loader.py +0 -0
  319. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/deps/registry/extractor.py +0 -0
  320. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/deps/registry/feature_gate.py +0 -0
  321. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/deps/registry/outdated.py +0 -0
  322. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/deps/registry/resolver.py +0 -0
  323. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/deps/registry/semver.py +0 -0
  324. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/deps/registry_proxy.py +0 -0
  325. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/deps/shared_clone_cache.py +0 -0
  326. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/deps/tiered_ref_resolver.py +0 -0
  327. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/deps/transport_selection.py +0 -0
  328. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/deps/verifier.py +0 -0
  329. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/export/__init__.py +0 -0
  330. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/export/authoring.py +0 -0
  331. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/export/declared_license.py +0 -0
  332. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/export/formats.py +0 -0
  333. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/export/purl.py +0 -0
  334. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/export/sbom.py +0 -0
  335. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/export/spdx.py +0 -0
  336. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/export/spdx_data.py +0 -0
  337. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/factory.py +0 -0
  338. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/install/__init__.py +0 -0
  339. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/install/argv.py +0 -0
  340. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/install/artifactory_resolver.py +0 -0
  341. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/install/cache_pin.py +0 -0
  342. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/install/deployed_paths.py +0 -0
  343. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/install/exec_gate.py +0 -0
  344. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/install/finalization.py +0 -0
  345. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/install/gitlab_resolver.py +0 -0
  346. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/install/heals/__init__.py +0 -0
  347. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/install/heals/base.py +0 -0
  348. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/install/heals/branch_ref_drift.py +0 -0
  349. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/install/heals/buggy_lockfile_recovery.py +0 -0
  350. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/install/helpers/__init__.py +0 -0
  351. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/install/helpers/security_scan.py +0 -0
  352. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/install/insecure_policy.py +0 -0
  353. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/install/integrity.py +0 -0
  354. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/install/legacy_plugin_compat.py +0 -0
  355. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/install/local_bundle_handler.py +0 -0
  356. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/install/local_bundle_paths.py +0 -0
  357. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/install/locking.py +0 -0
  358. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/install/lsp/__init__.py +0 -0
  359. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/install/manifest_helpers.py +0 -0
  360. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/install/mcp/__init__.py +0 -0
  361. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/install/mcp/args.py +0 -0
  362. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/install/mcp/conflicts.py +0 -0
  363. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/install/mcp/entry.py +0 -0
  364. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/install/mcp/registry.py +0 -0
  365. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/install/mcp/warnings.py +0 -0
  366. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/install/mcp/writer.py +0 -0
  367. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/install/phases/__init__.py +0 -0
  368. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/install/phases/_redownload.py +0 -0
  369. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/install/phases/_skip_logic.py +0 -0
  370. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/install/phases/audit.py +0 -0
  371. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/install/phases/copilot_plugins.py +0 -0
  372. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/install/phases/download.py +0 -0
  373. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/install/phases/finalize.py +0 -0
  374. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/install/phases/heal.py +0 -0
  375. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/install/phases/policy_gate.py +0 -0
  376. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/install/phases/policy_target_check.py +0 -0
  377. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/install/phases/post_deps_local.py +0 -0
  378. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/install/phases/targets.py +0 -0
  379. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/install/primitive_classification.py +0 -0
  380. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/install/project_package.py +0 -0
  381. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/install/registry_wiring.py +0 -0
  382. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/install/request.py +0 -0
  383. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/install/root_redirect.py +0 -0
  384. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/install/skill_path_migration.py +0 -0
  385. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/install/summary.py +0 -0
  386. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/install/target_filter.py +0 -0
  387. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/install/target_hints.py +0 -0
  388. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/install/target_warnings.py +0 -0
  389. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/integration/__init__.py +0 -0
  390. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/integration/_hook_dropped_targets.py +0 -0
  391. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/integration/_shared.py +0 -0
  392. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/integration/agent_integrator.py +0 -0
  393. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/integration/canvas_integrator.py +0 -0
  394. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/integration/command_integrator.py +0 -0
  395. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/integration/copilot_app_db.py +0 -0
  396. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/integration/copilot_app_project.py +0 -0
  397. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/integration/copilot_app_workflow_integrator.py +0 -0
  398. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/integration/copilot_app_ws.py +0 -0
  399. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/integration/copilot_cowork_paths.py +0 -0
  400. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/integration/coverage.py +0 -0
  401. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/integration/dispatch.py +0 -0
  402. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/integration/hook_command_warnings.py +0 -0
  403. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/integration/hook_cursor_preflight.py +0 -0
  404. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/integration/hook_file_routing.py +0 -0
  405. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/integration/hook_ir.py +0 -0
  406. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/integration/hook_ownership.py +0 -0
  407. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/integration/hook_reintegration.py +0 -0
  408. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/integration/instruction_integrator.py +0 -0
  409. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/integration/kiro_hook_integrator.py +0 -0
  410. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/integration/lsp_integrator.py +0 -0
  411. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/integration/opencode_frontmatter.py +0 -0
  412. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/integration/skill_package_routing.py +0 -0
  413. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/integration/skill_transformer.py +0 -0
  414. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/integration/utils.py +0 -0
  415. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/marketplace/__init__.py +0 -0
  416. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/marketplace/_git_utils.py +0 -0
  417. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/marketplace/_io.py +0 -0
  418. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/marketplace/_shared.py +0 -0
  419. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/marketplace/audit.py +0 -0
  420. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/marketplace/auth_helpers.py +0 -0
  421. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/marketplace/builder.py +0 -0
  422. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/marketplace/client.py +0 -0
  423. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/marketplace/diagnostics.py +0 -0
  424. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/marketplace/drift_check.py +0 -0
  425. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/marketplace/errors.py +0 -0
  426. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/marketplace/git_stderr.py +0 -0
  427. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/marketplace/init_template.py +0 -0
  428. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/marketplace/migration.py +0 -0
  429. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/marketplace/models.py +0 -0
  430. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/marketplace/output_mappers.py +0 -0
  431. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/marketplace/output_profiles.py +0 -0
  432. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/marketplace/ref_resolver.py +0 -0
  433. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/marketplace/registry.py +0 -0
  434. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/marketplace/semver.py +0 -0
  435. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/marketplace/shadow_detector.py +0 -0
  436. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/marketplace/source_identity.py +0 -0
  437. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/marketplace/tag_pattern.py +0 -0
  438. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/marketplace/validator.py +0 -0
  439. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/marketplace/version_check.py +0 -0
  440. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/marketplace/version_pins.py +0 -0
  441. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/marketplace/version_resolver.py +0 -0
  442. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/marketplace/yml_editor.py +0 -0
  443. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/marketplace/yml_schema.py +0 -0
  444. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/models/__init__.py +0 -0
  445. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/models/dependency/host_virtual.py +0 -0
  446. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/models/dependency/identity.py +0 -0
  447. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/models/dependency/lsp.py +0 -0
  448. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/models/dependency/mcp.py +0 -0
  449. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/models/dependency/object_fields.py +0 -0
  450. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/models/dependency/provider_coordinates.py +0 -0
  451. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/models/dependency/registry_entry.py +0 -0
  452. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/models/dependency/selection.py +0 -0
  453. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/models/dependency/subsets.py +0 -0
  454. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/models/dependency/types.py +0 -0
  455. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/models/plugin.py +0 -0
  456. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/output/__init__.py +0 -0
  457. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/output/formatters.py +0 -0
  458. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/output/models.py +0 -0
  459. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/output/script_formatters.py +0 -0
  460. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/policy/__init__.py +0 -0
  461. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/policy/_constraint_pinning.py +0 -0
  462. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/policy/_gitlab.py +0 -0
  463. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/policy/_help_text.py +0 -0
  464. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/policy/_shared.py +0 -0
  465. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/policy/inheritance.py +0 -0
  466. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/policy/install_preflight.py +0 -0
  467. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/policy/matcher.py +0 -0
  468. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/policy/models.py +0 -0
  469. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/policy/outcome_routing.py +0 -0
  470. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/policy/parser.py +0 -0
  471. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/policy/policy_checks.py +0 -0
  472. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/policy/project_config.py +0 -0
  473. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/policy/schema.py +0 -0
  474. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/primitives/__init__.py +0 -0
  475. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/primitives/discovery.py +0 -0
  476. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/primitives/models.py +0 -0
  477. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/primitives/parser.py +0 -0
  478. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/registry/__init__.py +0 -0
  479. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/registry/client.py +0 -0
  480. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/registry/integration.py +0 -0
  481. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/runtime/__init__.py +0 -0
  482. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/runtime/base.py +0 -0
  483. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/runtime/codex_runtime.py +0 -0
  484. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/runtime/copilot_runtime.py +0 -0
  485. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/runtime/factory.py +0 -0
  486. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/runtime/llm_runtime.py +0 -0
  487. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/runtime/manager.py +0 -0
  488. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/runtime/registry.py +0 -0
  489. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/runtime/utils.py +0 -0
  490. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/security/__init__.py +0 -0
  491. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/security/audit_report.py +0 -0
  492. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/security/content_scanner.py +0 -0
  493. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/security/executables.py +0 -0
  494. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/security/external/__init__.py +0 -0
  495. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/security/external/base.py +0 -0
  496. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/security/external/gate.py +0 -0
  497. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/security/external/generic_sarif.py +0 -0
  498. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/security/external/options.py +0 -0
  499. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/security/external/registry.py +0 -0
  500. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/security/external/runner.py +0 -0
  501. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/security/external/sarif_ingest.py +0 -0
  502. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/security/external/skillspector.py +0 -0
  503. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/security/gate.py +0 -0
  504. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/security/primitive_discovery.py +0 -0
  505. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/update_policy.py +0 -0
  506. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/utils/__init__.py +0 -0
  507. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/utils/archive.py +0 -0
  508. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/utils/console.py +0 -0
  509. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/utils/diagnostics.py +0 -0
  510. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/utils/exclude.py +0 -0
  511. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/utils/git_env.py +0 -0
  512. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/utils/git_sparse.py +0 -0
  513. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/utils/github_host.py +0 -0
  514. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/utils/guards.py +0 -0
  515. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/utils/install_tui.py +0 -0
  516. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/utils/net.py +0 -0
  517. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/utils/normalization.py +0 -0
  518. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/utils/path_security.py +0 -0
  519. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/utils/paths.py +0 -0
  520. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/utils/patterns.py +0 -0
  521. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/utils/perf_stats.py +0 -0
  522. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/utils/reflink.py +0 -0
  523. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/utils/short_sha.py +0 -0
  524. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/utils/staging_guard.py +0 -0
  525. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/utils/subprocess_env.py +0 -0
  526. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/utils/version_checker.py +0 -0
  527. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/workflow/__init__.py +0 -0
  528. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/workflow/discovery.py +0 -0
  529. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/workflow/parser.py +0 -0
  530. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli/workflow/runner.py +0 -0
  531. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli.egg-info/dependency_links.txt +0 -0
  532. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli.egg-info/requires.txt +0 -0
  533. {apm_cli-0.34.0 → apm_cli-0.35.0}/src/apm_cli.egg-info/top_level.txt +0 -0
  534. {apm_cli-0.34.0 → apm_cli-0.35.0}/tests/test_apm_resolver.py +0 -0
  535. {apm_cli-0.34.0 → apm_cli-0.35.0}/tests/test_codex_docker_args_fix.py +0 -0
  536. {apm_cli-0.34.0 → apm_cli-0.35.0}/tests/test_codex_empty_string_and_defaults.py +0 -0
  537. {apm_cli-0.34.0 → apm_cli-0.35.0}/tests/test_collision_integration.py +0 -0
  538. {apm_cli-0.34.0 → apm_cli-0.35.0}/tests/test_console.py +0 -0
  539. {apm_cli-0.34.0 → apm_cli-0.35.0}/tests/test_enhanced_discovery.py +0 -0
  540. {apm_cli-0.34.0 → apm_cli-0.35.0}/tests/test_github_downloader_token_precedence.py +0 -0
  541. {apm_cli-0.34.0 → apm_cli-0.35.0}/tests/test_gitlab_git_transport.py +0 -0
  542. {apm_cli-0.34.0 → apm_cli-0.35.0}/tests/test_runnable_prompts.py +0 -0
  543. {apm_cli-0.34.0 → apm_cli-0.35.0}/tests/test_runtime_manager_token_precedence.py +0 -0
  544. {apm_cli-0.34.0 → apm_cli-0.35.0}/tests/test_virtual_package_multi_install.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: apm-cli
3
- Version: 0.34.0
3
+ Version: 0.35.0
4
4
  Summary: MCP configuration tool
5
5
  Author-email: Daniel Meppiel <user@example.com>
6
6
  License: MIT License
@@ -95,6 +95,8 @@ AI coding agents need context to be useful — standards, prompts, skills, plugi
95
95
  # apm.yml — ships with your project
96
96
  name: your-project
97
97
  version: 1.0.0
98
+ targets:
99
+ - copilot # choose the harness(es) this project supports
98
100
  dependencies:
99
101
  apm:
100
102
  # Skills from any repository
@@ -106,7 +108,7 @@ dependencies:
106
108
  # A full APM package with instructions, skills, prompts, hooks...
107
109
  - microsoft/apm-sample-package#v1.0.0
108
110
  mcp:
109
- # MCP servers -- installed into every detected client
111
+ # MCP servers -- installed into every selected target
110
112
  - name: io.github.github/github-mcp-server
111
113
  transport: http # MCP transport name, not URL scheme -- connects over HTTPS
112
114
  ```
@@ -23,6 +23,8 @@ AI coding agents need context to be useful — standards, prompts, skills, plugi
23
23
  # apm.yml — ships with your project
24
24
  name: your-project
25
25
  version: 1.0.0
26
+ targets:
27
+ - copilot # choose the harness(es) this project supports
26
28
  dependencies:
27
29
  apm:
28
30
  # Skills from any repository
@@ -34,7 +36,7 @@ dependencies:
34
36
  # A full APM package with instructions, skills, prompts, hooks...
35
37
  - microsoft/apm-sample-package#v1.0.0
36
38
  mcp:
37
- # MCP servers -- installed into every detected client
39
+ # MCP servers -- installed into every selected target
38
40
  - name: io.github.github/github-mcp-server
39
41
  transport: http # MCP transport name, not URL scheme -- connects over HTTPS
40
42
  ```
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "apm-cli"
7
- version = "0.34.0"
7
+ version = "0.35.0"
8
8
  description = "MCP configuration tool"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.10"
@@ -60,7 +60,7 @@ build = [
60
60
  ]
61
61
 
62
62
  [project.scripts]
63
- apm = "apm_cli.cli:main"
63
+ apm = "apm_cli.entrypoint:main"
64
64
 
65
65
  [tool.setuptools.packages.find]
66
66
  where = ["src"]
@@ -337,6 +337,7 @@ class MCPClientAdapter(ABC):
337
337
  """
338
338
  self._project_root = Path(project_root) if project_root is not None else None
339
339
  self.user_scope = user_scope
340
+ self.written_mcp_hashes: dict[str, str] = {}
340
341
  # Per-server tracking populated by the env-resolution helpers and
341
342
  # consumed by ``configure_mcp_server`` for the post-install summary
342
343
  # and the aggregated legacy-syntax deprecation warning. Defined on
@@ -367,12 +368,18 @@ class MCPClientAdapter(ABC):
367
368
  return self._project_root
368
369
  return Path(os.getcwd())
369
370
 
370
- def render_server_config(self, server_info: dict) -> dict:
371
+ def render_server_config(
372
+ self,
373
+ server_info: dict,
374
+ *,
375
+ env_overrides: dict | None = None,
376
+ runtime_vars: dict | None = None,
377
+ ) -> dict:
371
378
  """Render one native server entry for exact baseline comparisons."""
372
379
  rendered = self._format_server_config(
373
380
  server_info,
374
- env_overrides={},
375
- runtime_vars={},
381
+ env_overrides=env_overrides or {},
382
+ runtime_vars=runtime_vars or {},
376
383
  )
377
384
  if isinstance(rendered, tuple):
378
385
  rendered = rendered[0]
@@ -380,6 +387,20 @@ class MCPClientAdapter(ABC):
380
387
  raise ValueError("Adapter did not produce a native MCP server mapping")
381
388
  return rendered
382
389
 
390
+ def matches_managed_server_config(self, native: object, expected: dict) -> bool:
391
+ """Compare the native connection with the adapter's rendered baseline."""
392
+ return native == expected
393
+
394
+ def managed_server_config(self, native: dict) -> dict:
395
+ """Return connection data for an actual-write fingerprint."""
396
+ return dict(native)
397
+
398
+ def project_managed_server_config(
399
+ self, native: object, *, baseline: dict, requested: dict
400
+ ) -> object:
401
+ """Return a comparison-only view for an already recorded managed connection."""
402
+ return native
403
+
383
404
  @abstractmethod
384
405
  def get_config_path(self):
385
406
  """Get the path to the MCP configuration file."""
@@ -1118,6 +1139,28 @@ class MCPClientAdapter(ABC):
1118
1139
  return True
1119
1140
  return not (sys.stdin.isatty() and sys.stdout.isatty())
1120
1141
 
1142
+ def _resolve_explicit_environment_values(
1143
+ self,
1144
+ env_vars: dict[str, object],
1145
+ env_overrides: dict[str, str] | None = None,
1146
+ ) -> dict[str, str]:
1147
+ """Translate authored references while preserving explicit env literals.
1148
+
1149
+ Resets placeholder tracking; mid-render callers must preserve prior keys.
1150
+ """
1151
+ resolved: dict[str, str] = {}
1152
+ self._last_env_placeholder_keys = set()
1153
+ for name, value in env_vars.items():
1154
+ if not name or value is None:
1155
+ continue
1156
+ if isinstance(value, TrustedEnvLiteral):
1157
+ resolved[name] = value
1158
+ elif isinstance(value, str):
1159
+ resolved[name] = self._resolve_env_variable(name, value, env_overrides)
1160
+ else:
1161
+ resolved[name] = _stringify_env_literal(value)
1162
+ return resolved
1163
+
1121
1164
  def _resolve_environment_variables(self, env_vars, env_overrides=None):
1122
1165
  """Resolve (or translate) declared environment variables.
1123
1166
 
@@ -26,7 +26,7 @@ from pathlib import Path
26
26
 
27
27
  from ...utils.atomic_io import atomic_write_text
28
28
  from ...utils.console import _rich_error, _rich_success, _rich_warning
29
- from ...utils.path_security import PathTraversalError
29
+ from ...utils.path_security import PathTraversalError, validate_path_segments
30
30
  from .copilot import CopilotClientAdapter
31
31
 
32
32
  _log = logging.getLogger(__name__)
@@ -83,6 +83,51 @@ class ClaudeClientAdapter(CopilotClientAdapter):
83
83
  config["command"] = self._rewrite_self_defined_skill_command(config["command"])
84
84
  return config
85
85
 
86
+ def render_server_config(
87
+ self,
88
+ server_info: dict,
89
+ *,
90
+ env_overrides: dict | None = None,
91
+ runtime_vars: dict | None = None,
92
+ ) -> dict:
93
+ """Compare against the normalized shape actually written to Claude."""
94
+ return self._normalize_mcp_entry_for_claude_code(
95
+ super().render_server_config(
96
+ server_info, env_overrides=env_overrides, runtime_vars=runtime_vars
97
+ )
98
+ )
99
+
100
+ def matches_managed_server_config(self, native: object, expected: dict) -> bool:
101
+ """OAuth metadata is runtime-owned, not part of an APM connection declaration."""
102
+ if not isinstance(native, dict):
103
+ return False
104
+ return self.managed_server_config(native) == expected
105
+
106
+ def managed_server_config(self, native: dict) -> dict:
107
+ """Exclude only the runtime-owned OAuth account from write fingerprints."""
108
+ return {key: value for key, value in native.items() if key != "oauthAccount"}
109
+
110
+ def project_managed_server_config(
111
+ self, native: object, *, baseline: dict, requested: dict
112
+ ) -> object:
113
+ """Exclude a valid native-only cwd from managed reconciliation, never cleanup."""
114
+ if (
115
+ not isinstance(native, dict)
116
+ or native.get("type") != "stdio"
117
+ or baseline.get("type") != "stdio"
118
+ or "cwd" in baseline
119
+ or "cwd" in requested
120
+ ):
121
+ return native
122
+ cwd = native.get("cwd")
123
+ if not isinstance(cwd, str) or not cwd.strip() or "\x00" in cwd:
124
+ return native
125
+ try:
126
+ validate_path_segments(cwd, context="MCP cwd", allow_current_dir=True)
127
+ except PathTraversalError:
128
+ return native
129
+ return {key: value for key, value in native.items() if key != "cwd"}
130
+
86
131
  @classmethod
87
132
  def _is_remote_mcp_entry(cls, entry: dict) -> bool:
88
133
  """Return whether *entry* describes a remote (URL-addressed) server."""
@@ -148,7 +193,9 @@ class ClaudeClientAdapter(CopilotClientAdapter):
148
193
  }
149
194
 
150
195
  @classmethod
151
- def _merge_mcp_server_dicts(cls, existing_servers: dict, config_updates: dict) -> None:
196
+ def _merge_mcp_server_dicts(
197
+ cls, existing_servers: dict, config_updates: dict, managed_fields: set[str] | None = None
198
+ ) -> None:
152
199
  """Merge *config_updates* into *existing_servers* in place.
153
200
 
154
201
  Per-server entries are shallow-merged: ``{**old, **new}`` so keys present
@@ -164,15 +211,23 @@ class ClaudeClientAdapter(CopilotClientAdapter):
164
211
  continue
165
212
  prev = existing_servers.get(name)
166
213
  if isinstance(prev, dict):
214
+ if managed_fields:
215
+ prev = {
216
+ key: value
217
+ for key, value in prev.items()
218
+ if key not in managed_fields or key in new_cfg
219
+ }
167
220
  merged = {**cls._retained_previous_entry(prev, new_cfg), **new_cfg}
168
221
  existing_servers[name] = merged
169
222
  else:
170
223
  existing_servers[name] = dict(new_cfg)
171
224
 
172
- def _merge_and_normalize_updates(self, data: dict, config_updates: dict) -> None:
225
+ def _merge_and_normalize_updates(
226
+ self, data: dict, config_updates: dict, managed_fields: set[str] | None = None
227
+ ) -> None:
173
228
  if "mcpServers" not in data:
174
229
  data["mcpServers"] = {}
175
- self._merge_mcp_server_dicts(data["mcpServers"], config_updates)
230
+ self._merge_mcp_server_dicts(data["mcpServers"], config_updates, managed_fields)
176
231
  for name in config_updates:
177
232
  ent = data["mcpServers"].get(name)
178
233
  if isinstance(ent, dict):
@@ -234,9 +289,11 @@ class ClaudeClientAdapter(CopilotClientAdapter):
234
289
  except (json.JSONDecodeError, OSError):
235
290
  return {"mcpServers": {}}
236
291
 
237
- def update_config(self, config_updates, enabled=True):
292
+ def update_config(
293
+ self, config_updates, enabled=True, *, managed_fields: set[str] | None = None
294
+ ):
238
295
  if self._is_user_scope():
239
- return self._merge_user_mcp(config_updates)
296
+ return self._merge_user_mcp(config_updates, managed_fields=managed_fields)
240
297
  if not self._should_write_project():
241
298
  _rich_warning(
242
299
  f"Skipped Claude Code project MCP -- .claude/ not found in {self.project_root}"
@@ -254,13 +311,13 @@ class ClaudeClientAdapter(CopilotClientAdapter):
254
311
  data = {}
255
312
  else:
256
313
  data = {}
257
- self._merge_and_normalize_updates(data, config_updates)
314
+ self._merge_and_normalize_updates(data, config_updates, managed_fields)
258
315
  path.write_text(json.dumps(data, indent=2) + "\n", encoding="utf-8")
259
316
  return True
260
317
  except OSError:
261
318
  return False
262
319
 
263
- def _merge_user_mcp(self, config_updates) -> bool:
320
+ def _merge_user_mcp(self, config_updates, *, managed_fields: set[str] | None = None) -> bool:
264
321
  path = self._user_claude_json_path()
265
322
  try:
266
323
  if path.is_file():
@@ -273,7 +330,7 @@ class ClaudeClientAdapter(CopilotClientAdapter):
273
330
  data = {}
274
331
  else:
275
332
  data = {}
276
- self._merge_and_normalize_updates(data, config_updates)
333
+ self._merge_and_normalize_updates(data, config_updates, managed_fields)
277
334
  payload = json.dumps(data, indent=2) + "\n"
278
335
  path.parent.mkdir(parents=True, exist_ok=True)
279
336
  atomic_write_text(path, payload, new_file_mode=0o600)
@@ -290,6 +347,7 @@ class ClaudeClientAdapter(CopilotClientAdapter):
290
347
  env_overrides=None,
291
348
  server_info_cache=None,
292
349
  runtime_vars=None,
350
+ managed_fields: set[str] | None = None,
293
351
  ):
294
352
  if not server_url:
295
353
  _rich_error("server_url cannot be empty")
@@ -314,10 +372,16 @@ class ClaudeClientAdapter(CopilotClientAdapter):
314
372
  config_key = self._determine_config_key(server_url, server_name)
315
373
 
316
374
  server_config = self._format_server_config(server_info, env_overrides, runtime_vars)
317
- ok = self.update_config({config_key: server_config})
375
+ from apm_cli.install.mcp.ownership import mcp_native_hash
376
+
377
+ fingerprint = mcp_native_hash(
378
+ self.managed_server_config(self._normalize_mcp_entry_for_claude_code(server_config))
379
+ )
380
+ ok = self.update_config({config_key: server_config}, managed_fields=managed_fields)
318
381
  if not ok:
319
382
  _rich_error(f"Failed to write MCP config for '{config_key}' to Claude Code")
320
383
  return False
384
+ self.written_mcp_hashes[server_url] = fingerprint
321
385
 
322
386
  _rich_success(f"Successfully configured MCP server '{config_key}' for Claude Code")
323
387
  return True
@@ -1,5 +1,6 @@
1
1
  """OpenAI Codex CLI implementation of MCP client adapter."""
2
2
 
3
+ import json
3
4
  import logging
4
5
  import os
5
6
  import re
@@ -8,6 +9,7 @@ from urllib.parse import urlparse
8
9
 
9
10
  import tomlkit
10
11
  from tomlkit.exceptions import TOMLKitError
12
+ from tomlkit.items import InlineTable, Item, String, Table
11
13
 
12
14
  from ...registry.client import SimpleRegistryClient
13
15
  from ...registry.integration import RegistryIntegration
@@ -31,6 +33,8 @@ _log = logging.getLogger(__name__)
31
33
  # ``_resolve_variable_placeholders`` untouched.
32
34
  # See https://learn.chatgpt.com/docs/extend/mcp?surface=cli
33
35
  _CODEX_BEARER_HEADER = "authorization"
36
+ _CODEX_REGISTRY_ID_COMMENT = "# apm-registry-id: "
37
+ _JSON_DECODER = json.JSONDecoder()
34
38
  # Reuse the canonical placeholder syntax so the two spellings APM accepts
35
39
  # (``${VAR}`` and ``${env:VAR}``) cannot drift apart here. The auth scheme is
36
40
  # case-insensitive per RFC 7235; Codex always writes it as ``Bearer``.
@@ -102,13 +106,125 @@ class CodexClientAdapter(MCPClientAdapter):
102
106
  """
103
107
  return str(self._get_codex_dir() / "config.toml")
104
108
 
109
+ @staticmethod
110
+ def _registry_id_item(server_config: object) -> Item | None:
111
+ """Locate a comment that survives standard, dotted and inline TOML layouts.
112
+
113
+ Inline values cannot contain comments, so annotate the whole inline
114
+ entry. Other layouts expose command/url scalar trivia even when their
115
+ parent tables are implicit or split across out-of-order fragments.
116
+ """
117
+ if isinstance(server_config, InlineTable):
118
+ return server_config
119
+ if isinstance(server_config, dict):
120
+ for key in ("command", "url"):
121
+ value = server_config.get(key)
122
+ if isinstance(value, String):
123
+ return value
124
+ return None
125
+
126
+ @classmethod
127
+ def get_registry_id(cls, server_config: dict) -> str | None:
128
+ """Read APM identity metadata without exposing it as a Codex setting.
129
+
130
+ Keep reading legacy native IDs for conflict detection; their presence
131
+ alone is not ownership evidence and never authorizes a migration.
132
+ """
133
+ legacy_id = server_config.get("id")
134
+ if isinstance(legacy_id, str) and legacy_id:
135
+ return legacy_id
136
+ item = cls._registry_id_item(server_config)
137
+ if item is None:
138
+ return None
139
+ comment = item.trivia.comment
140
+ if not comment.startswith(_CODEX_REGISTRY_ID_COMMENT):
141
+ return None
142
+ try:
143
+ registry_id, _ = _JSON_DECODER.raw_decode(comment[len(_CODEX_REGISTRY_ID_COMMENT) :])
144
+ except ValueError:
145
+ return None
146
+ return registry_id if isinstance(registry_id, str) and registry_id else None
147
+
148
+ @classmethod
149
+ def _annotate_registry_id(cls, server_config: dict, registry_id: str) -> None:
150
+ """Keep UUID matching metadata in an escaped, round-trip TOML comment."""
151
+ item = cls._registry_id_item(server_config)
152
+ if item is None:
153
+ raise ValueError("Codex MCP server must have a string command or url")
154
+ original_comment = item.trivia.comment
155
+ suffix = f" {original_comment}" if original_comment else ""
156
+ item.comment(_CODEX_REGISTRY_ID_COMMENT[2:] + json.dumps(registry_id) + suffix)
157
+
158
+ @staticmethod
159
+ def _expand_inline_table(entry: InlineTable) -> Table:
160
+ """Expand an inline container without discarding its values or comments.
161
+
162
+ Nested inline comments are invalid TOML, and deleting a middle key can
163
+ leave stray separators in tomlkit. Expand only containers being written
164
+ or owned entries being repaired; keep unrelated child items intact.
165
+ """
166
+ table = tomlkit.table(is_super_table=False)
167
+ for key, value in entry.items():
168
+ table.add(key, value)
169
+ if entry.trivia.comment:
170
+ table.comment(entry.trivia.comment)
171
+ return table
172
+
173
+ def _write_config(self, config: dict) -> None:
174
+ """Validate serialized TOML before atomically replacing the native file."""
175
+ serialized = tomlkit.dumps(config)
176
+ tomlkit.parse(serialized)
177
+ config_path = Path(self.get_config_path())
178
+ config_path.parent.mkdir(parents=True, exist_ok=True)
179
+ atomic_write_text(config_path, serialized, new_file_mode=0o600)
180
+ _log.debug("Codex config written to %s", config_path)
181
+
182
+ def migrate_legacy_managed_servers(self, managed_names: set[str]) -> set[str]:
183
+ """Remove unsupported IDs only from entries with recorded APM ownership."""
184
+ if not managed_names:
185
+ return set()
186
+ config = self.get_current_config()
187
+ if config is None:
188
+ return set()
189
+ servers = config.get("mcp_servers", {})
190
+ migrated: set[str] = set()
191
+ for name in sorted(managed_names):
192
+ config_key = self._determine_config_key(name, None)
193
+ entry = servers.get(config_key)
194
+ if not isinstance(entry, dict) or "id" not in entry:
195
+ continue
196
+ registry_id = entry["id"]
197
+ if not isinstance(registry_id, str):
198
+ continue
199
+ if isinstance(servers, InlineTable):
200
+ servers = self._expand_inline_table(servers)
201
+ config["mcp_servers"] = servers
202
+ if isinstance(entry, InlineTable):
203
+ entry = self._expand_inline_table(entry)
204
+ servers[config_key] = entry
205
+ if registry_id:
206
+ self._annotate_registry_id(entry, registry_id)
207
+ del entry["id"]
208
+ migrated.add(name)
209
+ if migrated:
210
+ self._write_config(config)
211
+ return migrated
212
+
213
+ def matches_managed_server_config(self, native: object, expected: dict) -> bool:
214
+ """Accept the historical empty-ID spelling without accepting foreign identity."""
215
+ if not isinstance(native, dict) or self.get_registry_id(native):
216
+ return False
217
+ comparable = dict(native)
218
+ if comparable.get("id") == "":
219
+ comparable.pop("id")
220
+ return comparable == expected
221
+
105
222
  def update_config(self, config_updates):
106
223
  """Update the Codex CLI MCP configuration.
107
224
 
108
225
  Args:
109
226
  config_updates (dict): Configuration updates to apply.
110
227
  """
111
- config_path = Path(self.get_config_path())
112
228
  current_config = self.get_current_config()
113
229
  if current_config is None:
114
230
  return False
@@ -116,15 +232,13 @@ class CodexClientAdapter(MCPClientAdapter):
116
232
  # Ensure mcp_servers section exists
117
233
  if "mcp_servers" not in current_config:
118
234
  current_config["mcp_servers"] = {}
235
+ elif isinstance(current_config["mcp_servers"], InlineTable):
236
+ current_config["mcp_servers"] = self._expand_inline_table(current_config["mcp_servers"])
119
237
 
120
238
  # Apply updates to mcp_servers section
121
239
  current_config["mcp_servers"].update(config_updates)
122
240
 
123
- # Ensure directory exists
124
- config_path.parent.mkdir(parents=True, exist_ok=True)
125
-
126
- atomic_write_text(config_path, tomlkit.dumps(current_config), new_file_mode=0o600)
127
- _log.debug("Codex config written to %s", config_path)
241
+ self._write_config(current_config)
128
242
  return True
129
243
 
130
244
  def get_current_config(self):
@@ -199,9 +313,19 @@ class CodexClientAdapter(MCPClientAdapter):
199
313
  if server_config is None:
200
314
  return False
201
315
 
316
+ # Registry identity is APM metadata, not a supported native field.
317
+ registry_id = server_info.get("id")
318
+ if isinstance(registry_id, str) and registry_id:
319
+ server_config = tomlkit.item(server_config)
320
+ self._annotate_registry_id(server_config, registry_id)
321
+
202
322
  # Update configuration using the chosen key
323
+ from apm_cli.install.mcp.ownership import mcp_native_hash
324
+
325
+ fingerprint = mcp_native_hash(self.managed_server_config(server_config))
203
326
  if not self.update_config({config_key: server_config}):
204
327
  return False
328
+ self.written_mcp_hashes[server_url] = fingerprint
205
329
 
206
330
  _rich_success(
207
331
  f"Configured MCP server '{config_key}' for Codex CLI",
@@ -227,12 +351,11 @@ class CodexClientAdapter(MCPClientAdapter):
227
351
  if runtime_vars is None:
228
352
  runtime_vars = {}
229
353
 
230
- # Default configuration structure with registry ID for conflict detection
354
+ # Only fields accepted by Codex belong in the native server mapping.
231
355
  config = {
232
356
  "command": "unknown",
233
357
  "args": [],
234
358
  "env": {},
235
- "id": server_info.get("id", ""), # Add registry UUID for conflict detection
236
359
  }
237
360
 
238
361
  # Self-defined stdio deps carry raw command/args. Route ``env`` and
@@ -313,10 +436,7 @@ class CodexClientAdapter(MCPClientAdapter):
313
436
  )
314
437
  return None
315
438
 
316
- remote_config = {
317
- "url": remote_url,
318
- "id": server_info.get("id", ""),
319
- }
439
+ remote_config = {"url": remote_url}
320
440
  http_headers: dict[str, str] = {}
321
441
  env_http_headers: dict[str, str] = {}
322
442
  bearer_token_env_var = ""
@@ -13,8 +13,6 @@ import os
13
13
  from pathlib import Path
14
14
 
15
15
  from ...core.token_manager import GitHubTokenManager
16
- from ...models.dependency.mcp import TrustedEnvLiteral
17
- from .base import _stringify_env_literal
18
16
  from .copilot import CopilotClientAdapter
19
17
 
20
18
 
@@ -55,18 +53,7 @@ class CursorClientAdapter(CopilotClientAdapter):
55
53
  if not isinstance(env_vars, dict):
56
54
  return super()._resolve_environment_variables(env_vars, env_overrides)
57
55
 
58
- resolved: dict[str, str] = {}
59
- self._last_env_placeholder_keys = set()
60
- for name, value in env_vars.items():
61
- if not name or value is None:
62
- continue
63
- if isinstance(value, TrustedEnvLiteral):
64
- resolved[name] = value
65
- elif isinstance(value, str):
66
- resolved[name] = self._resolve_env_variable(name, value, env_overrides)
67
- else:
68
- resolved[name] = _stringify_env_literal(value)
69
- return resolved
56
+ return self._resolve_explicit_environment_values(env_vars, env_overrides)
70
57
 
71
58
  # ------------------------------------------------------------------ #
72
59
  # Auth-header injection override (for testability)
@@ -29,12 +29,16 @@ At project scope APM only writes to ``opencode.json`` when the
29
29
 
30
30
  import json
31
31
  import os
32
+ import re
32
33
  from pathlib import Path
33
34
  from typing import Any
34
35
 
35
36
  from ...models.dependency.mcp import _EXTRA_DENYLIST, opencode_enabled_value
36
37
  from .copilot import CopilotClientAdapter
37
38
 
39
+ _ENV_REF_TEMPLATE = "{env:%s}"
40
+ _ENV_REF_RE = re.compile(re.escape(_ENV_REF_TEMPLATE) % r"([A-Za-z_][A-Za-z0-9_]*)")
41
+
38
42
 
39
43
  class OpenCodeClientAdapter(CopilotClientAdapter):
40
44
  """OpenCode MCP client adapter.
@@ -47,11 +51,43 @@ class OpenCodeClientAdapter(CopilotClientAdapter):
47
51
  target_name: str = "opencode"
48
52
  mcp_servers_key: str = "mcp"
49
53
 
50
- # OpenCode's config runtime-substitution support has not yet been
51
- # individually audited (see #1152). Pin to legacy install-time
52
- # resolution so this adapter is unchanged by the Copilot security fix;
53
- # revisit in a follow-up.
54
- _supports_runtime_env_substitution: bool = False
54
+ # OpenCode resolves {env:NAME} throughout config strings, including MCP
55
+ # environment, headers and command args (https://opencode.ai/docs/config/#env-vars).
56
+ # Keep referenced secrets out of generated configuration; see #3051.
57
+ _supports_runtime_env_substitution: bool = True
58
+
59
+ def _format_runtime_env_placeholder(self, name: str) -> str:
60
+ """Return OpenCode's native environment reference."""
61
+ return _ENV_REF_TEMPLATE % name
62
+
63
+ def _resolve_environment_variables(
64
+ self,
65
+ env_vars: dict[str, object] | list[dict[str, object]],
66
+ env_overrides: dict[str, str] | None = None,
67
+ ) -> dict[str, str]:
68
+ """Preserve explicit literals; translate references for runtime lookup."""
69
+ if not isinstance(env_vars, dict):
70
+ return super()._resolve_environment_variables(env_vars, env_overrides)
71
+ return self._resolve_explicit_environment_values(env_vars, env_overrides)
72
+
73
+ def _format_server_config(self, server_info, env_overrides=None, runtime_vars=None):
74
+ """Preserve per-server authored registry env values after normal rendering."""
75
+ config = super()._format_server_config(server_info, env_overrides, runtime_vars)
76
+ overlay = server_info.get("_apm_env_overlay")
77
+ env = config.get("env")
78
+ if server_info.get("_raw_stdio") or not overlay or not isinstance(env, dict):
79
+ return config
80
+
81
+ # Only declared/emitted keys participate, as on the legacy registry path.
82
+ # Never recover authored values from the shared collected overrides.
83
+ authored = {name: value for name, value in overlay.items() if name in env}
84
+ previous_keys = self._last_env_placeholder_keys - set(env)
85
+ # Deliberately omit collected overrides: only authored values belong here.
86
+ env.update(self._resolve_explicit_environment_values(authored))
87
+ self._last_env_placeholder_keys = previous_keys | {
88
+ name for value in env.values() for name in _ENV_REF_RE.findall(value)
89
+ }
90
+ return config
55
91
 
56
92
  @staticmethod
57
93
  def config_path_for(project_root: Path, user_scope: bool) -> Path: