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.
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/PKG-INFO +1 -1
- py_wlcli-0.9.0/VERSION +1 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/pyproject.toml +5 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/capabilities.py +6 -1
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/cc/checks.py +176 -1
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/cc/cli.py +97 -3
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/cc/mutate.py +31 -8
- py_wlcli-0.9.0/src/wl_cli/cc/schemas/cc_check.schema.json +560 -0
- py_wlcli-0.9.0/src/wl_cli/cc/token.py +528 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/cli_click.py +1 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/env/cli.py +17 -4
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/env_status.py +93 -13
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/mcp/gitlab.py +29 -43
- py_wlcli-0.9.0/src/wl_cli/utils/credentials.py +179 -0
- py_wlcli-0.8.1/VERSION +0 -1
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/.gitignore +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/LICENSE +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/README.md +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/__init__.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/__init__.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/__main__.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/cc/__init__.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/__init__.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/base.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/buildcommands/__init__.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/buildcommands/build.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/buildcommands/build_utils.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/buildcommands/builders/__init__.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/buildcommands/builders/cleanup.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/buildcommands/builders/coordinator.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/buildcommands/builders/environment.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/buildcommands/builders/rust_builder.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/buildcommands/builders/stubs.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/buildcommands/dist.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/buildcommands/test.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/clean/__init__.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/clean/build.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/clean/clean.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/clean/clean_utils.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/clean/core.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/clean/dead_code/__init__.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/clean/dead_code/dead_code_command.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/clean/dead_code/detector.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/clean/dead_code/fixer.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/clean/dead_code/reporter.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/clean/dead_code/utils.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/clean/lfs.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/clean/python.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/clean/rust.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/clean/utils/__init__.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/clean/venv.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/cleanup.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/click_base.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/config/__init__.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/config/config.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/debug/__init__.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/debug/debug.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/debug/debug_cache.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/debug/debug_subagent.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/debug/output_formatter.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/debug/source_hasher.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/format/__init__.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/format/format_cache_adapter.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/format/format_command.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/format/format_coordinator.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/format/format_executor.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/format/format_outcome.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/format/format_path_handler.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/format/format_progress.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/format/format_reporter.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/format/python_formatter.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/format/rust_formatter.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/gate/__init__.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/gate/gate_command.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/gate/preflight.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/git/__init__.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/git/config.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/git/git_facts.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/git/git_flow.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/git/hook.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/git/policy.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/git/push_update.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/initenv/__init__.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/initenv/common/__init__.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/initenv/common/check_git_bash.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/initenv/common/error_handler.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/initenv/common/exceptions.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/initenv/components/__init__.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/initenv/components/cargo_sync.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/initenv/components/config_manager.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/initenv/components/directory_utils.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/initenv/components/git/__init__.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/initenv/components/git/branch_creator.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/initenv/components/git/git_flow_interface.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/initenv/components/git/git_flow_manager.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/initenv/components/git/git_lfs_manager.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/initenv/components/git/git_utility.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/initenv/components/git/gitignore_manager.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/initenv/components/git_initializer.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/initenv/components/i18n_manager.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/initenv/components/log_manager.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/initenv/components/project_structure/__init__.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/initenv/components/project_structure/config_generator.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/initenv/components/project_structure/directory_creator.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/initenv/components/project_structure/hook_source.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/initenv/components/project_structure/hooks_manager.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/initenv/components/project_structure/readme_handler.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/initenv/components/project_structure/rust_files_handler.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/initenv/components/project_structure/setup_handler.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/initenv/components/project_structure/sop_generator.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/initenv/components/project_structure/template_copier.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/initenv/components/project_structure/template_manager.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/initenv/components/pyproject_generator.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/initenv/components/rust_initializer.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/initenv/components/symlink_cleaner.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/initenv/components/symlink_manager.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/initenv/components/venv_manager.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/initenv/initenv.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/initenv/services/__init__.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/initenv/services/environment_initializer.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/initenv/services/git_lfs_initializer.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/initenv/services/project_structure_initializer.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/lfs/README.md +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/lfs/__init__.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/lfs/cli.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/lfs/config.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/lfs/hook.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/lfs/initializer.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/lfs/manager.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/lfs/policy.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/lfs/watcher.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/lint/__init__.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/lint/lint_command.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/lint/lint_executor.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/lint/lint_reporter.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/lint/lint_run.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/lint/mypy_config.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/registry.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/self/__init__.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/self/common/__init__.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/self/common/capabilities.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/self/common/config.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/self/common/version_cache.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/self/handlers/__init__.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/self/handlers/base_handler.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/self/handlers/install_handler.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/self/handlers/status_handler.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/self/handlers/uninstall_handler.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/self/handlers/update_handler.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/self/handlers/version_handler.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/self/self_command.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/self/services/__init__.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/self/services/installation_manager.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/self/services/local_installer.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/self/services/pypi_updater.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/self/services/windows_update.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/testcommands/__init__.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/testcommands/base_dependency_analyzer.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/testcommands/batch_processor.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/testcommands/cache_manager.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/testcommands/coverage_analyzer.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/testcommands/coverage_cache_manager.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/testcommands/progress_manager.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/testcommands/python_env_detector.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/testcommands/report_generator.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/testcommands/single_test_executor.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/testcommands/speed_checker.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/testcommands/test_command_builder.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/testcommands/test_commands.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/testcommands/test_reporter.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/testcommands/test_result_handler.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/testcommands/test_runner.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/testcommands/test_utils.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/testcommands/utils/__init__.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/testcommands/utils/coverage_parser.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/testcommands/utils/env_info.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/testcommands/utils/junit_parser.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/testcommands/utils/markdown_utils.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/testcommands/utils/project_root.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/update/__init__.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/update/services/__init__.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/update/services/backup_manager.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/update/services/component_manager.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/update/services/conflict_resolver.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/update/services/vendors_updater.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/update/services/version_tracker.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/update/update_command.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/update/utils/__init__.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/version/__init__.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/version/version_command.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/commands/workflow.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/env/__init__.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/envelope.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/exceptions.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/lib/__init__.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/lib/rust_utils.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/mcp/__init__.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/mcp/capabilities.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/mcp/cli.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/mcp/k8s.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/mcp/protocol.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/platform.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/quality/__init__.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/utils/__init__.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/utils/cache.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/utils/cache_ledger.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/utils/cache_store.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/utils/config/__init__.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/utils/config/config_loader.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/utils/config/core.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/utils/config/defaults.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/utils/config/env_exporter.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/utils/config/env_parser.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/utils/config/validation.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/utils/error_handler.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/utils/file_copier.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/utils/file_operations.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/utils/language_utils.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/utils/lazy_import.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/utils/log_levels.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/utils/log_rotators.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/utils/logging.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/utils/output_context.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/utils/performance/__init__.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/utils/performance/decorators.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/utils/performance/exporter.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/utils/performance/models.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/utils/performance/monitor.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/utils/performance_monitor.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/utils/platform_adapter.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/utils/pre_commit.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/utils/pre_commit_config.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/utils/root.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/utils/root_fallback.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/utils/run_evidence.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/utils/structured_logger.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/utils/structured_logging/__init__.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/utils/structured_logging/config.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/utils/structured_logging/core.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/utils/structured_logging/env.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/utils/structured_logging/filtering.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/utils/structured_logging/filters.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/utils/structured_logging/formatters.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/utils/structured_logging/handlers.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/utils/structured_logging/logger.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/utils/subprocess.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/utils/subprocess_utils.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/utils/test_utils/__init__.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/utils/test_utils/test_filter.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/utils/uv_run.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/utils/uv_tool.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/utils/uv_tree.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/utils/uv_workspace.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/utils/version/__init__.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/utils/version/pypi_version_checker.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/utils/version/version_comparator.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/utils/version/version_detectors.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/utils/version/version_service.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/utils/version/version_updater.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/utils/wl_dir_updater.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/utils/workspace_detector/__init__.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/utils/workspace_detector/core.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/utils/workspace_detector/detection_strategies.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/utils/workspace_detector/exceptions.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/utils/workspace_detector/types.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/utils/workspace_detector/venv_resolver.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/vendors/config/.codespellrc +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/vendors/config/dependencies.toml +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/vendors/config/mypy.ini +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/vendors/config/pyproject_defaults.toml +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/vendors/config/template_config.toml +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/vendors/config/tool_configs.toml +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/vendors/git/.gitignore +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/vendors/git/.pre-commit-config.yaml +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/vendors/hooks/applypatch-msg.sample +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/vendors/hooks/commit-msg.sample +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/vendors/hooks/fsmonitor-watchman.sample +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/vendors/hooks/post-update.sample +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/vendors/hooks/pre-applypatch.sample +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/vendors/hooks/pre-commit +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/vendors/hooks/pre-commit.legacy +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/vendors/hooks/pre-commit.sample +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/vendors/hooks/pre-merge-commit.sample +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/vendors/hooks/pre-push.sample +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/vendors/hooks/pre-rebase.sample +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/vendors/hooks/pre-receive.sample +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/vendors/hooks/prepare-commit-msg.sample +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/vendors/hooks/push-to-checkout.sample +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/vendors/hooks/sendemail-validate.sample +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/vendors/hooks/unix/applypatch-msg.sample +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/vendors/hooks/unix/check_lockfile.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/vendors/hooks/unix/check_lockfile.sh +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/vendors/hooks/unix/commit-msg.sample +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/vendors/hooks/unix/fsmonitor-watchman.sample +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/vendors/hooks/unix/post-update.sample +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/vendors/hooks/unix/pre-applypatch.sample +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/vendors/hooks/unix/pre-commit +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/vendors/hooks/unix/pre-commit.legacy +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/vendors/hooks/unix/pre-commit.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/vendors/hooks/unix/pre-commit.sample +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/vendors/hooks/unix/pre-merge-commit.sample +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/vendors/hooks/unix/pre-push +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/vendors/hooks/unix/pre-push.sample +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/vendors/hooks/unix/pre-rebase.sample +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/vendors/hooks/unix/pre-receive.sample +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/vendors/hooks/unix/prepare-commit-msg.sample +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/vendors/hooks/update.sample +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/vendors/hooks/win/work.bat +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/vendors/project/.gitignore +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/vendors/project/.python-version +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/vendors/project/LICENSE +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/vendors/project/README.md +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/vendors/project/pyproject.toml +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/vendors/project/pyproject_no_workspace.toml +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/vendors/project/pyproject_workspace.toml +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/vendors/readme/README.md +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/vendors/rust/Cargo.toml +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/vendors/rust/lib/__init__.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/vendors/rust/lib/rust_utils.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/vendors/rust/src/lib.rs +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/vendors/rust/src/main.rs +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/vendors/rust/tests/test_rust_fallback.py +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/vendors/sop_doc/git-dev-sop.md +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/vendors/sop_doc/industrial-standard-sop.md +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/vendors/sop_doc/python-sop.md +0 -0
- {py_wlcli-0.8.1 → py_wlcli-0.9.0}/src/wl_cli/vendors/sop_doc/rust-readme.md +0 -0
py_wlcli-0.9.0/VERSION
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
0.9.0
|
|
@@ -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(
|
|
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 .
|
|
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
|
-
|
|
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(
|
|
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)
|
|
91
|
-
#:
|
|
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
|
-
|
|
94
|
-
|
|
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.
|
|
498
|
-
|
|
499
|
-
|
|
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
|
-
|
|
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,
|