apm-cli 0.8.5__tar.gz → 0.8.7__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 (174) hide show
  1. {apm_cli-0.8.5/src/apm_cli.egg-info → apm_cli-0.8.7}/PKG-INFO +1 -1
  2. {apm_cli-0.8.5 → apm_cli-0.8.7}/pyproject.toml +1 -1
  3. {apm_cli-0.8.5 → apm_cli-0.8.7}/src/apm_cli/commands/deps/__init__.py +0 -4
  4. {apm_cli-0.8.5 → apm_cli-0.8.7}/src/apm_cli/commands/deps/_utils.py +2 -106
  5. {apm_cli-0.8.5 → apm_cli-0.8.7}/src/apm_cli/commands/deps/cli.py +177 -38
  6. {apm_cli-0.8.5 → apm_cli-0.8.7}/src/apm_cli/commands/install.py +214 -239
  7. {apm_cli-0.8.5 → apm_cli-0.8.7}/src/apm_cli/commands/uninstall/engine.py +69 -76
  8. {apm_cli-0.8.5 → apm_cli-0.8.7}/src/apm_cli/compilation/claude_formatter.py +4 -1
  9. {apm_cli-0.8.5 → apm_cli-0.8.7}/src/apm_cli/compilation/context_optimizer.py +3 -2
  10. {apm_cli-0.8.5 → apm_cli-0.8.7}/src/apm_cli/compilation/distributed_compiler.py +4 -1
  11. {apm_cli-0.8.5 → apm_cli-0.8.7}/src/apm_cli/compilation/template_builder.py +3 -3
  12. {apm_cli-0.8.5 → apm_cli-0.8.7}/src/apm_cli/core/auth.py +23 -18
  13. {apm_cli-0.8.5 → apm_cli-0.8.7}/src/apm_cli/deps/github_downloader.py +65 -51
  14. {apm_cli-0.8.5 → apm_cli-0.8.7}/src/apm_cli/deps/lockfile.py +20 -0
  15. apm_cli-0.8.7/src/apm_cli/integration/agent_integrator.py +382 -0
  16. {apm_cli-0.8.5 → apm_cli-0.8.7}/src/apm_cli/integration/base_integrator.py +83 -40
  17. {apm_cli-0.8.5 → apm_cli-0.8.7}/src/apm_cli/integration/command_integrator.py +113 -114
  18. {apm_cli-0.8.5 → apm_cli-0.8.7}/src/apm_cli/integration/hook_integrator.py +40 -0
  19. {apm_cli-0.8.5 → apm_cli-0.8.7}/src/apm_cli/integration/instruction_integrator.py +113 -102
  20. {apm_cli-0.8.5 → apm_cli-0.8.7}/src/apm_cli/integration/prompt_integrator.py +60 -1
  21. {apm_cli-0.8.5 → apm_cli-0.8.7}/src/apm_cli/integration/skill_integrator.py +121 -145
  22. {apm_cli-0.8.5 → apm_cli-0.8.7}/src/apm_cli/integration/targets.py +40 -13
  23. {apm_cli-0.8.5 → apm_cli-0.8.7}/src/apm_cli/models/dependency/reference.py +314 -239
  24. apm_cli-0.8.7/src/apm_cli/utils/file_ops.py +294 -0
  25. {apm_cli-0.8.5 → apm_cli-0.8.7}/src/apm_cli/utils/path_security.py +50 -6
  26. {apm_cli-0.8.5 → apm_cli-0.8.7/src/apm_cli.egg-info}/PKG-INFO +1 -1
  27. {apm_cli-0.8.5 → apm_cli-0.8.7}/src/apm_cli.egg-info/SOURCES.txt +1 -0
  28. {apm_cli-0.8.5 → apm_cli-0.8.7}/tests/test_apm_package_models.py +463 -348
  29. {apm_cli-0.8.5 → apm_cli-0.8.7}/tests/test_github_downloader.py +9 -0
  30. {apm_cli-0.8.5 → apm_cli-0.8.7}/tests/test_lockfile.py +68 -0
  31. apm_cli-0.8.5/src/apm_cli/integration/agent_integrator.py +0 -487
  32. {apm_cli-0.8.5 → apm_cli-0.8.7}/AUTHORS +0 -0
  33. {apm_cli-0.8.5 → apm_cli-0.8.7}/LICENSE +0 -0
  34. {apm_cli-0.8.5 → apm_cli-0.8.7}/README.md +0 -0
  35. {apm_cli-0.8.5 → apm_cli-0.8.7}/setup.cfg +0 -0
  36. {apm_cli-0.8.5 → apm_cli-0.8.7}/src/apm_cli/__init__.py +0 -0
  37. {apm_cli-0.8.5 → apm_cli-0.8.7}/src/apm_cli/adapters/__init__.py +0 -0
  38. {apm_cli-0.8.5 → apm_cli-0.8.7}/src/apm_cli/adapters/client/__init__.py +0 -0
  39. {apm_cli-0.8.5 → apm_cli-0.8.7}/src/apm_cli/adapters/client/base.py +0 -0
  40. {apm_cli-0.8.5 → apm_cli-0.8.7}/src/apm_cli/adapters/client/codex.py +0 -0
  41. {apm_cli-0.8.5 → apm_cli-0.8.7}/src/apm_cli/adapters/client/copilot.py +0 -0
  42. {apm_cli-0.8.5 → apm_cli-0.8.7}/src/apm_cli/adapters/client/cursor.py +0 -0
  43. {apm_cli-0.8.5 → apm_cli-0.8.7}/src/apm_cli/adapters/client/opencode.py +0 -0
  44. {apm_cli-0.8.5 → apm_cli-0.8.7}/src/apm_cli/adapters/client/vscode.py +0 -0
  45. {apm_cli-0.8.5 → apm_cli-0.8.7}/src/apm_cli/adapters/package_manager/__init__.py +0 -0
  46. {apm_cli-0.8.5 → apm_cli-0.8.7}/src/apm_cli/adapters/package_manager/base.py +0 -0
  47. {apm_cli-0.8.5 → apm_cli-0.8.7}/src/apm_cli/adapters/package_manager/default_manager.py +0 -0
  48. {apm_cli-0.8.5 → apm_cli-0.8.7}/src/apm_cli/bundle/__init__.py +0 -0
  49. {apm_cli-0.8.5 → apm_cli-0.8.7}/src/apm_cli/bundle/lockfile_enrichment.py +0 -0
  50. {apm_cli-0.8.5 → apm_cli-0.8.7}/src/apm_cli/bundle/packer.py +0 -0
  51. {apm_cli-0.8.5 → apm_cli-0.8.7}/src/apm_cli/bundle/plugin_exporter.py +0 -0
  52. {apm_cli-0.8.5 → apm_cli-0.8.7}/src/apm_cli/bundle/unpacker.py +0 -0
  53. {apm_cli-0.8.5 → apm_cli-0.8.7}/src/apm_cli/cli.py +0 -0
  54. {apm_cli-0.8.5 → apm_cli-0.8.7}/src/apm_cli/commands/__init__.py +0 -0
  55. {apm_cli-0.8.5 → apm_cli-0.8.7}/src/apm_cli/commands/_helpers.py +0 -0
  56. {apm_cli-0.8.5 → apm_cli-0.8.7}/src/apm_cli/commands/audit.py +0 -0
  57. {apm_cli-0.8.5 → apm_cli-0.8.7}/src/apm_cli/commands/compile/__init__.py +0 -0
  58. {apm_cli-0.8.5 → apm_cli-0.8.7}/src/apm_cli/commands/compile/cli.py +0 -0
  59. {apm_cli-0.8.5 → apm_cli-0.8.7}/src/apm_cli/commands/compile/watcher.py +0 -0
  60. {apm_cli-0.8.5 → apm_cli-0.8.7}/src/apm_cli/commands/config.py +0 -0
  61. {apm_cli-0.8.5 → apm_cli-0.8.7}/src/apm_cli/commands/init.py +0 -0
  62. {apm_cli-0.8.5 → apm_cli-0.8.7}/src/apm_cli/commands/list_cmd.py +0 -0
  63. {apm_cli-0.8.5 → apm_cli-0.8.7}/src/apm_cli/commands/mcp.py +0 -0
  64. {apm_cli-0.8.5 → apm_cli-0.8.7}/src/apm_cli/commands/pack.py +0 -0
  65. {apm_cli-0.8.5 → apm_cli-0.8.7}/src/apm_cli/commands/prune.py +0 -0
  66. {apm_cli-0.8.5 → apm_cli-0.8.7}/src/apm_cli/commands/run.py +0 -0
  67. {apm_cli-0.8.5 → apm_cli-0.8.7}/src/apm_cli/commands/runtime.py +0 -0
  68. {apm_cli-0.8.5 → apm_cli-0.8.7}/src/apm_cli/commands/uninstall/__init__.py +0 -0
  69. {apm_cli-0.8.5 → apm_cli-0.8.7}/src/apm_cli/commands/uninstall/cli.py +0 -0
  70. {apm_cli-0.8.5 → apm_cli-0.8.7}/src/apm_cli/commands/update.py +0 -0
  71. {apm_cli-0.8.5 → apm_cli-0.8.7}/src/apm_cli/compilation/__init__.py +0 -0
  72. {apm_cli-0.8.5 → apm_cli-0.8.7}/src/apm_cli/compilation/agents_compiler.py +0 -0
  73. {apm_cli-0.8.5 → apm_cli-0.8.7}/src/apm_cli/compilation/constants.py +0 -0
  74. {apm_cli-0.8.5 → apm_cli-0.8.7}/src/apm_cli/compilation/constitution.py +0 -0
  75. {apm_cli-0.8.5 → apm_cli-0.8.7}/src/apm_cli/compilation/constitution_block.py +0 -0
  76. {apm_cli-0.8.5 → apm_cli-0.8.7}/src/apm_cli/compilation/injector.py +0 -0
  77. {apm_cli-0.8.5 → apm_cli-0.8.7}/src/apm_cli/compilation/link_resolver.py +0 -0
  78. {apm_cli-0.8.5 → apm_cli-0.8.7}/src/apm_cli/config.py +0 -0
  79. {apm_cli-0.8.5 → apm_cli-0.8.7}/src/apm_cli/constants.py +0 -0
  80. {apm_cli-0.8.5 → apm_cli-0.8.7}/src/apm_cli/core/__init__.py +0 -0
  81. {apm_cli-0.8.5 → apm_cli-0.8.7}/src/apm_cli/core/command_logger.py +0 -0
  82. {apm_cli-0.8.5 → apm_cli-0.8.7}/src/apm_cli/core/conflict_detector.py +0 -0
  83. {apm_cli-0.8.5 → apm_cli-0.8.7}/src/apm_cli/core/docker_args.py +0 -0
  84. {apm_cli-0.8.5 → apm_cli-0.8.7}/src/apm_cli/core/operations.py +0 -0
  85. {apm_cli-0.8.5 → apm_cli-0.8.7}/src/apm_cli/core/safe_installer.py +0 -0
  86. {apm_cli-0.8.5 → apm_cli-0.8.7}/src/apm_cli/core/script_runner.py +0 -0
  87. {apm_cli-0.8.5 → apm_cli-0.8.7}/src/apm_cli/core/target_detection.py +0 -0
  88. {apm_cli-0.8.5 → apm_cli-0.8.7}/src/apm_cli/core/token_manager.py +0 -0
  89. {apm_cli-0.8.5 → apm_cli-0.8.7}/src/apm_cli/deps/__init__.py +0 -0
  90. {apm_cli-0.8.5 → apm_cli-0.8.7}/src/apm_cli/deps/aggregator.py +0 -0
  91. {apm_cli-0.8.5 → apm_cli-0.8.7}/src/apm_cli/deps/apm_resolver.py +0 -0
  92. {apm_cli-0.8.5 → apm_cli-0.8.7}/src/apm_cli/deps/collection_parser.py +0 -0
  93. {apm_cli-0.8.5 → apm_cli-0.8.7}/src/apm_cli/deps/dependency_graph.py +0 -0
  94. {apm_cli-0.8.5 → apm_cli-0.8.7}/src/apm_cli/deps/package_validator.py +0 -0
  95. {apm_cli-0.8.5 → apm_cli-0.8.7}/src/apm_cli/deps/plugin_parser.py +0 -0
  96. {apm_cli-0.8.5 → apm_cli-0.8.7}/src/apm_cli/deps/verifier.py +0 -0
  97. {apm_cli-0.8.5 → apm_cli-0.8.7}/src/apm_cli/drift.py +0 -0
  98. {apm_cli-0.8.5 → apm_cli-0.8.7}/src/apm_cli/factory.py +0 -0
  99. {apm_cli-0.8.5 → apm_cli-0.8.7}/src/apm_cli/integration/__init__.py +0 -0
  100. {apm_cli-0.8.5 → apm_cli-0.8.7}/src/apm_cli/integration/mcp_integrator.py +0 -0
  101. {apm_cli-0.8.5 → apm_cli-0.8.7}/src/apm_cli/integration/skill_transformer.py +0 -0
  102. {apm_cli-0.8.5 → apm_cli-0.8.7}/src/apm_cli/integration/utils.py +0 -0
  103. {apm_cli-0.8.5 → apm_cli-0.8.7}/src/apm_cli/models/__init__.py +0 -0
  104. {apm_cli-0.8.5 → apm_cli-0.8.7}/src/apm_cli/models/apm_package.py +0 -0
  105. {apm_cli-0.8.5 → apm_cli-0.8.7}/src/apm_cli/models/dependency/__init__.py +0 -0
  106. {apm_cli-0.8.5 → apm_cli-0.8.7}/src/apm_cli/models/dependency/mcp.py +0 -0
  107. {apm_cli-0.8.5 → apm_cli-0.8.7}/src/apm_cli/models/dependency/types.py +0 -0
  108. {apm_cli-0.8.5 → apm_cli-0.8.7}/src/apm_cli/models/plugin.py +0 -0
  109. {apm_cli-0.8.5 → apm_cli-0.8.7}/src/apm_cli/models/results.py +0 -0
  110. {apm_cli-0.8.5 → apm_cli-0.8.7}/src/apm_cli/models/validation.py +0 -0
  111. {apm_cli-0.8.5 → apm_cli-0.8.7}/src/apm_cli/output/__init__.py +0 -0
  112. {apm_cli-0.8.5 → apm_cli-0.8.7}/src/apm_cli/output/formatters.py +0 -0
  113. {apm_cli-0.8.5 → apm_cli-0.8.7}/src/apm_cli/output/models.py +0 -0
  114. {apm_cli-0.8.5 → apm_cli-0.8.7}/src/apm_cli/output/script_formatters.py +0 -0
  115. {apm_cli-0.8.5 → apm_cli-0.8.7}/src/apm_cli/policy/__init__.py +0 -0
  116. {apm_cli-0.8.5 → apm_cli-0.8.7}/src/apm_cli/policy/ci_checks.py +0 -0
  117. {apm_cli-0.8.5 → apm_cli-0.8.7}/src/apm_cli/policy/discovery.py +0 -0
  118. {apm_cli-0.8.5 → apm_cli-0.8.7}/src/apm_cli/policy/inheritance.py +0 -0
  119. {apm_cli-0.8.5 → apm_cli-0.8.7}/src/apm_cli/policy/matcher.py +0 -0
  120. {apm_cli-0.8.5 → apm_cli-0.8.7}/src/apm_cli/policy/models.py +0 -0
  121. {apm_cli-0.8.5 → apm_cli-0.8.7}/src/apm_cli/policy/parser.py +0 -0
  122. {apm_cli-0.8.5 → apm_cli-0.8.7}/src/apm_cli/policy/policy_checks.py +0 -0
  123. {apm_cli-0.8.5 → apm_cli-0.8.7}/src/apm_cli/policy/schema.py +0 -0
  124. {apm_cli-0.8.5 → apm_cli-0.8.7}/src/apm_cli/primitives/__init__.py +0 -0
  125. {apm_cli-0.8.5 → apm_cli-0.8.7}/src/apm_cli/primitives/discovery.py +0 -0
  126. {apm_cli-0.8.5 → apm_cli-0.8.7}/src/apm_cli/primitives/models.py +0 -0
  127. {apm_cli-0.8.5 → apm_cli-0.8.7}/src/apm_cli/primitives/parser.py +0 -0
  128. {apm_cli-0.8.5 → apm_cli-0.8.7}/src/apm_cli/registry/__init__.py +0 -0
  129. {apm_cli-0.8.5 → apm_cli-0.8.7}/src/apm_cli/registry/client.py +0 -0
  130. {apm_cli-0.8.5 → apm_cli-0.8.7}/src/apm_cli/registry/integration.py +0 -0
  131. {apm_cli-0.8.5 → apm_cli-0.8.7}/src/apm_cli/registry/operations.py +0 -0
  132. {apm_cli-0.8.5 → apm_cli-0.8.7}/src/apm_cli/runtime/__init__.py +0 -0
  133. {apm_cli-0.8.5 → apm_cli-0.8.7}/src/apm_cli/runtime/base.py +0 -0
  134. {apm_cli-0.8.5 → apm_cli-0.8.7}/src/apm_cli/runtime/codex_runtime.py +0 -0
  135. {apm_cli-0.8.5 → apm_cli-0.8.7}/src/apm_cli/runtime/copilot_runtime.py +0 -0
  136. {apm_cli-0.8.5 → apm_cli-0.8.7}/src/apm_cli/runtime/factory.py +0 -0
  137. {apm_cli-0.8.5 → apm_cli-0.8.7}/src/apm_cli/runtime/llm_runtime.py +0 -0
  138. {apm_cli-0.8.5 → apm_cli-0.8.7}/src/apm_cli/runtime/manager.py +0 -0
  139. {apm_cli-0.8.5 → apm_cli-0.8.7}/src/apm_cli/security/__init__.py +0 -0
  140. {apm_cli-0.8.5 → apm_cli-0.8.7}/src/apm_cli/security/audit_report.py +0 -0
  141. {apm_cli-0.8.5 → apm_cli-0.8.7}/src/apm_cli/security/content_scanner.py +0 -0
  142. {apm_cli-0.8.5 → apm_cli-0.8.7}/src/apm_cli/security/file_scanner.py +0 -0
  143. {apm_cli-0.8.5 → apm_cli-0.8.7}/src/apm_cli/security/gate.py +0 -0
  144. {apm_cli-0.8.5 → apm_cli-0.8.7}/src/apm_cli/utils/__init__.py +0 -0
  145. {apm_cli-0.8.5 → apm_cli-0.8.7}/src/apm_cli/utils/console.py +0 -0
  146. {apm_cli-0.8.5 → apm_cli-0.8.7}/src/apm_cli/utils/content_hash.py +0 -0
  147. {apm_cli-0.8.5 → apm_cli-0.8.7}/src/apm_cli/utils/diagnostics.py +0 -0
  148. {apm_cli-0.8.5 → apm_cli-0.8.7}/src/apm_cli/utils/github_host.py +0 -0
  149. {apm_cli-0.8.5 → apm_cli-0.8.7}/src/apm_cli/utils/helpers.py +0 -0
  150. {apm_cli-0.8.5 → apm_cli-0.8.7}/src/apm_cli/utils/paths.py +0 -0
  151. {apm_cli-0.8.5 → apm_cli-0.8.7}/src/apm_cli/utils/version_checker.py +0 -0
  152. {apm_cli-0.8.5 → apm_cli-0.8.7}/src/apm_cli/utils/yaml_io.py +0 -0
  153. {apm_cli-0.8.5 → apm_cli-0.8.7}/src/apm_cli/version.py +0 -0
  154. {apm_cli-0.8.5 → apm_cli-0.8.7}/src/apm_cli/workflow/__init__.py +0 -0
  155. {apm_cli-0.8.5 → apm_cli-0.8.7}/src/apm_cli/workflow/discovery.py +0 -0
  156. {apm_cli-0.8.5 → apm_cli-0.8.7}/src/apm_cli/workflow/parser.py +0 -0
  157. {apm_cli-0.8.5 → apm_cli-0.8.7}/src/apm_cli/workflow/runner.py +0 -0
  158. {apm_cli-0.8.5 → apm_cli-0.8.7}/src/apm_cli.egg-info/dependency_links.txt +0 -0
  159. {apm_cli-0.8.5 → apm_cli-0.8.7}/src/apm_cli.egg-info/entry_points.txt +0 -0
  160. {apm_cli-0.8.5 → apm_cli-0.8.7}/src/apm_cli.egg-info/requires.txt +0 -0
  161. {apm_cli-0.8.5 → apm_cli-0.8.7}/src/apm_cli.egg-info/top_level.txt +0 -0
  162. {apm_cli-0.8.5 → apm_cli-0.8.7}/tests/test_apm_resolver.py +0 -0
  163. {apm_cli-0.8.5 → apm_cli-0.8.7}/tests/test_codex_docker_args_fix.py +0 -0
  164. {apm_cli-0.8.5 → apm_cli-0.8.7}/tests/test_codex_empty_string_and_defaults.py +0 -0
  165. {apm_cli-0.8.5 → apm_cli-0.8.7}/tests/test_collision_integration.py +0 -0
  166. {apm_cli-0.8.5 → apm_cli-0.8.7}/tests/test_console.py +0 -0
  167. {apm_cli-0.8.5 → apm_cli-0.8.7}/tests/test_distributed_compilation.py +0 -0
  168. {apm_cli-0.8.5 → apm_cli-0.8.7}/tests/test_empty_string_and_defaults.py +0 -0
  169. {apm_cli-0.8.5 → apm_cli-0.8.7}/tests/test_enhanced_discovery.py +0 -0
  170. {apm_cli-0.8.5 → apm_cli-0.8.7}/tests/test_github_downloader_token_precedence.py +0 -0
  171. {apm_cli-0.8.5 → apm_cli-0.8.7}/tests/test_runnable_prompts.py +0 -0
  172. {apm_cli-0.8.5 → apm_cli-0.8.7}/tests/test_runtime_manager_token_precedence.py +0 -0
  173. {apm_cli-0.8.5 → apm_cli-0.8.7}/tests/test_token_manager.py +0 -0
  174. {apm_cli-0.8.5 → apm_cli-0.8.7}/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.8.5
