py-wlcli 0.8.0__tar.gz → 0.8.2__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.0 → py_wlcli-0.8.2}/PKG-INFO +1 -1
- py_wlcli-0.8.2/VERSION +1 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/capabilities.py +3 -1
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/cc/checks.py +263 -17
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/cc/cli.py +1 -1
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/cc/mutate.py +46 -32
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/env/cli.py +17 -4
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/env_status.py +93 -13
- py_wlcli-0.8.0/VERSION +0 -1
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/.gitignore +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/LICENSE +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/README.md +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/pyproject.toml +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/__init__.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/__init__.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/__main__.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/cc/__init__.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/cli_click.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/commands/__init__.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/commands/base.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/commands/buildcommands/__init__.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/commands/buildcommands/build.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/commands/buildcommands/build_utils.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/commands/buildcommands/builders/__init__.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/commands/buildcommands/builders/cleanup.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/commands/buildcommands/builders/coordinator.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/commands/buildcommands/builders/environment.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/commands/buildcommands/builders/rust_builder.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/commands/buildcommands/builders/stubs.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/commands/buildcommands/dist.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/commands/buildcommands/test.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/commands/clean/__init__.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/commands/clean/build.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/commands/clean/clean.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/commands/clean/clean_utils.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/commands/clean/core.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/commands/clean/dead_code/__init__.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/commands/clean/dead_code/dead_code_command.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/commands/clean/dead_code/detector.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/commands/clean/dead_code/fixer.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/commands/clean/dead_code/reporter.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/commands/clean/dead_code/utils.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/commands/clean/lfs.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/commands/clean/python.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/commands/clean/rust.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/commands/clean/utils/__init__.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/commands/clean/venv.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/commands/cleanup.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/commands/click_base.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/commands/config/__init__.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/commands/config/config.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/commands/debug/__init__.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/commands/debug/debug.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/commands/debug/debug_cache.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/commands/debug/debug_subagent.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/commands/debug/output_formatter.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/commands/debug/source_hasher.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/commands/format/__init__.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/commands/format/format_cache_adapter.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/commands/format/format_command.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/commands/format/format_coordinator.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/commands/format/format_executor.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/commands/format/format_outcome.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/commands/format/format_path_handler.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/commands/format/format_progress.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/commands/format/format_reporter.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/commands/format/python_formatter.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/commands/format/rust_formatter.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/commands/gate/__init__.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/commands/gate/gate_command.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/commands/gate/preflight.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/commands/git/__init__.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/commands/git/config.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/commands/git/git_facts.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/commands/git/git_flow.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/commands/git/hook.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/commands/git/policy.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/commands/git/push_update.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/commands/initenv/__init__.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/commands/initenv/common/__init__.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/commands/initenv/common/check_git_bash.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/commands/initenv/common/error_handler.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/commands/initenv/common/exceptions.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/commands/initenv/components/__init__.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/commands/initenv/components/cargo_sync.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/commands/initenv/components/config_manager.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/commands/initenv/components/directory_utils.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/commands/initenv/components/git/__init__.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/commands/initenv/components/git/branch_creator.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/commands/initenv/components/git/git_flow_interface.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/commands/initenv/components/git/git_flow_manager.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/commands/initenv/components/git/git_lfs_manager.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/commands/initenv/components/git/git_utility.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/commands/initenv/components/git/gitignore_manager.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/commands/initenv/components/git_initializer.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/commands/initenv/components/i18n_manager.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/commands/initenv/components/log_manager.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/commands/initenv/components/project_structure/__init__.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/commands/initenv/components/project_structure/config_generator.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/commands/initenv/components/project_structure/directory_creator.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/commands/initenv/components/project_structure/hook_source.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/commands/initenv/components/project_structure/hooks_manager.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/commands/initenv/components/project_structure/readme_handler.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/commands/initenv/components/project_structure/rust_files_handler.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/commands/initenv/components/project_structure/setup_handler.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/commands/initenv/components/project_structure/sop_generator.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/commands/initenv/components/project_structure/template_copier.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/commands/initenv/components/project_structure/template_manager.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/commands/initenv/components/pyproject_generator.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/commands/initenv/components/rust_initializer.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/commands/initenv/components/symlink_cleaner.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/commands/initenv/components/symlink_manager.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/commands/initenv/components/venv_manager.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/commands/initenv/initenv.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/commands/initenv/services/__init__.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/commands/initenv/services/environment_initializer.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/commands/initenv/services/git_lfs_initializer.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/commands/initenv/services/project_structure_initializer.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/commands/lfs/README.md +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/commands/lfs/__init__.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/commands/lfs/cli.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/commands/lfs/config.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/commands/lfs/hook.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/commands/lfs/initializer.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/commands/lfs/manager.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/commands/lfs/policy.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/commands/lfs/watcher.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/commands/lint/__init__.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/commands/lint/lint_command.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/commands/lint/lint_executor.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/commands/lint/lint_reporter.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/commands/lint/lint_run.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/commands/lint/mypy_config.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/commands/registry.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/commands/self/__init__.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/commands/self/common/__init__.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/commands/self/common/capabilities.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/commands/self/common/config.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/commands/self/common/version_cache.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/commands/self/handlers/__init__.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/commands/self/handlers/base_handler.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/commands/self/handlers/install_handler.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/commands/self/handlers/status_handler.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/commands/self/handlers/uninstall_handler.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/commands/self/handlers/update_handler.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/commands/self/handlers/version_handler.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/commands/self/self_command.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/commands/self/services/__init__.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/commands/self/services/installation_manager.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/commands/self/services/local_installer.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/commands/self/services/pypi_updater.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/commands/self/services/windows_update.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/commands/testcommands/__init__.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/commands/testcommands/base_dependency_analyzer.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/commands/testcommands/batch_processor.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/commands/testcommands/cache_manager.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/commands/testcommands/coverage_analyzer.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/commands/testcommands/coverage_cache_manager.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/commands/testcommands/progress_manager.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/commands/testcommands/python_env_detector.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/commands/testcommands/report_generator.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/commands/testcommands/single_test_executor.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/commands/testcommands/speed_checker.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/commands/testcommands/test_command_builder.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/commands/testcommands/test_commands.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/commands/testcommands/test_reporter.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/commands/testcommands/test_result_handler.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/commands/testcommands/test_runner.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/commands/testcommands/test_utils.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/commands/testcommands/utils/__init__.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/commands/testcommands/utils/coverage_parser.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/commands/testcommands/utils/env_info.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/commands/testcommands/utils/junit_parser.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/commands/testcommands/utils/markdown_utils.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/commands/testcommands/utils/project_root.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/commands/update/__init__.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/commands/update/services/__init__.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/commands/update/services/backup_manager.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/commands/update/services/component_manager.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/commands/update/services/conflict_resolver.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/commands/update/services/vendors_updater.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/commands/update/services/version_tracker.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/commands/update/update_command.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/commands/update/utils/__init__.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/commands/version/__init__.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/commands/version/version_command.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/commands/workflow.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/env/__init__.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/envelope.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/exceptions.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/lib/__init__.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/lib/rust_utils.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/mcp/__init__.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/mcp/capabilities.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/mcp/cli.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/mcp/gitlab.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/mcp/k8s.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/mcp/protocol.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/platform.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/quality/__init__.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/utils/__init__.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/utils/cache.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/utils/cache_ledger.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/utils/cache_store.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/utils/config/__init__.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/utils/config/config_loader.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/utils/config/core.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/utils/config/defaults.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/utils/config/env_exporter.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/utils/config/env_parser.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/utils/config/validation.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/utils/error_handler.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/utils/file_copier.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/utils/file_operations.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/utils/language_utils.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/utils/lazy_import.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/utils/log_levels.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/utils/log_rotators.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/utils/logging.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/utils/output_context.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/utils/performance/__init__.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/utils/performance/decorators.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/utils/performance/exporter.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/utils/performance/models.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/utils/performance/monitor.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/utils/performance_monitor.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/utils/platform_adapter.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/utils/pre_commit.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/utils/pre_commit_config.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/utils/root.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/utils/root_fallback.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/utils/run_evidence.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/utils/structured_logger.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/utils/structured_logging/__init__.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/utils/structured_logging/config.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/utils/structured_logging/core.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/utils/structured_logging/env.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/utils/structured_logging/filtering.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/utils/structured_logging/filters.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/utils/structured_logging/formatters.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/utils/structured_logging/handlers.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/utils/structured_logging/logger.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/utils/subprocess.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/utils/subprocess_utils.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/utils/test_utils/__init__.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/utils/test_utils/test_filter.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/utils/uv_run.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/utils/uv_tool.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/utils/uv_tree.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/utils/uv_workspace.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/utils/version/__init__.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/utils/version/pypi_version_checker.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/utils/version/version_comparator.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/utils/version/version_detectors.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/utils/version/version_service.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/utils/version/version_updater.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/utils/wl_dir_updater.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/utils/workspace_detector/__init__.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/utils/workspace_detector/core.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/utils/workspace_detector/detection_strategies.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/utils/workspace_detector/exceptions.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/utils/workspace_detector/types.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/utils/workspace_detector/venv_resolver.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/vendors/config/.codespellrc +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/vendors/config/dependencies.toml +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/vendors/config/mypy.ini +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/vendors/config/pyproject_defaults.toml +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/vendors/config/template_config.toml +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/vendors/config/tool_configs.toml +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/vendors/git/.gitignore +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/vendors/git/.pre-commit-config.yaml +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/vendors/hooks/applypatch-msg.sample +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/vendors/hooks/commit-msg.sample +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/vendors/hooks/fsmonitor-watchman.sample +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/vendors/hooks/post-update.sample +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/vendors/hooks/pre-applypatch.sample +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/vendors/hooks/pre-commit +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/vendors/hooks/pre-commit.legacy +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/vendors/hooks/pre-commit.sample +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/vendors/hooks/pre-merge-commit.sample +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/vendors/hooks/pre-push.sample +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/vendors/hooks/pre-rebase.sample +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/vendors/hooks/pre-receive.sample +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/vendors/hooks/prepare-commit-msg.sample +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/vendors/hooks/push-to-checkout.sample +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/vendors/hooks/sendemail-validate.sample +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/vendors/hooks/unix/applypatch-msg.sample +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/vendors/hooks/unix/check_lockfile.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/vendors/hooks/unix/check_lockfile.sh +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/vendors/hooks/unix/commit-msg.sample +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/vendors/hooks/unix/fsmonitor-watchman.sample +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/vendors/hooks/unix/post-update.sample +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/vendors/hooks/unix/pre-applypatch.sample +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/vendors/hooks/unix/pre-commit +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/vendors/hooks/unix/pre-commit.legacy +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/vendors/hooks/unix/pre-commit.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/vendors/hooks/unix/pre-commit.sample +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/vendors/hooks/unix/pre-merge-commit.sample +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/vendors/hooks/unix/pre-push +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/vendors/hooks/unix/pre-push.sample +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/vendors/hooks/unix/pre-rebase.sample +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/vendors/hooks/unix/pre-receive.sample +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/vendors/hooks/unix/prepare-commit-msg.sample +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/vendors/hooks/update.sample +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/vendors/hooks/win/work.bat +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/vendors/project/.gitignore +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/vendors/project/.python-version +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/vendors/project/LICENSE +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/vendors/project/README.md +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/vendors/project/pyproject.toml +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/vendors/project/pyproject_no_workspace.toml +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/vendors/project/pyproject_workspace.toml +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/vendors/readme/README.md +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/vendors/rust/Cargo.toml +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/vendors/rust/lib/__init__.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/vendors/rust/lib/rust_utils.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/vendors/rust/src/lib.rs +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/vendors/rust/src/main.rs +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/vendors/rust/tests/test_rust_fallback.py +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/vendors/sop_doc/git-dev-sop.md +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/vendors/sop_doc/industrial-standard-sop.md +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/vendors/sop_doc/python-sop.md +0 -0
- {py_wlcli-0.8.0 → py_wlcli-0.8.2}/src/wl_cli/vendors/sop_doc/rust-readme.md +0 -0
py_wlcli-0.8.2/VERSION
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
0.8.2
|
|
@@ -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):
|
|
@@ -43,9 +43,11 @@ CAPABILITY_SINCE: dict[str, str] = {
|
|
|
43
43
|
"cc.statusline": "0.8.0",
|
|
44
44
|
"cc.upgrade": "0.8.0",
|
|
45
45
|
"env.check": "0.8.0",
|
|
46
|
+
"env.check.require": "0.8.2",
|
|
46
47
|
"env.repair": "0.8.0",
|
|
47
48
|
"mcp.gitlab": "0.8.0",
|
|
48
49
|
"mcp.k8s": "0.8.0",
|
|
50
|
+
"mcp.serve": "0.8.1",
|
|
49
51
|
"test.clean_cache": "0.7.0",
|
|
50
52
|
}
|
|
51
53
|
|
|
@@ -15,7 +15,7 @@ the ticket cannot drift from the implementation:
|
|
|
15
15
|
section wlcc source
|
|
16
16
|
=========== ============================================================
|
|
17
17
|
plugins §1 required plugins + §7 context-mode (optional plugin)
|
|
18
|
-
mcp §3
|
|
18
|
+
mcp §3 registered wl command, version stamp, interpreter visibility
|
|
19
19
|
settings §5 gstack + §6 claude-mem (host-side configuration)
|
|
20
20
|
stamps §8 stamp registry (report only -- never delete)
|
|
21
21
|
hooks §9 dangling hook commands (read-only plan)
|
|
@@ -98,6 +98,29 @@ RETIRED_STAMPS = frozenset({"gemini-key.enc", "mcp-visionary-pending"})
|
|
|
98
98
|
#: MCP servers check.sh §3 registers.
|
|
99
99
|
MCP_SERVERS: tuple[str, ...] = ("gitlab", "k8s-diagnose")
|
|
100
100
|
|
|
101
|
+
#: Registered server name -> ``wl mcp serve`` subcommand (#228). The server
|
|
102
|
+
#: names are the stable interface (tool schema and existing user config); only
|
|
103
|
+
#: the execution path moved from the plugin's ``mcp-tools/server.py`` to the
|
|
104
|
+
#: wl CLI. ``k8s-diagnose`` keeps its name but serves ``wl mcp serve k8s``.
|
|
105
|
+
MCP_SERVE_ARGS: dict[str, str] = {
|
|
106
|
+
"gitlab": "gitlab",
|
|
107
|
+
"k8s-diagnose": "k8s",
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
#: Environment the registered argv needs, per server (#229). ``gitlab`` owns
|
|
111
|
+
#: its default host inside ``server.py``; ``k8s-diagnose`` cannot discover the
|
|
112
|
+
#: SSH target, so the registration must carry it. This is the single source
|
|
113
|
+
#: for both the ``claude mcp add -e`` argv and the registration check.
|
|
114
|
+
MCP_SERVE_ENV: dict[str, tuple[tuple[str, str], ...]] = {
|
|
115
|
+
"gitlab": (),
|
|
116
|
+
"k8s-diagnose": (("K8S_SSH_HOST", "ubuntu-server"),),
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
#: Capability the ``wl`` on ``PATH`` must advertise before a registration argv
|
|
120
|
+
#: counts as verifiable (#228). Consumers (wlcc) use the same bit to decide
|
|
121
|
+
#: that registration goes through ``wl mcp serve``.
|
|
122
|
+
MCP_SERVE_CAPABILITY = "mcp.serve"
|
|
123
|
+
|
|
101
124
|
#: Literal absolute path anchor from wlcc ``hooks-drift.py``: the dangling rule
|
|
102
125
|
#: is exactly ``*/.claude/*``. Kept with the trailing slash on purpose.
|
|
103
126
|
CLAUDE_SEG = "/.claude/"
|
|
@@ -475,7 +498,10 @@ def _interpreter_state(path: str, version: str, returncode: int) -> dict[str, An
|
|
|
475
498
|
|
|
476
499
|
|
|
477
500
|
def _probe_python() -> dict[str, Any]:
|
|
478
|
-
"""
|
|
501
|
+
"""Report the interpreter check.sh §3 used to run the MCP servers under.
|
|
502
|
+
|
|
503
|
+
Since #228 the servers run under ``wl mcp serve`` and no interpreter is
|
|
504
|
+
part of the registered argv, so the result is informational only.
|
|
479
505
|
|
|
480
506
|
``uv --no-cache python find 3.12`` resolves a local installation without
|
|
481
507
|
downloading and keeps its cache in a temporary directory for the duration
|
|
@@ -518,8 +544,211 @@ def _probe_python() -> dict[str, Any]:
|
|
|
518
544
|
return _interpreter_state(path, probe.stdout.strip(), probe.returncode)
|
|
519
545
|
|
|
520
546
|
|
|
547
|
+
def _probe_wl_serve() -> dict[str, Any]:
|
|
548
|
+
"""Probe the ``wl`` on ``PATH`` for the ``mcp.serve`` capability (#228).
|
|
549
|
+
|
|
550
|
+
The registration argv is ``<wl> mcp serve <sub>``, so the executable that
|
|
551
|
+
will be registered has to exist *and* advertise the capability. Asking it
|
|
552
|
+
for ``wl env check --json`` reads the same capability registry wlcc keys
|
|
553
|
+
off, instead of trusting the wl that happens to be running ``cc check``.
|
|
554
|
+
Every failure is a state value, never an exception.
|
|
555
|
+
|
|
556
|
+
Returns:
|
|
557
|
+
Fields ``path`` / ``state`` / ``version`` / ``capability``. ``state``
|
|
558
|
+
is ``ok:<version>`` when the capability is advertised, ``fail:absent``
|
|
559
|
+
when no ``wl`` is on ``PATH``, and ``fail:unusable`` /
|
|
560
|
+
``fail:missing_capability`` (with a readable ``reason``) otherwise.
|
|
561
|
+
"""
|
|
562
|
+
fields: dict[str, Any] = {
|
|
563
|
+
"path": None,
|
|
564
|
+
"state": "fail:absent",
|
|
565
|
+
"version": None,
|
|
566
|
+
"capability": MCP_SERVE_CAPABILITY,
|
|
567
|
+
}
|
|
568
|
+
wl = shutil.which("wl")
|
|
569
|
+
if wl is None:
|
|
570
|
+
return fields
|
|
571
|
+
fields["path"] = wl
|
|
572
|
+
try:
|
|
573
|
+
probe = subprocess.run(
|
|
574
|
+
[wl, "env", "check", "--json"],
|
|
575
|
+
capture_output=True,
|
|
576
|
+
text=True,
|
|
577
|
+
check=False,
|
|
578
|
+
timeout=30,
|
|
579
|
+
)
|
|
580
|
+
except (OSError, subprocess.SubprocessError) as exc:
|
|
581
|
+
fields.update(state="fail:unusable", reason=str(exc))
|
|
582
|
+
return fields
|
|
583
|
+
# ``env check`` exits 1 when the platform matrix says ``unverifiable`` but
|
|
584
|
+
# still emits the payload; parse first so a supported capability is not
|
|
585
|
+
# rejected because of an unrelated platform warning.
|
|
586
|
+
try:
|
|
587
|
+
payload = json.loads(probe.stdout)
|
|
588
|
+
except ValueError:
|
|
589
|
+
payload = None
|
|
590
|
+
if not isinstance(payload, dict):
|
|
591
|
+
fields.update(
|
|
592
|
+
state="fail:unusable",
|
|
593
|
+
reason=f"wl env check exited {probe.returncode} without a JSON payload",
|
|
594
|
+
)
|
|
595
|
+
return fields
|
|
596
|
+
version = payload.get("version")
|
|
597
|
+
fields["version"] = version if isinstance(version, str) else None
|
|
598
|
+
capabilities = payload.get("capabilities")
|
|
599
|
+
if isinstance(capabilities, list) and MCP_SERVE_CAPABILITY in capabilities:
|
|
600
|
+
fields["state"] = f"ok:{fields['version'] or 'unknown'}"
|
|
601
|
+
return fields
|
|
602
|
+
fields.update(
|
|
603
|
+
state="fail:missing_capability",
|
|
604
|
+
reason=f"{wl} does not advertise {MCP_SERVE_CAPABILITY}",
|
|
605
|
+
)
|
|
606
|
+
return fields
|
|
607
|
+
|
|
608
|
+
|
|
609
|
+
def _wl_reason(fields: dict[str, Any]) -> str:
|
|
610
|
+
"""Return a readable reason for a ``wl`` probe that is not ``ok``."""
|
|
611
|
+
state = str(fields.get("state", ""))
|
|
612
|
+
if state == "fail:absent":
|
|
613
|
+
return "the wl CLI is not on PATH"
|
|
614
|
+
reason = fields.get("reason")
|
|
615
|
+
if isinstance(reason, str) and reason:
|
|
616
|
+
return reason
|
|
617
|
+
return f"the wl CLI on PATH is not usable ({state or 'unknown state'})"
|
|
618
|
+
|
|
619
|
+
|
|
620
|
+
def mcp_config_path() -> Path:
|
|
621
|
+
"""Return Claude Code's user-scope config file (``claude mcp add -s user``).
|
|
622
|
+
|
|
623
|
+
``CLAUDE_CONFIG_DIR`` moves the file *inside* that directory, while the
|
|
624
|
+
default location is ``~/.claude.json`` -- a sibling of ``~/.claude``, not
|
|
625
|
+
``~/.claude/.claude.json``. ``HostContext.config_root`` therefore cannot
|
|
626
|
+
supply this path on its own. Verified against the CLI on 2026-11-05.
|
|
627
|
+
"""
|
|
628
|
+
raw = os.environ.get("CLAUDE_CONFIG_DIR")
|
|
629
|
+
if raw:
|
|
630
|
+
# The real CLI resolves this relative to the cwd and does **not**
|
|
631
|
+
# expand ``~`` (measured 2026-11-05), so neither may we.
|
|
632
|
+
return Path(os.path.abspath(raw)) / ".claude.json"
|
|
633
|
+
return Path(os.path.expanduser("~/.claude.json"))
|
|
634
|
+
|
|
635
|
+
|
|
636
|
+
def _registration_status(name: str, entry: Any, wl: str) -> str:
|
|
637
|
+
"""Classify one stored registration as ``ok``, ``missing`` or ``stale``.
|
|
638
|
+
|
|
639
|
+
The stamp alone is not evidence: a payload swap that keeps the version
|
|
640
|
+
leaves the old argv pointing at a deleted plugin file (#229), so the
|
|
641
|
+
stored command, args and required environment are compared verbatim.
|
|
642
|
+
"""
|
|
643
|
+
if not isinstance(entry, dict):
|
|
644
|
+
return "missing"
|
|
645
|
+
if entry.get("type", "stdio") != "stdio":
|
|
646
|
+
return "stale"
|
|
647
|
+
if entry.get("command") != wl:
|
|
648
|
+
return "stale"
|
|
649
|
+
if entry.get("args") != ["mcp", "serve", MCP_SERVE_ARGS[name]]:
|
|
650
|
+
return "stale"
|
|
651
|
+
env = entry.get("env")
|
|
652
|
+
if env is None:
|
|
653
|
+
env = {}
|
|
654
|
+
if not isinstance(env, dict):
|
|
655
|
+
return "stale"
|
|
656
|
+
for key, _default in MCP_SERVE_ENV[name]:
|
|
657
|
+
# Only presence matters: a user's custom host (e.g. a real K8S_SSH_HOST)
|
|
658
|
+
# is a working registration and must not be rewritten to the default.
|
|
659
|
+
if not env.get(key):
|
|
660
|
+
return "stale"
|
|
661
|
+
return "ok"
|
|
662
|
+
|
|
663
|
+
|
|
664
|
+
def _cwd() -> str:
|
|
665
|
+
"""The working directory Claude Code keys the local scope by."""
|
|
666
|
+
return os.path.abspath(os.getcwd())
|
|
667
|
+
|
|
668
|
+
|
|
669
|
+
def _shadowing_servers(config: dict[str, Any]) -> dict[str, str]:
|
|
670
|
+
"""Return server name -> scope for entries that shadow the user scope.
|
|
671
|
+
|
|
672
|
+
Claude Code resolves ``mcpServers`` for the working directory: the local
|
|
673
|
+
scope in ``projects[<cwd>].mcpServers`` and the project ``<cwd>/.mcp.json``
|
|
674
|
+
both take precedence over the user-scope map (#229 review). A shadowing
|
|
675
|
+
entry is reported, never rewritten -- it belongs to the project, not wlcc.
|
|
676
|
+
"""
|
|
677
|
+
shadowed: dict[str, str] = {}
|
|
678
|
+
cwd = _cwd()
|
|
679
|
+
projects = config.get("projects")
|
|
680
|
+
if isinstance(projects, dict):
|
|
681
|
+
local = projects.get(cwd)
|
|
682
|
+
if isinstance(local, dict):
|
|
683
|
+
servers = local.get("mcpServers")
|
|
684
|
+
if isinstance(servers, dict):
|
|
685
|
+
for name in MCP_SERVERS:
|
|
686
|
+
if name in servers:
|
|
687
|
+
shadowed[name] = "local"
|
|
688
|
+
project_data, _ = _read_json_object(Path(cwd) / ".mcp.json")
|
|
689
|
+
if project_data is not None:
|
|
690
|
+
servers = project_data.get("mcpServers")
|
|
691
|
+
if isinstance(servers, dict):
|
|
692
|
+
for name in MCP_SERVERS:
|
|
693
|
+
shadowed.setdefault(name, "project")
|
|
694
|
+
return shadowed
|
|
695
|
+
|
|
696
|
+
|
|
697
|
+
def probe_mcp_registrations(wl: str) -> dict[str, Any]:
|
|
698
|
+
"""Report the user-scope registrations for the servers wlcc owns.
|
|
699
|
+
|
|
700
|
+
A missing config file reads as "no registrations" rather than an error --
|
|
701
|
+
``claude mcp add`` creates it, so the first repair must be allowed to
|
|
702
|
+
write. An unreadable file is reported through ``error`` and never
|
|
703
|
+
rewritten. ``stale`` lists the server names whose stored argv does not
|
|
704
|
+
match ``<wl> mcp serve <sub>``; ``shadowed`` names the same-name entries
|
|
705
|
+
in the local/project scopes that override the user registration.
|
|
706
|
+
"""
|
|
707
|
+
path = mcp_config_path()
|
|
708
|
+
data, error = _read_json_object(path)
|
|
709
|
+
report: dict[str, Any] = {
|
|
710
|
+
"config": str(path),
|
|
711
|
+
"servers": {},
|
|
712
|
+
"stale": [],
|
|
713
|
+
"shadowed": {},
|
|
714
|
+
"error": error,
|
|
715
|
+
}
|
|
716
|
+
if data is None:
|
|
717
|
+
return report
|
|
718
|
+
servers = data.get("mcpServers")
|
|
719
|
+
if servers is None:
|
|
720
|
+
servers = {}
|
|
721
|
+
elif not isinstance(servers, dict):
|
|
722
|
+
report["error"] = f"{path}: 'mcpServers' is not an object"
|
|
723
|
+
return report
|
|
724
|
+
for name in MCP_SERVERS:
|
|
725
|
+
entry = servers.get(name)
|
|
726
|
+
status = _registration_status(name, entry, wl)
|
|
727
|
+
report["servers"][name] = {
|
|
728
|
+
"status": status,
|
|
729
|
+
"command": entry.get("command") if isinstance(entry, dict) else None,
|
|
730
|
+
"args": entry.get("args") if isinstance(entry, dict) else None,
|
|
731
|
+
}
|
|
732
|
+
if status != "ok":
|
|
733
|
+
report["stale"].append(name)
|
|
734
|
+
report["shadowed"] = _shadowing_servers(data)
|
|
735
|
+
return report
|
|
736
|
+
|
|
737
|
+
|
|
521
738
|
def probe_mcp(host: HostContext) -> dict[str, Any]:
|
|
522
|
-
"""§3:
|
|
739
|
+
"""§3: the registration target, version stamp and interpreter visibility.
|
|
740
|
+
|
|
741
|
+
Since #228 the registered argv is ``<wl> mcp serve <sub>``: the probe
|
|
742
|
+
verifies that the ``wl`` on ``PATH`` exists and advertises ``mcp.serve``
|
|
743
|
+
instead of looking for a plugin-root ``mcp-tools/server.py``. The
|
|
744
|
+
interpreter probe stays a report field but can no longer gate the section
|
|
745
|
+
-- ``python`` is not part of the registered command any more.
|
|
746
|
+
|
|
747
|
+
Since #229 the version stamp is not the only evidence: the stored
|
|
748
|
+
user-scope registration is read back and compared verbatim, because a
|
|
749
|
+
payload swap that keeps the version number used to leave a dead
|
|
750
|
+
``mcp-tools/server.py`` argv behind while this section still said ``ok``.
|
|
751
|
+
"""
|
|
523
752
|
cache = _wlcc_cache(host)
|
|
524
753
|
fields: dict[str, Any] = {
|
|
525
754
|
"cache_root": str(cache),
|
|
@@ -528,6 +757,9 @@ def probe_mcp(host: HostContext) -> dict[str, Any]:
|
|
|
528
757
|
"plugin_root": None,
|
|
529
758
|
"rejected": False,
|
|
530
759
|
"servers": list(MCP_SERVERS),
|
|
760
|
+
"mcp_config": str(mcp_config_path()),
|
|
761
|
+
"registrations": {},
|
|
762
|
+
"wl": _probe_wl_serve(),
|
|
531
763
|
"python": _probe_python(),
|
|
532
764
|
}
|
|
533
765
|
try:
|
|
@@ -552,17 +784,17 @@ def probe_mcp(host: HostContext) -> dict[str, Any]:
|
|
|
552
784
|
fields["rejected"] = True
|
|
553
785
|
return _result("unverifiable", root_error, **fields)
|
|
554
786
|
fields["plugin_root"] = str(root)
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
return _result(
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
)
|
|
787
|
+
|
|
788
|
+
wl_state = str(fields["wl"].get("state", ""))
|
|
789
|
+
if not wl_state.startswith("ok:"):
|
|
790
|
+
return _result("unverifiable", _wl_reason(fields["wl"]), **fields)
|
|
791
|
+
|
|
792
|
+
registration = probe_mcp_registrations(str(fields["wl"].get("path") or ""))
|
|
793
|
+
fields["mcp_config"] = registration["config"]
|
|
794
|
+
fields["registrations"] = registration["servers"]
|
|
795
|
+
fields["shadowed"] = registration["shadowed"]
|
|
796
|
+
if registration["error"]:
|
|
797
|
+
return _result("unverifiable", registration["error"], **fields)
|
|
566
798
|
|
|
567
799
|
if registered != version:
|
|
568
800
|
return _result(
|
|
@@ -571,10 +803,24 @@ def probe_mcp(host: HostContext) -> dict[str, Any]:
|
|
|
571
803
|
"wl cc repair will re-register",
|
|
572
804
|
**fields,
|
|
573
805
|
)
|
|
574
|
-
|
|
575
|
-
if
|
|
806
|
+
|
|
807
|
+
if registration["shadowed"]:
|
|
808
|
+
scopes = ", ".join(
|
|
809
|
+
f"{name} ({scope})" for name, scope in registration["shadowed"].items()
|
|
810
|
+
)
|
|
811
|
+
return _result(
|
|
812
|
+
"dangling",
|
|
813
|
+
f"MCP registration shadowed by a higher scope: {scopes}; "
|
|
814
|
+
"remove the shadowing project entry manually",
|
|
815
|
+
**fields,
|
|
816
|
+
)
|
|
817
|
+
if registration["stale"]:
|
|
576
818
|
return _result(
|
|
577
|
-
"dangling",
|
|
819
|
+
"dangling",
|
|
820
|
+
"stale MCP registration for "
|
|
821
|
+
+ ", ".join(registration["stale"])
|
|
822
|
+
+ "; wl cc repair will re-register",
|
|
823
|
+
**fields,
|
|
578
824
|
)
|
|
579
825
|
return _result("ok", None, **fields)
|
|
580
826
|
|
|
@@ -278,7 +278,7 @@ def mcp_ensure(as_json: bool) -> None:
|
|
|
278
278
|
@mcp_group.command(name="list")
|
|
279
279
|
@click.option("--json", "as_json", is_flag=True, help=_JSON_HELP)
|
|
280
280
|
def mcp_list(as_json: bool) -> None:
|
|
281
|
-
"""Report the plugin root, interpreter, stamp and servers
|
|
281
|
+
"""Report the wl target, plugin root, interpreter, stamp and servers."""
|
|
282
282
|
_run_single("cc mcp list", lambda: mutate.probe_section("mcp"), as_json)
|
|
283
283
|
|
|
284
284
|
|
|
@@ -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).
|
|
@@ -488,22 +494,18 @@ def ensure_plugins() -> dict[str, Any]:
|
|
|
488
494
|
# --------------------------------------------------------------------------- #
|
|
489
495
|
|
|
490
496
|
|
|
491
|
-
def _mcp_script(plugin_root: Path, name: str) -> Path:
|
|
492
|
-
"""Return the registered server script for *name* under the plugin root."""
|
|
493
|
-
tools = plugin_root / ".claude" / "mcp-tools"
|
|
494
|
-
if name == "gitlab":
|
|
495
|
-
return tools / "server.py"
|
|
496
|
-
return tools / name / "server.py"
|
|
497
|
-
|
|
498
|
-
|
|
499
497
|
def ensure_mcp() -> dict[str, Any]:
|
|
500
|
-
"""Re-register both MCP servers
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
``
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
the
|
|
498
|
+
"""Re-register both MCP servers as ``wl mcp serve`` and stamp on success.
|
|
499
|
+
|
|
500
|
+
Since #228 the registered argv is ``<wl> mcp serve <sub>`` -- the plugin
|
|
501
|
+
tree's ``mcp-tools/server.py`` is neither required nor kept as a fallback.
|
|
502
|
+
A rejected plugin root or a missing/unusable ``wl`` is reported as
|
|
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.
|
|
507
509
|
"""
|
|
508
510
|
before = checks.probe_mcp(checks.load_host_context())
|
|
509
511
|
fields = _section_fields(before)
|
|
@@ -513,6 +515,17 @@ def ensure_mcp() -> dict[str, Any]:
|
|
|
513
515
|
if before["status"] == "ok":
|
|
514
516
|
return _result("ok", None, changed, **fields)
|
|
515
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
|
+
|
|
516
529
|
plugin_root = before.get("plugin_root")
|
|
517
530
|
if not isinstance(plugin_root, str) or not plugin_root:
|
|
518
531
|
return _result(
|
|
@@ -521,15 +534,12 @@ def ensure_mcp() -> dict[str, Any]:
|
|
|
521
534
|
changed,
|
|
522
535
|
**fields,
|
|
523
536
|
)
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
if not isinstance(python_path, str) or not str(python_state).startswith(
|
|
528
|
-
("supplied:", "ok:")
|
|
529
|
-
):
|
|
537
|
+
wl_probe = before.get("wl")
|
|
538
|
+
wl = wl_probe.get("path") if isinstance(wl_probe, dict) else None
|
|
539
|
+
if not isinstance(wl, str) or not wl:
|
|
530
540
|
return _result(
|
|
531
541
|
"unverifiable",
|
|
532
|
-
|
|
542
|
+
before.get("reason") or "the wl CLI is not on PATH",
|
|
533
543
|
changed,
|
|
534
544
|
**fields,
|
|
535
545
|
)
|
|
@@ -541,11 +551,13 @@ def ensure_mcp() -> dict[str, Any]:
|
|
|
541
551
|
)
|
|
542
552
|
|
|
543
553
|
failures: list[str] = []
|
|
544
|
-
root = Path(plugin_root)
|
|
545
554
|
for name in checks.MCP_SERVERS:
|
|
546
|
-
|
|
555
|
+
subcommand = checks.MCP_SERVE_ARGS[name]
|
|
547
556
|
try:
|
|
548
|
-
|
|
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"])
|
|
549
561
|
proc = _run(
|
|
550
562
|
[
|
|
551
563
|
claude,
|
|
@@ -556,15 +568,17 @@ def ensure_mcp() -> dict[str, Any]:
|
|
|
556
568
|
"-s",
|
|
557
569
|
"user",
|
|
558
570
|
"--",
|
|
559
|
-
|
|
560
|
-
|
|
571
|
+
wl,
|
|
572
|
+
"mcp",
|
|
573
|
+
"serve",
|
|
574
|
+
subcommand,
|
|
561
575
|
]
|
|
562
576
|
)
|
|
563
577
|
except (OSError, subprocess.SubprocessError) as exc:
|
|
564
578
|
failures.append(f"{name}: {exc}")
|
|
565
579
|
continue
|
|
566
580
|
if proc.returncode == 0:
|
|
567
|
-
changed.append(f"mcp: registered {name} -> {
|
|
581
|
+
changed.append(f"mcp: registered {name} -> {wl} mcp serve {subcommand}")
|
|
568
582
|
else:
|
|
569
583
|
failures.append(f"{name}: {_failure(proc)}")
|
|
570
584
|
|
|
@@ -74,18 +74,31 @@ def _summary_lines(
|
|
|
74
74
|
is_flag=True,
|
|
75
75
|
help="Emit one five-state JSON envelope on stdout.",
|
|
76
76
|
)
|
|
77
|
-
|
|
77
|
+
@click.option(
|
|
78
|
+
"--require",
|
|
79
|
+
"require",
|
|
80
|
+
multiple=True,
|
|
81
|
+
metavar="CAPABILITY",
|
|
82
|
+
help=(
|
|
83
|
+
"Assert a capability is available (repeatable). The consumer contract "
|
|
84
|
+
"is the capability name, not a version string; a missing or unknown "
|
|
85
|
+
"name exits 1 with status 'error'."
|
|
86
|
+
),
|
|
87
|
+
)
|
|
88
|
+
def check(as_json: bool, require: tuple[str, ...]) -> None:
|
|
78
89
|
"""Report the running wl: version, executable, platform and capabilities.
|
|
79
90
|
|
|
80
91
|
Read-only. In ``--json`` mode stdout is exactly one envelope line and
|
|
81
92
|
diagnostics go to stderr; the probe itself runs in a temporary CWD and the
|
|
82
93
|
dispatcher skips the startup ``.wl`` self-sync (#220), so the caller's
|
|
83
|
-
directory is never written to.
|
|
94
|
+
directory is never written to. ``--require`` turns the report into an
|
|
95
|
+
assertion: consumers gate on capability names, never on a version string
|
|
96
|
+
(#231).
|
|
84
97
|
"""
|
|
85
98
|
if as_json:
|
|
86
|
-
raise SystemExit(emit_check())
|
|
99
|
+
raise SystemExit(emit_check(require))
|
|
87
100
|
|
|
88
|
-
status, reason, fields = build_payload()
|
|
101
|
+
status, reason, fields = build_payload(require=require)
|
|
89
102
|
for line in _summary_lines(status, reason, fields):
|
|
90
103
|
click.echo(line)
|
|
91
104
|
raise SystemExit(exit_code(status))
|