py-wlcli 0.8.1__tar.gz → 0.9.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 (326) hide show
  1. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/PKG-INFO +1 -1
  2. py_wlcli-0.9.0/VERSION +1 -0
  3. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/pyproject.toml +5 -0
  4. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/capabilities.py +6 -1
  5. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/cc/checks.py +176 -1
  6. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/cc/cli.py +97 -3
  7. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/cc/mutate.py +31 -8
  8. py_wlcli-0.9.0/src/wl_cli/cc/schemas/cc_check.schema.json +560 -0
  9. py_wlcli-0.9.0/src/wl_cli/cc/token.py +528 -0
  10. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/cli_click.py +1 -0
  11. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/env/cli.py +17 -4
  12. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/env_status.py +93 -13
  13. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/mcp/gitlab.py +29 -43
  14. py_wlcli-0.9.0/src/wl_cli/utils/credentials.py +179 -0
  15. py_wlcli-0.8.1/VERSION +0 -1
  16. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/.gitignore +0 -0
  17. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/LICENSE +0 -0
  18. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/README.md +0 -0
  19. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/__init__.py +0 -0
  20. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/__init__.py +0 -0
  21. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/__main__.py +0 -0
  22. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/cc/__init__.py +0 -0
  23. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/__init__.py +0 -0
  24. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/base.py +0 -0
  25. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/buildcommands/__init__.py +0 -0
  26. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/buildcommands/build.py +0 -0
  27. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/buildcommands/build_utils.py +0 -0
  28. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/buildcommands/builders/__init__.py +0 -0
  29. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/buildcommands/builders/cleanup.py +0 -0
  30. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/buildcommands/builders/coordinator.py +0 -0
  31. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/buildcommands/builders/environment.py +0 -0
  32. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/buildcommands/builders/rust_builder.py +0 -0
  33. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/buildcommands/builders/stubs.py +0 -0
  34. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/buildcommands/dist.py +0 -0
  35. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/buildcommands/test.py +0 -0
  36. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/clean/__init__.py +0 -0
  37. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/clean/build.py +0 -0
  38. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/clean/clean.py +0 -0
  39. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/clean/clean_utils.py +0 -0
  40. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/clean/core.py +0 -0
  41. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/clean/dead_code/__init__.py +0 -0
  42. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/clean/dead_code/dead_code_command.py +0 -0
  43. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/clean/dead_code/detector.py +0 -0
  44. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/clean/dead_code/fixer.py +0 -0
  45. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/clean/dead_code/reporter.py +0 -0
  46. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/clean/dead_code/utils.py +0 -0
  47. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/clean/lfs.py +0 -0
  48. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/clean/python.py +0 -0
  49. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/clean/rust.py +0 -0
  50. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/clean/utils/__init__.py +0 -0
  51. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/clean/venv.py +0 -0
  52. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/cleanup.py +0 -0
  53. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/click_base.py +0 -0
  54. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/config/__init__.py +0 -0
  55. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/config/config.py +0 -0
  56. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/debug/__init__.py +0 -0
  57. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/debug/debug.py +0 -0
  58. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/debug/debug_cache.py +0 -0
  59. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/debug/debug_subagent.py +0 -0
  60. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/debug/output_formatter.py +0 -0
  61. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/debug/source_hasher.py +0 -0
  62. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/format/__init__.py +0 -0
  63. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/format/format_cache_adapter.py +0 -0
  64. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/format/format_command.py +0 -0
  65. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/format/format_coordinator.py +0 -0
  66. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/format/format_executor.py +0 -0
  67. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/format/format_outcome.py +0 -0
  68. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/format/format_path_handler.py +0 -0
  69. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/format/format_progress.py +0 -0
  70. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/format/format_reporter.py +0 -0
  71. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/format/python_formatter.py +0 -0
  72. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/format/rust_formatter.py +0 -0
  73. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/gate/__init__.py +0 -0
  74. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/gate/gate_command.py +0 -0
  75. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/gate/preflight.py +0 -0
  76. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/git/__init__.py +0 -0
  77. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/git/config.py +0 -0
  78. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/git/git_facts.py +0 -0
  79. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/git/git_flow.py +0 -0
  80. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/git/hook.py +0 -0
  81. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/git/policy.py +0 -0
  82. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/git/push_update.py +0 -0
  83. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/initenv/__init__.py +0 -0
  84. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/initenv/common/__init__.py +0 -0
  85. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/initenv/common/check_git_bash.py +0 -0
  86. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/initenv/common/error_handler.py +0 -0
  87. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/initenv/common/exceptions.py +0 -0
  88. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/initenv/components/__init__.py +0 -0
  89. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/initenv/components/cargo_sync.py +0 -0
  90. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/initenv/components/config_manager.py +0 -0
  91. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/initenv/components/directory_utils.py +0 -0
  92. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/initenv/components/git/__init__.py +0 -0
  93. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/initenv/components/git/branch_creator.py +0 -0
  94. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/initenv/components/git/git_flow_interface.py +0 -0
  95. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/initenv/components/git/git_flow_manager.py +0 -0
  96. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/initenv/components/git/git_lfs_manager.py +0 -0
  97. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/initenv/components/git/git_utility.py +0 -0
  98. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/initenv/components/git/gitignore_manager.py +0 -0
  99. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/initenv/components/git_initializer.py +0 -0
  100. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/initenv/components/i18n_manager.py +0 -0
  101. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/initenv/components/log_manager.py +0 -0
  102. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/initenv/components/project_structure/__init__.py +0 -0
  103. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/initenv/components/project_structure/config_generator.py +0 -0
  104. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/initenv/components/project_structure/directory_creator.py +0 -0
  105. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/initenv/components/project_structure/hook_source.py +0 -0
  106. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/initenv/components/project_structure/hooks_manager.py +0 -0
  107. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/initenv/components/project_structure/readme_handler.py +0 -0
  108. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/initenv/components/project_structure/rust_files_handler.py +0 -0
  109. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/initenv/components/project_structure/setup_handler.py +0 -0
  110. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/initenv/components/project_structure/sop_generator.py +0 -0
  111. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/initenv/components/project_structure/template_copier.py +0 -0
  112. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/initenv/components/project_structure/template_manager.py +0 -0
  113. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/initenv/components/pyproject_generator.py +0 -0
  114. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/initenv/components/rust_initializer.py +0 -0
  115. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/initenv/components/symlink_cleaner.py +0 -0
  116. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/initenv/components/symlink_manager.py +0 -0
  117. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/initenv/components/venv_manager.py +0 -0
  118. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/initenv/initenv.py +0 -0
  119. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/initenv/services/__init__.py +0 -0
  120. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/initenv/services/environment_initializer.py +0 -0
  121. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/initenv/services/git_lfs_initializer.py +0 -0
  122. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/initenv/services/project_structure_initializer.py +0 -0
  123. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/lfs/README.md +0 -0
  124. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/lfs/__init__.py +0 -0
  125. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/lfs/cli.py +0 -0
  126. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/lfs/config.py +0 -0
  127. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/lfs/hook.py +0 -0
  128. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/lfs/initializer.py +0 -0
  129. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/lfs/manager.py +0 -0
  130. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/lfs/policy.py +0 -0
  131. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/lfs/watcher.py +0 -0
  132. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/lint/__init__.py +0 -0
  133. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/lint/lint_command.py +0 -0
  134. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/lint/lint_executor.py +0 -0
  135. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/lint/lint_reporter.py +0 -0
  136. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/lint/lint_run.py +0 -0
  137. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/lint/mypy_config.py +0 -0
  138. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/registry.py +0 -0
  139. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/self/__init__.py +0 -0
  140. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/self/common/__init__.py +0 -0
  141. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/self/common/capabilities.py +0 -0
  142. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/self/common/config.py +0 -0
  143. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/self/common/version_cache.py +0 -0
  144. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/self/handlers/__init__.py +0 -0
  145. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/self/handlers/base_handler.py +0 -0
  146. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/self/handlers/install_handler.py +0 -0
  147. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/self/handlers/status_handler.py +0 -0
  148. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/self/handlers/uninstall_handler.py +0 -0
  149. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/self/handlers/update_handler.py +0 -0
  150. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/self/handlers/version_handler.py +0 -0
  151. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/self/self_command.py +0 -0
  152. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/self/services/__init__.py +0 -0
  153. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/self/services/installation_manager.py +0 -0
  154. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/self/services/local_installer.py +0 -0
  155. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/self/services/pypi_updater.py +0 -0
  156. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/self/services/windows_update.py +0 -0
  157. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/testcommands/__init__.py +0 -0
  158. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/testcommands/base_dependency_analyzer.py +0 -0
  159. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/testcommands/batch_processor.py +0 -0
  160. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/testcommands/cache_manager.py +0 -0
  161. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/testcommands/coverage_analyzer.py +0 -0
  162. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/testcommands/coverage_cache_manager.py +0 -0
  163. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/testcommands/progress_manager.py +0 -0
  164. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/testcommands/python_env_detector.py +0 -0
  165. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/testcommands/report_generator.py +0 -0
  166. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/testcommands/single_test_executor.py +0 -0
  167. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/testcommands/speed_checker.py +0 -0
  168. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/testcommands/test_command_builder.py +0 -0
  169. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/testcommands/test_commands.py +0 -0
  170. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/testcommands/test_reporter.py +0 -0
  171. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/testcommands/test_result_handler.py +0 -0
  172. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/testcommands/test_runner.py +0 -0
  173. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/testcommands/test_utils.py +0 -0
  174. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/testcommands/utils/__init__.py +0 -0
  175. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/testcommands/utils/coverage_parser.py +0 -0
  176. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/testcommands/utils/env_info.py +0 -0
  177. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/testcommands/utils/junit_parser.py +0 -0
  178. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/testcommands/utils/markdown_utils.py +0 -0
  179. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/testcommands/utils/project_root.py +0 -0
  180. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/update/__init__.py +0 -0
  181. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/update/services/__init__.py +0 -0
  182. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/update/services/backup_manager.py +0 -0
  183. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/update/services/component_manager.py +0 -0
  184. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/update/services/conflict_resolver.py +0 -0
  185. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/update/services/vendors_updater.py +0 -0
  186. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/update/services/version_tracker.py +0 -0
  187. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/update/update_command.py +0 -0
  188. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/update/utils/__init__.py +0 -0
  189. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/version/__init__.py +0 -0
  190. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/version/version_command.py +0 -0
  191. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/workflow.py +0 -0
  192. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/env/__init__.py +0 -0
  193. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/envelope.py +0 -0
  194. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/exceptions.py +0 -0
  195. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/lib/__init__.py +0 -0
  196. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/lib/rust_utils.py +0 -0
  197. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/mcp/__init__.py +0 -0
  198. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/mcp/capabilities.py +0 -0
  199. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/mcp/cli.py +0 -0
  200. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/mcp/k8s.py +0 -0
  201. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/mcp/protocol.py +0 -0
  202. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/platform.py +0 -0
  203. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/quality/__init__.py +0 -0
  204. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/utils/__init__.py +0 -0
  205. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/utils/cache.py +0 -0
  206. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/utils/cache_ledger.py +0 -0
  207. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/utils/cache_store.py +0 -0
  208. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/utils/config/__init__.py +0 -0
  209. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/utils/config/config_loader.py +0 -0
  210. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/utils/config/core.py +0 -0
  211. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/utils/config/defaults.py +0 -0
  212. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/utils/config/env_exporter.py +0 -0
  213. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/utils/config/env_parser.py +0 -0
  214. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/utils/config/validation.py +0 -0
  215. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/utils/error_handler.py +0 -0
  216. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/utils/file_copier.py +0 -0
  217. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/utils/file_operations.py +0 -0
  218. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/utils/language_utils.py +0 -0
  219. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/utils/lazy_import.py +0 -0
  220. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/utils/log_levels.py +0 -0
  221. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/utils/log_rotators.py +0 -0
  222. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/utils/logging.py +0 -0
  223. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/utils/output_context.py +0 -0
  224. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/utils/performance/__init__.py +0 -0
  225. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/utils/performance/decorators.py +0 -0
  226. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/utils/performance/exporter.py +0 -0
  227. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/utils/performance/models.py +0 -0
  228. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/utils/performance/monitor.py +0 -0
  229. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/utils/performance_monitor.py +0 -0
  230. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/utils/platform_adapter.py +0 -0
  231. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/utils/pre_commit.py +0 -0
  232. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/utils/pre_commit_config.py +0 -0
  233. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/utils/root.py +0 -0
  234. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/utils/root_fallback.py +0 -0
  235. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/utils/run_evidence.py +0 -0
  236. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/utils/structured_logger.py +0 -0
  237. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/utils/structured_logging/__init__.py +0 -0
  238. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/utils/structured_logging/config.py +0 -0
  239. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/utils/structured_logging/core.py +0 -0
  240. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/utils/structured_logging/env.py +0 -0
  241. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/utils/structured_logging/filtering.py +0 -0
  242. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/utils/structured_logging/filters.py +0 -0
  243. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/utils/structured_logging/formatters.py +0 -0
  244. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/utils/structured_logging/handlers.py +0 -0
  245. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/utils/structured_logging/logger.py +0 -0
  246. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/utils/subprocess.py +0 -0
  247. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/utils/subprocess_utils.py +0 -0
  248. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/utils/test_utils/__init__.py +0 -0
  249. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/utils/test_utils/test_filter.py +0 -0
  250. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/utils/uv_run.py +0 -0
  251. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/utils/uv_tool.py +0 -0
  252. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/utils/uv_tree.py +0 -0
  253. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/utils/uv_workspace.py +0 -0
  254. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/utils/version/__init__.py +0 -0
  255. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/utils/version/pypi_version_checker.py +0 -0
  256. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/utils/version/version_comparator.py +0 -0
  257. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/utils/version/version_detectors.py +0 -0
  258. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/utils/version/version_service.py +0 -0
  259. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/utils/version/version_updater.py +0 -0
  260. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/utils/wl_dir_updater.py +0 -0
  261. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/utils/workspace_detector/__init__.py +0 -0
  262. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/utils/workspace_detector/core.py +0 -0
  263. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/utils/workspace_detector/detection_strategies.py +0 -0
  264. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/utils/workspace_detector/exceptions.py +0 -0
  265. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/utils/workspace_detector/types.py +0 -0
  266. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/utils/workspace_detector/venv_resolver.py +0 -0
  267. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/vendors/config/.codespellrc +0 -0
  268. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/vendors/config/dependencies.toml +0 -0
  269. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/vendors/config/mypy.ini +0 -0
  270. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/vendors/config/pyproject_defaults.toml +0 -0
  271. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/vendors/config/template_config.toml +0 -0
  272. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/vendors/config/tool_configs.toml +0 -0
  273. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/vendors/git/.gitignore +0 -0
  274. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/vendors/git/.pre-commit-config.yaml +0 -0
  275. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/vendors/hooks/applypatch-msg.sample +0 -0
  276. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/vendors/hooks/commit-msg.sample +0 -0
  277. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/vendors/hooks/fsmonitor-watchman.sample +0 -0
  278. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/vendors/hooks/post-update.sample +0 -0
  279. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/vendors/hooks/pre-applypatch.sample +0 -0
  280. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/vendors/hooks/pre-commit +0 -0
  281. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/vendors/hooks/pre-commit.legacy +0 -0
  282. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/vendors/hooks/pre-commit.sample +0 -0
  283. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/vendors/hooks/pre-merge-commit.sample +0 -0
  284. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/vendors/hooks/pre-push.sample +0 -0
  285. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/vendors/hooks/pre-rebase.sample +0 -0
  286. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/vendors/hooks/pre-receive.sample +0 -0
  287. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/vendors/hooks/prepare-commit-msg.sample +0 -0
  288. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/vendors/hooks/push-to-checkout.sample +0 -0
  289. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/vendors/hooks/sendemail-validate.sample +0 -0
  290. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/vendors/hooks/unix/applypatch-msg.sample +0 -0
  291. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/vendors/hooks/unix/check_lockfile.py +0 -0
  292. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/vendors/hooks/unix/check_lockfile.sh +0 -0
  293. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/vendors/hooks/unix/commit-msg.sample +0 -0
  294. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/vendors/hooks/unix/fsmonitor-watchman.sample +0 -0
  295. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/vendors/hooks/unix/post-update.sample +0 -0
  296. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/vendors/hooks/unix/pre-applypatch.sample +0 -0
  297. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/vendors/hooks/unix/pre-commit +0 -0
  298. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/vendors/hooks/unix/pre-commit.legacy +0 -0
  299. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/vendors/hooks/unix/pre-commit.py +0 -0
  300. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/vendors/hooks/unix/pre-commit.sample +0 -0
  301. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/vendors/hooks/unix/pre-merge-commit.sample +0 -0
  302. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/vendors/hooks/unix/pre-push +0 -0
  303. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/vendors/hooks/unix/pre-push.sample +0 -0
  304. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/vendors/hooks/unix/pre-rebase.sample +0 -0
  305. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/vendors/hooks/unix/pre-receive.sample +0 -0
  306. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/vendors/hooks/unix/prepare-commit-msg.sample +0 -0
  307. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/vendors/hooks/update.sample +0 -0
  308. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/vendors/hooks/win/work.bat +0 -0
  309. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/vendors/project/.gitignore +0 -0
  310. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/vendors/project/.python-version +0 -0
  311. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/vendors/project/LICENSE +0 -0
  312. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/vendors/project/README.md +0 -0
  313. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/vendors/project/pyproject.toml +0 -0
  314. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/vendors/project/pyproject_no_workspace.toml +0 -0
  315. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/vendors/project/pyproject_workspace.toml +0 -0
  316. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/vendors/readme/README.md +0 -0
  317. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/vendors/rust/Cargo.toml +0 -0
  318. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/vendors/rust/lib/__init__.py +0 -0
  319. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/vendors/rust/lib/rust_utils.py +0 -0
  320. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/vendors/rust/src/lib.rs +0 -0
  321. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/vendors/rust/src/main.rs +0 -0
  322. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/vendors/rust/tests/test_rust_fallback.py +0 -0
  323. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/vendors/sop_doc/git-dev-sop.md +0 -0
  324. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/vendors/sop_doc/industrial-standard-sop.md +0 -0
  325. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/vendors/sop_doc/python-sop.md +0 -0
  326. {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/vendors/sop_doc/rust-readme.md +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: py_wlcli
3
- Version: 0.8.1
3
+ Version: 0.9.0
4
4
  Summary: wl_cli - Python项目
5
5
  Project-URL: Homepage, https://gitlab.gewinnrobo.com/Humuyuan/wl-cli
6
6
  Project-URL: Issues, https://gitlab.gewinnrobo.com/Humuyuan/wl-cli/-/issues
py_wlcli-0.9.0/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.9.0
@@ -50,6 +50,11 @@ default = true
50
50
  requires = [ "hatchling>=1.27",]
51
51
  build-backend = "hatchling.build"
52
52
 
53
+ [dependency-groups]
54
+ dev = [
55
+ "jsonschema>=4.26.0",
56
+ ]
57
+
53
58
  [tool.hatch.version]
54
59
  source = "regex"
55
60
  path = "VERSION"
@@ -1,4 +1,4 @@
1
- """The shared capability registry for the ``wl`` CLI (issues #270, #221).
1
+ """The shared capability registry for the ``wl`` CLI (issues #270, #221, #231).
2
2
 
3
3
  Capabilities are the stable, dotted names a consumer (wlcc) probes instead of
4
4
  grepping ``--help`` for an implementation flag (wlcc ADR-0010, decision 6):
@@ -33,6 +33,7 @@ SCHEMA_VERSION = 1
33
33
  #: data ships in (the release bump happens outside this change).
34
34
  CAPABILITY_SINCE: dict[str, str] = {
35
35
  "cc.check": "0.8.0",
36
+ "cc.check.schema": "0.9.0",
36
37
  "cc.hooks": "0.8.0",
37
38
  "cc.init": "0.8.0",
38
39
  "cc.mcp": "0.8.0",
@@ -41,8 +42,12 @@ CAPABILITY_SINCE: dict[str, str] = {
41
42
  "cc.settings": "0.8.0",
42
43
  "cc.stamps": "0.8.0",
43
44
  "cc.statusline": "0.8.0",
45
+ "cc.token.set": "0.9.0",
46
+ "cc.token.status": "0.9.0",
47
+ "cc.token.verify": "0.9.0",
44
48
  "cc.upgrade": "0.8.0",
45
49
  "env.check": "0.8.0",
50
+ "env.check.require": "0.8.2",
46
51
  "env.repair": "0.8.0",
47
52
  "mcp.gitlab": "0.8.0",
48
53
  "mcp.k8s": "0.8.0",
@@ -66,6 +66,14 @@ if TYPE_CHECKING:
66
66
  #: Stable tool name in the envelope's ``tool`` key.
67
67
  TOOL = "cc check"
68
68
 
69
+ #: The ``cc.check`` payload schema version (#240). The packaged
70
+ #: ``cc/schemas/cc_check.schema.json`` is the single owner of the shape; this
71
+ #: constant mirrors its top-level ``const``, and the tests pin the two
72
+ #: together. It is deliberately separate from
73
+ #: :data:`wl_cli.capabilities.SCHEMA_VERSION`, which only serves the
74
+ #: deprecated ``wl self capabilities`` payload.
75
+ CC_CHECK_SCHEMA_VERSION = 1
76
+
69
77
  #: Required plugins -- the consumer-side copy of wlcc
70
78
  #: ``references/stamps.md``'s ``wl-required-plugins`` key block (#226 there).
71
79
  #: Entries are the full ``name@marketplace`` form, so a name cannot match a
@@ -107,6 +115,15 @@ MCP_SERVE_ARGS: dict[str, str] = {
107
115
  "k8s-diagnose": "k8s",
108
116
  }
109
117
 
118
+ #: Environment the registered argv needs, per server (#229). ``gitlab`` owns
119
+ #: its default host inside ``server.py``; ``k8s-diagnose`` cannot discover the
120
+ #: SSH target, so the registration must carry it. This is the single source
121
+ #: for both the ``claude mcp add -e`` argv and the registration check.
122
+ MCP_SERVE_ENV: dict[str, tuple[tuple[str, str], ...]] = {
123
+ "gitlab": (),
124
+ "k8s-diagnose": (("K8S_SSH_HOST", "ubuntu-server"),),
125
+ }
126
+
110
127
  #: Capability the ``wl`` on ``PATH`` must advertise before a registration argv
111
128
  #: counts as verifiable (#228). Consumers (wlcc) use the same bit to decide
112
129
  #: that registration goes through ``wl mcp serve``.
@@ -608,6 +625,124 @@ def _wl_reason(fields: dict[str, Any]) -> str:
608
625
  return f"the wl CLI on PATH is not usable ({state or 'unknown state'})"
609
626
 
610
627
 
628
+ def mcp_config_path() -> Path:
629
+ """Return Claude Code's user-scope config file (``claude mcp add -s user``).
630
+
631
+ ``CLAUDE_CONFIG_DIR`` moves the file *inside* that directory, while the
632
+ default location is ``~/.claude.json`` -- a sibling of ``~/.claude``, not
633
+ ``~/.claude/.claude.json``. ``HostContext.config_root`` therefore cannot
634
+ supply this path on its own. Verified against the CLI on 2026-11-05.
635
+ """
636
+ raw = os.environ.get("CLAUDE_CONFIG_DIR")
637
+ if raw:
638
+ # The real CLI resolves this relative to the cwd and does **not**
639
+ # expand ``~`` (measured 2026-11-05), so neither may we.
640
+ return Path(os.path.abspath(raw)) / ".claude.json"
641
+ return Path(os.path.expanduser("~/.claude.json"))
642
+
643
+
644
+ def _registration_status(name: str, entry: Any, wl: str) -> str:
645
+ """Classify one stored registration as ``ok``, ``missing`` or ``stale``.
646
+
647
+ The stamp alone is not evidence: a payload swap that keeps the version
648
+ leaves the old argv pointing at a deleted plugin file (#229), so the
649
+ stored command, args and required environment are compared verbatim.
650
+ """
651
+ if not isinstance(entry, dict):
652
+ return "missing"
653
+ if entry.get("type", "stdio") != "stdio":
654
+ return "stale"
655
+ if entry.get("command") != wl:
656
+ return "stale"
657
+ if entry.get("args") != ["mcp", "serve", MCP_SERVE_ARGS[name]]:
658
+ return "stale"
659
+ env = entry.get("env")
660
+ if env is None:
661
+ env = {}
662
+ if not isinstance(env, dict):
663
+ return "stale"
664
+ for key, _default in MCP_SERVE_ENV[name]:
665
+ # Only presence matters: a user's custom host (e.g. a real K8S_SSH_HOST)
666
+ # is a working registration and must not be rewritten to the default.
667
+ if not env.get(key):
668
+ return "stale"
669
+ return "ok"
670
+
671
+
672
+ def _cwd() -> str:
673
+ """The working directory Claude Code keys the local scope by."""
674
+ return os.path.abspath(os.getcwd())
675
+
676
+
677
+ def _shadowing_servers(config: dict[str, Any]) -> dict[str, str]:
678
+ """Return server name -> scope for entries that shadow the user scope.
679
+
680
+ Claude Code resolves ``mcpServers`` for the working directory: the local
681
+ scope in ``projects[<cwd>].mcpServers`` and the project ``<cwd>/.mcp.json``
682
+ both take precedence over the user-scope map (#229 review). A shadowing
683
+ entry is reported, never rewritten -- it belongs to the project, not wlcc.
684
+ """
685
+ shadowed: dict[str, str] = {}
686
+ cwd = _cwd()
687
+ projects = config.get("projects")
688
+ if isinstance(projects, dict):
689
+ local = projects.get(cwd)
690
+ if isinstance(local, dict):
691
+ servers = local.get("mcpServers")
692
+ if isinstance(servers, dict):
693
+ for name in MCP_SERVERS:
694
+ if name in servers:
695
+ shadowed[name] = "local"
696
+ project_data, _ = _read_json_object(Path(cwd) / ".mcp.json")
697
+ if project_data is not None:
698
+ servers = project_data.get("mcpServers")
699
+ if isinstance(servers, dict):
700
+ for name in MCP_SERVERS:
701
+ shadowed.setdefault(name, "project")
702
+ return shadowed
703
+
704
+
705
+ def probe_mcp_registrations(wl: str) -> dict[str, Any]:
706
+ """Report the user-scope registrations for the servers wlcc owns.
707
+
708
+ A missing config file reads as "no registrations" rather than an error --
709
+ ``claude mcp add`` creates it, so the first repair must be allowed to
710
+ write. An unreadable file is reported through ``error`` and never
711
+ rewritten. ``stale`` lists the server names whose stored argv does not
712
+ match ``<wl> mcp serve <sub>``; ``shadowed`` names the same-name entries
713
+ in the local/project scopes that override the user registration.
714
+ """
715
+ path = mcp_config_path()
716
+ data, error = _read_json_object(path)
717
+ report: dict[str, Any] = {
718
+ "config": str(path),
719
+ "servers": {},
720
+ "stale": [],
721
+ "shadowed": {},
722
+ "error": error,
723
+ }
724
+ if data is None:
725
+ return report
726
+ servers = data.get("mcpServers")
727
+ if servers is None:
728
+ servers = {}
729
+ elif not isinstance(servers, dict):
730
+ report["error"] = f"{path}: 'mcpServers' is not an object"
731
+ return report
732
+ for name in MCP_SERVERS:
733
+ entry = servers.get(name)
734
+ status = _registration_status(name, entry, wl)
735
+ report["servers"][name] = {
736
+ "status": status,
737
+ "command": entry.get("command") if isinstance(entry, dict) else None,
738
+ "args": entry.get("args") if isinstance(entry, dict) else None,
739
+ }
740
+ if status != "ok":
741
+ report["stale"].append(name)
742
+ report["shadowed"] = _shadowing_servers(data)
743
+ return report
744
+
745
+
611
746
  def probe_mcp(host: HostContext) -> dict[str, Any]:
612
747
  """§3: the registration target, version stamp and interpreter visibility.
613
748
 
@@ -616,6 +751,11 @@ def probe_mcp(host: HostContext) -> dict[str, Any]:
616
751
  instead of looking for a plugin-root ``mcp-tools/server.py``. The
617
752
  interpreter probe stays a report field but can no longer gate the section
618
753
  -- ``python`` is not part of the registered command any more.
754
+
755
+ Since #229 the version stamp is not the only evidence: the stored
756
+ user-scope registration is read back and compared verbatim, because a
757
+ payload swap that keeps the version number used to leave a dead
758
+ ``mcp-tools/server.py`` argv behind while this section still said ``ok``.
619
759
  """
620
760
  cache = _wlcc_cache(host)
621
761
  fields: dict[str, Any] = {
@@ -625,6 +765,8 @@ def probe_mcp(host: HostContext) -> dict[str, Any]:
625
765
  "plugin_root": None,
626
766
  "rejected": False,
627
767
  "servers": list(MCP_SERVERS),
768
+ "mcp_config": str(mcp_config_path()),
769
+ "registrations": {},
628
770
  "wl": _probe_wl_serve(),
629
771
  "python": _probe_python(),
630
772
  }
@@ -655,6 +797,13 @@ def probe_mcp(host: HostContext) -> dict[str, Any]:
655
797
  if not wl_state.startswith("ok:"):
656
798
  return _result("unverifiable", _wl_reason(fields["wl"]), **fields)
657
799
 
800
+ registration = probe_mcp_registrations(str(fields["wl"].get("path") or ""))
801
+ fields["mcp_config"] = registration["config"]
802
+ fields["registrations"] = registration["servers"]
803
+ fields["shadowed"] = registration["shadowed"]
804
+ if registration["error"]:
805
+ return _result("unverifiable", registration["error"], **fields)
806
+
658
807
  if registered != version:
659
808
  return _result(
660
809
  "dangling",
@@ -662,6 +811,25 @@ def probe_mcp(host: HostContext) -> dict[str, Any]:
662
811
  "wl cc repair will re-register",
663
812
  **fields,
664
813
  )
814
+
815
+ if registration["shadowed"]:
816
+ scopes = ", ".join(
817
+ f"{name} ({scope})" for name, scope in registration["shadowed"].items()
818
+ )
819
+ return _result(
820
+ "dangling",
821
+ f"MCP registration shadowed by a higher scope: {scopes}; "
822
+ "remove the shadowing project entry manually",
823
+ **fields,
824
+ )
825
+ if registration["stale"]:
826
+ return _result(
827
+ "dangling",
828
+ "stale MCP registration for "
829
+ + ", ".join(registration["stale"])
830
+ + "; wl cc repair will re-register",
831
+ **fields,
832
+ )
665
833
  return _result("ok", None, **fields)
666
834
 
667
835
 
@@ -1101,5 +1269,12 @@ def build_report() -> tuple[str, str | None, dict[str, Any]]:
1101
1269
  def emit_check() -> int:
1102
1270
  """Write the ``cc check`` envelope to stdout and return its exit code."""
1103
1271
  status, reason, fields = build_report()
1104
- dump(status, status in OK_STATUSES, tool=TOOL, reason=reason, **fields)
1272
+ dump(
1273
+ status,
1274
+ status in OK_STATUSES,
1275
+ tool=TOOL,
1276
+ reason=reason,
1277
+ schema_version=CC_CHECK_SCHEMA_VERSION,
1278
+ **fields,
1279
+ )
1105
1280
  return exit_code(status)
@@ -19,13 +19,15 @@ can never disagree with ``repair``.
19
19
 
20
20
  from __future__ import annotations
21
21
 
22
+ from importlib import resources
22
23
  from typing import TYPE_CHECKING, Any
23
24
 
24
25
  import click
25
26
 
26
27
  from ..envelope import OK_STATUSES, dump, exit_code
27
28
  from . import mutate
28
- from .checks import TOOL, build_report
29
+ from . import token as token_ops
30
+ from .checks import CC_CHECK_SCHEMA_VERSION, TOOL, build_report
29
31
 
30
32
  if TYPE_CHECKING:
31
33
  from collections.abc import Callable
@@ -35,6 +37,24 @@ _HOST_SECTIONS = ("plugins", "mcp", "settings", "stamps", "hooks", "statusline")
35
37
 
36
38
  _JSON_HELP = "Emit one five-state JSON envelope on stdout."
37
39
 
40
+ _SCHEMA_HELP = (
41
+ "Print the packaged cc.check JSON Schema and exit without running any probe."
42
+ )
43
+
44
+
45
+ def schema_bytes() -> bytes:
46
+ """Return the packaged ``cc_check.schema.json`` bytes, unchanged.
47
+
48
+ The schema file is the single owner of the ``wl cc check --json`` payload
49
+ shape (#240, ruling #234). Reading it through :mod:`importlib.resources`
50
+ means an installed wheel serves the same bytes as the source tree.
51
+ """
52
+ return (
53
+ resources.files("wl_cli.cc")
54
+ .joinpath("schemas", "cc_check.schema.json")
55
+ .read_bytes()
56
+ )
57
+
38
58
 
39
59
  def _section_line(name: str, section: dict[str, Any]) -> str:
40
60
  """Render one ``name: status -- reason`` line."""
@@ -146,7 +166,13 @@ def cc_group() -> None:
146
166
  is_flag=True,
147
167
  help=_JSON_HELP,
148
168
  )
149
- def check(as_json: bool) -> None:
169
+ @click.option(
170
+ "--schema",
171
+ "show_schema",
172
+ is_flag=True,
173
+ help=_SCHEMA_HELP,
174
+ )
175
+ def check(as_json: bool, show_schema: bool) -> None:
150
176
  """Report the Claude Code host state without writing anything.
151
177
 
152
178
  The report nests the same-process ``wl env check`` payload under ``env``
@@ -156,10 +182,26 @@ def check(as_json: bool) -> None:
156
182
  hides the others. In ``--json`` mode stdout is exactly one envelope line
157
183
  and diagnostics go to stderr; the probe is read-only, and the dispatcher
158
184
  skips the startup ``.wl`` self-sync (#220).
185
+
186
+ ``--schema`` prints the packaged JSON Schema byte-for-byte and exits 0
187
+ without probing anything; it cannot be combined with ``--json``.
159
188
  """
189
+ if show_schema:
190
+ if as_json:
191
+ raise click.UsageError("--schema and --json are mutually exclusive")
192
+ click.echo(schema_bytes(), nl=False)
193
+ raise SystemExit(0)
194
+
160
195
  status, reason, sections = build_report()
161
196
  if as_json:
162
- dump(status, status in OK_STATUSES, tool=TOOL, reason=reason, **sections)
197
+ dump(
198
+ status,
199
+ status in OK_STATUSES,
200
+ tool=TOOL,
201
+ reason=reason,
202
+ schema_version=CC_CHECK_SCHEMA_VERSION,
203
+ **sections,
204
+ )
163
205
  raise SystemExit(exit_code(status))
164
206
 
165
207
  for line in _summary_lines(status, reason, sections):
@@ -368,3 +410,55 @@ def stamps_check(as_json: bool) -> None:
368
410
  are reported and kept here and there.
369
411
  """
370
412
  _run_single("cc stamps check", lambda: mutate.probe_section("stamps"), as_json)
413
+
414
+
415
+ @cc_group.group(name="token")
416
+ def token_group() -> None:
417
+ """GitLab credential status, set and verify (never echoes the token).
418
+
419
+ The three subcommands are ADR-0012's command surface: ``status`` is a
420
+ local-only probe, ``set`` is stdin-only and ``verify`` is the one explicit
421
+ network call. Reasons are the closed ADR-0012 §6 prefixes.
422
+ """
423
+
424
+
425
+ @token_group.command(name="status")
426
+ @click.option("--json", "as_json", is_flag=True, help=_JSON_HELP)
427
+ def token_status(as_json: bool) -> None:
428
+ """Report the credential source and whether the local file decrypts.
429
+
430
+ Returns ``source`` / ``path`` / ``exists`` / ``mode`` / ``decryptable``
431
+ only -- never the token, the hostname, the username or the plaintext
432
+ length. ``dangling`` (with ``no_token:``, ``token_undecryptable:`` or
433
+ ``token_insecure_permissions:``) still exits 0: the probe holds and the
434
+ reason names the one pending action.
435
+ """
436
+ _run_single("cc token status", token_ops.status, as_json)
437
+
438
+
439
+ @token_group.command(name="set")
440
+ @click.option("--json", "as_json", is_flag=True, help=_JSON_HELP)
441
+ def token_set(as_json: bool) -> None:
442
+ """Encrypt and atomically write the token read from stdin.
443
+
444
+ A TTY prompts without echo; a pipe is read directly. There is deliberately
445
+ no ``--from-file`` / ``--path`` / ``--force`` / ``--dry-run``: argv and
446
+ environment variables are a second leak surface for a secret.
447
+ """
448
+
449
+ def action() -> dict[str, Any]:
450
+ return token_ops.set_token(token_ops.read_token_stdin())
451
+
452
+ _run_single("cc token set", action, as_json)
453
+
454
+
455
+ @token_group.command(name="verify")
456
+ @click.option("--json", "as_json", is_flag=True, help=_JSON_HELP)
457
+ def token_verify(as_json: bool) -> None:
458
+ """Check the token against GitLab (``GET /api/v4/user``).
459
+
460
+ The only subcommand that uses the network. It reports ``http_code`` and
461
+ ``host`` only; the response body is never echoed, redirects are never
462
+ followed and TLS verification cannot be disabled.
463
+ """
464
+ _run_single("cc token verify", token_ops.verify, as_json)
@@ -87,11 +87,17 @@ GSTACK_REPO = "https://github.com/garrytan/gstack.git"
87
87
  #: wlcc marketplace source when it is not registered yet (``/wl-upgrade`` §2).
88
88
  WLCC_MARKETPLACE_REPO = "https://gitlab.gewinnrobo.com/Humuyuan/wlcc.git"
89
89
 
90
- #: Per-server extra argv for ``claude mcp add`` (check.sh §3). The GitLab host
91
- #: is deliberately *not* passed: ``server.py`` owns that default (#242).
90
+ #: Per-server extra argv for ``claude mcp add`` (check.sh §3), derived from
91
+ #: the same ``checks.MCP_SERVE_ENV`` table the registration check reads, so
92
+ #: the written argv and the verified argv cannot drift (#229). The GitLab
93
+ #: host is deliberately *not* passed: ``server.py`` owns that default (#242).
92
94
  MCP_SERVER_EXTRA: dict[str, tuple[str, ...]] = {
93
- "gitlab": (),
94
- "k8s-diagnose": ("-e", "K8S_SSH_HOST=ubuntu-server"),
95
+ name: tuple(
96
+ part
97
+ for key, value in checks.MCP_SERVE_ENV[name]
98
+ for part in ("-e", f"{key}={value}")
99
+ )
100
+ for name in checks.MCP_SERVERS
95
101
  }
96
102
 
97
103
  #: How many timestamped ``settings.json`` backups are kept (hooks-drift).
@@ -494,9 +500,12 @@ def ensure_mcp() -> dict[str, Any]:
494
500
  Since #228 the registered argv is ``<wl> mcp serve <sub>`` -- the plugin
495
501
  tree's ``mcp-tools/server.py`` is neither required nor kept as a fallback.
496
502
  A rejected plugin root or a missing/unusable ``wl`` is reported as
497
- ``unverifiable`` and never registered. The stamp is the idempotency latch,
498
- so it is written only after *both* ``claude mcp add`` calls returned 0; one
499
- failure leaves the old stamp in place and the next run retries.
503
+ ``unverifiable`` and never registered. Since #229 the idempotency latch is
504
+ the *pair* of the version stamp and the stored registration: a matching
505
+ stamp with a stale argv (same version, swapped payload) is repaired rather
506
+ than reported ``ok``. The stamp is written only after *both* ``claude mcp
507
+ add`` calls returned 0; one failure leaves the old stamp in place and the
508
+ next run retries.
500
509
  """
501
510
  before = checks.probe_mcp(checks.load_host_context())
502
511
  fields = _section_fields(before)
@@ -506,6 +515,17 @@ def ensure_mcp() -> dict[str, Any]:
506
515
  if before["status"] == "ok":
507
516
  return _result("ok", None, changed, **fields)
508
517
 
518
+ shadowed = before.get("shadowed")
519
+ if isinstance(shadowed, dict) and shadowed:
520
+ scopes = ", ".join(f"{name} ({scope})" for name, scope in shadowed.items())
521
+ return _result(
522
+ "dangling",
523
+ f"MCP registration shadowed by a higher scope: {scopes}; "
524
+ "remove the shadowing project entry manually",
525
+ changed,
526
+ **fields,
527
+ )
528
+
509
529
  plugin_root = before.get("plugin_root")
510
530
  if not isinstance(plugin_root, str) or not plugin_root:
511
531
  return _result(
@@ -534,7 +554,10 @@ def ensure_mcp() -> dict[str, Any]:
534
554
  for name in checks.MCP_SERVERS:
535
555
  subcommand = checks.MCP_SERVE_ARGS[name]
536
556
  try:
537
- _run([claude, "mcp", "remove", name])
557
+ # ``-s user`` is required: without it the CLI refuses to remove
558
+ # when the same name also exists in the local/project scope, and
559
+ # the following ``add -s user`` then fails as a duplicate.
560
+ _run([claude, "mcp", "remove", name, "-s", "user"])
538
561
  proc = _run(
539
562
  [
540
563
  claude,