3
+ Version: 0.8.7
4
4
  Summary: MCP configuration tool
5
5
  Author-email: Daniel Meppiel <user@example.com>
6
6
  License: MIT License
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "apm-cli"
7
- version = "0.8.5"
7
+ version = "0.8.7"
8
8
  description = "MCP configuration tool"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.10"
@@ -9,8 +9,6 @@ from ._utils import (
9
9
  _get_detailed_context_counts,
10
10
  _get_package_display_info,
11
11
  _get_detailed_package_info,
12
- _update_single_package,
13
- _update_all_packages,
14
12
  )
15
13
 
16
14
  __all__ = [
@@ -29,6 +27,4 @@ __all__ = [
29
27
  "_get_detailed_context_counts",
30
28
  "_get_package_display_info",
31
29
  "_get_detailed_package_info",
32
- "_update_single_package",
33
- "_update_all_packages",
34
30
  ]
@@ -1,11 +1,10 @@
1
1
  """Utility helpers for APM dependency commands."""
2
2
 
3
3
  from pathlib import Path
4
- from typing import Any, Dict, List, Optional
4
+ from typing import Any, Dict
5
5
 
6
- from ...constants import APM_DIR, APM_MODULES_DIR, APM_YML_FILENAME, SKILL_MD_FILENAME
6
+ from ...constants import APM_DIR, APM_YML_FILENAME, SKILL_MD_FILENAME
7
7
  from ...models.apm_package import APMPackage
8
- from ...deps.github_downloader import GitHubPackageDownloader
9
8
 
10
9
 
11
10
  def _scan_installed_packages(apm_modules_dir: Path) -> list:
@@ -221,106 +220,3 @@ def _get_detailed_package_info(package_path: Path) -> Dict[str, Any]:
221
220
  'workflows': 0,
222
221
  'hooks': 0
223
222
  }
224
-
225
-
226
- def _update_single_package(package_name: str, project_deps: List, apm_modules_path: Path, logger=None):
227
- """Update a specific package."""
228
- if logger is None:
229
- from ...core.command_logger import CommandLogger
230
- logger = CommandLogger("deps-update")
231
-
232
- # Find the dependency reference for this package
233
- target_dep = None
234
- for dep in project_deps:
235
- if dep.get_display_name() == package_name or dep.repo_url.split('/')[-1] == package_name:
236
- target_dep = dep
237
- break
238
-
239
- if not target_dep:
240
- logger.error(f"Package '{package_name}' not found in apm.yml dependencies")
241
- return
242
-
243
- # Find the installed package directory using namespaced structure
244
- # GitHub: owner/repo (2 parts)
245
- # Azure DevOps: org/project/repo (3 parts)
246
- package_dir = None
247
- if target_dep.alias:
248
- package_dir = apm_modules_path / target_dep.alias
249
- else:
250
- # Parse path from repo_url
251
- repo_parts = target_dep.repo_url.split('/')
252
- if target_dep.is_azure_devops() and len(repo_parts) >= 3:
253
- # ADO structure: apm_modules/org/project/repo
254
- package_dir = apm_modules_path / repo_parts[0] / repo_parts[1] / repo_parts[2]
255
- elif len(repo_parts) >= 2:
256
- package_dir = apm_modules_path / repo_parts[0] / repo_parts[1]
257
- else:
258
- # Fallback to simple name matching
259
- package_dir = apm_modules_path / package_name
260
-
261
- if not package_dir.exists():
262
- logger.error(f"Package '{package_name}' not installed in apm_modules/")
263
- logger.progress(f"Run 'apm install' to install it first")
264
- return
265
-
266
- try:
267
- downloader = GitHubPackageDownloader()
268
- logger.progress(f"Updating {target_dep.repo_url}...")
269
-
270
- # Download latest version
271
- package_info = downloader.download_package(target_dep, package_dir)
272
-
273
- logger.success(f"Updated {target_dep.repo_url}")
274
-
275
- except Exception as e:
276
- logger.error(f"Failed to update {package_name}: {e}")
277
-
278
-
279
- def _update_all_packages(project_deps: List, apm_modules_path: Path, logger=None):
280
- """Update all packages."""
281
- if logger is None:
282
- from ...core.command_logger import CommandLogger
283
- logger = CommandLogger("deps-update")
284
-
285
- if not project_deps:
286
- logger.progress("No APM dependencies to update")
287
- return
288
-
289
- logger.start(f"Updating {len(project_deps)} APM dependencies...")
290
-
291
- downloader = GitHubPackageDownloader()
292
- updated_count = 0
293
-
294
- for dep in project_deps:
295
- # Determine package directory using namespaced structure
296
- # GitHub: apm_modules/owner/repo (2 parts)
297
- # Azure DevOps: apm_modules/org/project/repo (3 parts)
298
- if dep.alias:
299
- package_dir = apm_modules_path / dep.alias
300
- else:
301
- # Parse path from repo_url
302
- repo_parts = dep.repo_url.split('/')
303
- if dep.is_azure_devops() and len(repo_parts) >= 3:
304
- # ADO structure
305
- package_dir = apm_modules_path / repo_parts[0] / repo_parts[1] / repo_parts[2]
306
- elif len(repo_parts) >= 2:
307
- package_dir = apm_modules_path / repo_parts[0] / repo_parts[1]
308
- else:
309
- # Fallback to simple repo name (shouldn't happen)
310
- package_dir = apm_modules_path / dep.repo_url
311
-
312
- if not package_dir.exists():
313
- logger.warning(f"{dep.repo_url} not installed - skipping")
314
- continue
315
-
316
- try:
317
- logger.verbose_detail(f" Updating {dep.repo_url}...")
318
- package_info = downloader.download_package(dep, package_dir)
319
- updated_count += 1
320
- logger.success(f" {dep.repo_url}")
321
-
322
- except Exception as e:
323
- logger.error(f" Failed to update {dep.repo_url}: {e}")
324
- continue
325
-
326
- logger.success(f"Updated {updated_count} of {len(project_deps)} packages")
@@ -11,10 +11,6 @@ from ...constants import APM_DIR, APM_MODULES_DIR, APM_YML_FILENAME, SKILL_MD_FI
11
11
  from ...models.apm_package import APMPackage, ValidationResult, validate_apm_package
12
12
  from ...core.command_logger import CommandLogger
13
13
 
14
- # Import APM dependency system components (with fallback)
15
- from ...deps.github_downloader import GitHubPackageDownloader
16
- from ...deps.apm_resolver import APMDependencyResolver
17
-
18
14
  from ._utils import (
19
15
  _is_nested_under_package,
20
16
  _count_primitives,
@@ -23,8 +19,6 @@ from ._utils import (
23
19
  _get_detailed_context_counts,
24
20
  _get_package_display_info,
25
21
  _get_detailed_package_info,
26
- _update_single_package,
27
- _update_all_packages,
28
22
  )
29
23
 
30
24
 
@@ -443,43 +437,188 @@ def clean(dry_run: bool, yes: bool):
443
437
  sys.exit(1)
444
438
 
445
439
 
446
- @deps.command(help="Update APM dependencies")
447
- @click.argument('package', required=False)
448
- def update(package: Optional[str]):
449
- """Update specific package or all if no package specified."""
450
- logger = CommandLogger("deps-update")
440
+ @deps.command(help="Update APM dependencies to latest refs")
441
+ @click.argument("packages", nargs=-1)
442
+ @click.option("--verbose", "-v", is_flag=True, help="Show detailed update information")
443
+ @click.option(
444
+ "--force", is_flag=True,
445
+ help="Overwrite locally-authored files on collision",
446
+ )
447
+ @click.option(
448
+ "--target", "-t",
449
+ type=click.Choice(
450
+ ["copilot", "claude", "cursor", "opencode", "vscode", "agents", "all"],
451
+ case_sensitive=False,
452
+ ),
453
+ default=None,
454
+ help="Force deployment to a specific target (overrides auto-detection)",
455
+ )
456
+ @click.option(
457
+ "--parallel-downloads",
458
+ type=int,
459
+ default=4,
460
+ show_default=True,
461
+ help="Max concurrent package downloads (0 to disable parallelism)",
462
+ )
463
+ def update(packages, verbose, force, target, parallel_downloads):
464
+ """Update APM dependencies to latest git refs.
465
+
466
+ Re-resolves git references (branches/tags) to their current SHAs,
467
+ downloads updated content, re-integrates primitives, and regenerates
468
+ the lockfile.
469
+
470
+ \b
471
+ Examples:
472
+ apm deps update # Update all packages
473
+ apm deps update org/repo # Update one package
474
+ apm deps update org/a org/b # Update specific packages
475
+ apm deps update --verbose # Show detailed progress
476
+ """
477
+ from ..install import (
478
+ _install_apm_dependencies,
479
+ APM_DEPS_AVAILABLE,
480
+ _APM_IMPORT_ERROR,
481
+ )
482
+ from ...core.command_logger import InstallLogger
483
+ from ...core.auth import AuthResolver
484
+
485
+ logger = InstallLogger(verbose=verbose, partial=bool(packages))
486
+
487
+ if not APM_DEPS_AVAILABLE:
488
+ logger.error("APM dependency system not available")
489
+ if _APM_IMPORT_ERROR:
490
+ logger.progress(f"Import error: {_APM_IMPORT_ERROR}")
491
+ sys.exit(1)
492
+
493
+ project_root = Path.cwd()
494
+ apm_yml_path = project_root / APM_YML_FILENAME
495
+
496
+ if not apm_yml_path.exists():
497
+ logger.error(f"No {APM_YML_FILENAME} found in current directory")
498
+ sys.exit(1)
451
499
 
452
- project_root = Path(".")
453
- apm_modules_path = project_root / APM_MODULES_DIR
454
-
455
- if not apm_modules_path.exists():
456
- logger.progress("No apm_modules/ directory found - no packages to update")
457
- return
458
-
459
- # Get project dependencies to validate updates
460
500
  try:
461
- apm_yml_path = project_root / APM_YML_FILENAME
462
- if not apm_yml_path.exists():
463
- logger.error(f"No {APM_YML_FILENAME} found in current directory")
464
- return
465
-
466
- project_package = APMPackage.from_apm_yml(apm_yml_path)
467
- project_deps = project_package.get_apm_dependencies()
468
-
469
- if not project_deps:
470
- logger.progress("No APM dependencies defined in apm.yml")
471
- return
472
-
501
+ apm_package = APMPackage.from_apm_yml(apm_yml_path)
473
502
  except Exception as e:
474
- logger.error(f"Error reading {APM_YML_FILENAME}: {e}")
503
+ logger.error(f"Failed to parse {APM_YML_FILENAME}: {e}")
504
+ sys.exit(1)
505
+
506
+ all_deps = apm_package.get_apm_dependencies() + apm_package.get_dev_apm_dependencies()
507
+ if not all_deps:
508
+ logger.progress("No APM dependencies defined in apm.yml")
475
509
  return
476
-
477
- if package:
478
- # Update specific package
479
- _update_single_package(package, project_deps, apm_modules_path, logger=logger)
510
+
511
+ # Validate and normalize requested packages to canonical dependency keys.
512
+ # The install engine matches only_packages by DependencyReference identity
513
+ # (e.g. "owner/repo"), so short names like "compliance-rules" must be
514
+ # mapped to their canonical form before calling the engine.
515
+ only_pkgs = None
516
+ if packages:
517
+ token_to_canonical: Dict[str, str] = {}
518
+ for dep in all_deps:
519
+ canonical_key = dep.get_unique_key() or dep.repo_url or dep.get_display_name()
520
+ tokens = {canonical_key, dep.get_display_name(), dep.repo_url}
521
+ if hasattr(dep, "alias") and dep.alias:
522
+ tokens.add(dep.alias)
523
+ parts = dep.repo_url.split("/")
524
+ if len(parts) >= 2:
525
+ tokens.add(parts[-1])
526
+ for token in tokens:
527
+ if token and token not in token_to_canonical:
528
+ token_to_canonical[token] = canonical_key
529
+
530
+ only_pkgs = []
531
+ seen: Dict[str, bool] = {}
532
+ for pkg in packages:
533
+ canonical = token_to_canonical.get(pkg)
534
+ if not canonical:
535
+ available = ", ".join(dep.get_display_name() for dep in all_deps)
536
+ logger.error(f"Package '{pkg}' not found in {APM_YML_FILENAME}")
537
+ logger.progress(f"Available: {available}")
538
+ sys.exit(1)
539
+ if canonical not in seen:
540
+ seen[canonical] = True
541
+ only_pkgs.append(canonical)
542
+
543
+ # Migrate legacy lockfile first, then snapshot SHAs for before/after diff
544
+ from ...deps.lockfile import LockFile, get_lockfile_path, migrate_lockfile_if_needed
545
+
546
+ lockfile_path = get_lockfile_path(project_root)
547
+ migrate_lockfile_if_needed(project_root)
548
+
549
+ old_lockfile = LockFile.read(lockfile_path)
550
+ had_baseline = old_lockfile is not None
551
+ old_shas: dict = {}
552
+ if old_lockfile:
553
+ for key, dep in old_lockfile.dependencies.items():
554
+ old_shas[key] = dep.resolved_commit
555
+
556
+ auth_resolver = AuthResolver()
557
+
558
+ if packages:
559
+ noun = f"{len(packages)} package(s)"
560
+ else:
561
+ noun = f"all {len(all_deps)} dependencies"
562
+ logger.start(f"Updating {noun}...")
563
+
564
+ try:
565
+ install_result = _install_apm_dependencies(
566
+ apm_package,
567
+ update_refs=True,
568
+ verbose=verbose,
569
+ only_packages=only_pkgs,
570
+ force=force,
571
+ parallel_downloads=parallel_downloads,
572
+ logger=logger,
573
+ auth_resolver=auth_resolver,
574
+ target=target,
575
+ )
576
+ except Exception as e:
577
+ logger.error(f"Update failed: {e}")
578
+ if not verbose:
579
+ logger.progress("Run with --verbose for detailed diagnostics")
580
+ sys.exit(1)
581
+
582
+ # Show diagnostics if any
583
+ if install_result.diagnostics and install_result.diagnostics.has_diagnostics:
584
+ install_result.diagnostics.render_summary()
585
+
586
+ # Compare old vs new lockfile SHAs to show what changed
587
+ new_lockfile = LockFile.read(lockfile_path)
588
+ changed: list = []
589
+ if new_lockfile:
590
+ for key, dep in new_lockfile.dependencies.items():
591
+ old_sha = old_shas.get(key)
592
+ new_sha = dep.resolved_commit
593
+ if old_sha and new_sha and old_sha != new_sha:
594
+ changed.append(
595
+ (key, old_sha[:8], new_sha[:8], dep.resolved_ref or "")
596
+ )
597
+
598
+ error_count = 0
599
+ if install_result.diagnostics:
600
+ try:
601
+ error_count = int(install_result.diagnostics.error_count)
602
+ except (TypeError, ValueError):
603
+ error_count = 0
604
+
605
+ if changed:
606
+ pkg_noun = "package" if len(changed) == 1 else "packages"
607
+ if error_count > 0:
608
+ logger.warning(
609
+ f"Updated {len(changed)} {pkg_noun} with {error_count} error(s)."
610
+ )
611
+ else:
612
+ logger.success(f"Updated {len(changed)} {pkg_noun}:")
613
+ for key, old_sha, new_sha, ref in changed:
614
+ ref_str = f" ({ref})" if ref else ""
615
+ click.echo(f" {key}{ref_str}: {old_sha} -> {new_sha}")
616
+ elif error_count > 0:
617
+ logger.error(f"Update failed with {error_count} error(s).")
618
+ elif not had_baseline:
619
+ logger.success("Update complete.")
480
620
  else:
481
- # Update all packages
482
- _update_all_packages(project_deps, apm_modules_path, logger=logger)
621
+ logger.success("All packages already at latest refs.")
483
622
 
484
623
 
485
624
  @deps.command(help="Show detailed package information")