meshcode 2.11.27__tar.gz → 2.11.31__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.
- {meshcode-2.11.27 → meshcode-2.11.31}/PKG-INFO +1 -1
- {meshcode-2.11.27 → meshcode-2.11.31}/meshcode/__init__.py +1 -1
- {meshcode-2.11.27 → meshcode-2.11.31}/meshcode/meshcode_mcp/server.py +49 -10
- {meshcode-2.11.27 → meshcode-2.11.31}/meshcode/setup_clients.py +208 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/meshcode.egg-info/PKG-INFO +1 -1
- {meshcode-2.11.27 → meshcode-2.11.31}/pyproject.toml +1 -1
- {meshcode-2.11.27 → meshcode-2.11.31}/tests/test_auto_update_hardening.py +58 -1
- {meshcode-2.11.27 → meshcode-2.11.31}/README.md +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/meshcode/__main__.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/meshcode/_stop_hook_template.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/meshcode/ascii_art.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/meshcode/atomic_push.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/meshcode/cli.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/meshcode/comms_v4.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/meshcode/compat.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/meshcode/daemon.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/meshcode/date_parse.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/meshcode/doctor.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/meshcode/error_hints.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/meshcode/exceptions.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/meshcode/invites.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/meshcode/launcher.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/meshcode/launcher_install.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/meshcode/meshcode_mcp/__init__.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/meshcode/meshcode_mcp/__main__.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/meshcode/meshcode_mcp/backend.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/meshcode/meshcode_mcp/realtime.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/meshcode/meshcode_mcp/sleep_signals.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/meshcode/meshcode_mcp/test_backend.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/meshcode/meshcode_mcp/test_boot_timing.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/meshcode/meshcode_mcp/test_install_guard.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/meshcode/meshcode_mcp/test_prefs_claude_version.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/meshcode/meshcode_mcp/test_realtime.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/meshcode/meshcode_mcp/test_server_wrapper.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/meshcode/preferences.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/meshcode/protocol_handler.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/meshcode/protocol_v2.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/meshcode/quickstart.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/meshcode/rpc_allowlist.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/meshcode/run_agent.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/meshcode/scripts/check_secrets.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/meshcode/scripts/race_rate_harness.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/meshcode/secrets.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/meshcode/self_update.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/meshcode/supervisor.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/meshcode/upload.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/meshcode-backend-wt/comms_v4.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/meshcode-backend-wt/meshcode/__init__.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/meshcode-backend-wt/meshcode/ascii_art.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/meshcode-backend-wt/meshcode/cli.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/meshcode-backend-wt/meshcode/comms_v4.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/meshcode-backend-wt/meshcode/compat.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/meshcode-backend-wt/meshcode/error_hints.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/meshcode-backend-wt/meshcode/exceptions.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/meshcode-backend-wt/meshcode/invites.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/meshcode-backend-wt/meshcode/launcher.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/meshcode-backend-wt/meshcode/launcher_install.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/meshcode-backend-wt/meshcode/meshcode_mcp/__init__.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/meshcode-backend-wt/meshcode/meshcode_mcp/__main__.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/meshcode-backend-wt/meshcode/meshcode_mcp/backend.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/meshcode-backend-wt/meshcode/meshcode_mcp/realtime.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/meshcode-backend-wt/meshcode/meshcode_mcp/server.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/meshcode-backend-wt/meshcode/meshcode_mcp/test_backend.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/meshcode-backend-wt/meshcode/meshcode_mcp/test_realtime.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/meshcode-backend-wt/meshcode/meshcode_mcp/test_server_wrapper.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/meshcode-backend-wt/meshcode/preferences.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/meshcode-backend-wt/meshcode/protocol_v2.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/meshcode-backend-wt/meshcode/quickstart.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/meshcode-backend-wt/meshcode/run_agent.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/meshcode-backend-wt/meshcode/secrets.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/meshcode-backend-wt/meshcode/self_update.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/meshcode-backend-wt/meshcode/setup_clients.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/meshcode-backend-wt/meshcode/supervisor.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/meshcode-backend-wt/meshcode/upload.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/meshcode-backend-wt/scripts/sentinel.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/meshcode-backend-wt/tests/test_core.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/meshcode-backend-wt/tests/test_cross_agent_messaging.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/meshcode-backend-wt/tests/test_esc_deaf_state.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/meshcode-backend-wt/tests/test_exceptions.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/meshcode-backend-wt/tests/test_mark_read_batch.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/meshcode-backend-wt/tests/test_migration_integrity.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/meshcode-backend-wt/tests/test_realtime_event_freshness.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/meshcode-backend-wt/tests/test_rls_cross_tenant.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/meshcode-backend-wt/tests/test_rpc_migrations.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/meshcode-backend-wt/tests/test_security_regressions.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/meshcode-backend-wt/tests/test_sentinel.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/meshcode-backend-wt/tests/test_status_enum_coverage.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/meshcode-noun-wt/build/lib/meshcode/__init__.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/meshcode-noun-wt/build/lib/meshcode/ascii_art.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/meshcode-noun-wt/build/lib/meshcode/cli.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/meshcode-noun-wt/build/lib/meshcode/comms_v4.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/meshcode-noun-wt/build/lib/meshcode/compat.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/meshcode-noun-wt/build/lib/meshcode/error_hints.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/meshcode-noun-wt/build/lib/meshcode/exceptions.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/meshcode-noun-wt/build/lib/meshcode/invites.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/meshcode-noun-wt/build/lib/meshcode/launcher.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/meshcode-noun-wt/build/lib/meshcode/launcher_install.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/meshcode-noun-wt/build/lib/meshcode/meshcode_mcp/__init__.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/meshcode-noun-wt/build/lib/meshcode/meshcode_mcp/__main__.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/meshcode-noun-wt/build/lib/meshcode/meshcode_mcp/backend.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/meshcode-noun-wt/build/lib/meshcode/meshcode_mcp/realtime.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/meshcode-noun-wt/build/lib/meshcode/meshcode_mcp/server.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/meshcode-noun-wt/build/lib/meshcode/meshcode_mcp/test_backend.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/meshcode-noun-wt/build/lib/meshcode/meshcode_mcp/test_realtime.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/meshcode-noun-wt/build/lib/meshcode/meshcode_mcp/test_server_wrapper.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/meshcode-noun-wt/build/lib/meshcode/preferences.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/meshcode-noun-wt/build/lib/meshcode/protocol_v2.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/meshcode-noun-wt/build/lib/meshcode/quickstart.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/meshcode-noun-wt/build/lib/meshcode/run_agent.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/meshcode-noun-wt/build/lib/meshcode/secrets.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/meshcode-noun-wt/build/lib/meshcode/self_update.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/meshcode-noun-wt/build/lib/meshcode/setup_clients.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/meshcode-noun-wt/build/lib/meshcode/supervisor.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/meshcode-noun-wt/build/lib/meshcode/upload.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/meshcode-noun-wt/comms_v4.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/meshcode-noun-wt/meshcode/__init__.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/meshcode-noun-wt/meshcode/ascii_art.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/meshcode-noun-wt/meshcode/cli.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/meshcode-noun-wt/meshcode/comms_v4.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/meshcode-noun-wt/meshcode/compat.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/meshcode-noun-wt/meshcode/error_hints.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/meshcode-noun-wt/meshcode/exceptions.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/meshcode-noun-wt/meshcode/invites.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/meshcode-noun-wt/meshcode/launcher.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/meshcode-noun-wt/meshcode/launcher_install.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/meshcode-noun-wt/meshcode/meshcode_mcp/__init__.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/meshcode-noun-wt/meshcode/meshcode_mcp/__main__.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/meshcode-noun-wt/meshcode/meshcode_mcp/backend.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/meshcode-noun-wt/meshcode/meshcode_mcp/realtime.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/meshcode-noun-wt/meshcode/meshcode_mcp/server.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/meshcode-noun-wt/meshcode/meshcode_mcp/test_backend.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/meshcode-noun-wt/meshcode/meshcode_mcp/test_realtime.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/meshcode-noun-wt/meshcode/meshcode_mcp/test_server_wrapper.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/meshcode-noun-wt/meshcode/preferences.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/meshcode-noun-wt/meshcode/protocol_v2.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/meshcode-noun-wt/meshcode/quickstart.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/meshcode-noun-wt/meshcode/run_agent.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/meshcode-noun-wt/meshcode/secrets.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/meshcode-noun-wt/meshcode/self_update.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/meshcode-noun-wt/meshcode/setup_clients.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/meshcode-noun-wt/meshcode/supervisor.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/meshcode-noun-wt/meshcode/upload.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/meshcode-noun-wt/scripts/sentinel.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/meshcode-noun-wt/tests/test_core.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/meshcode-noun-wt/tests/test_cross_agent_messaging.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/meshcode-noun-wt/tests/test_esc_deaf_state.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/meshcode-noun-wt/tests/test_exceptions.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/meshcode-noun-wt/tests/test_mark_read_batch.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/meshcode-noun-wt/tests/test_migration_integrity.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/meshcode-noun-wt/tests/test_realtime_event_freshness.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/meshcode-noun-wt/tests/test_rls_cross_tenant.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/meshcode-noun-wt/tests/test_rpc_migrations.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/meshcode-noun-wt/tests/test_security_regressions.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/meshcode-noun-wt/tests/test_sentinel.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/meshcode-noun-wt/tests/test_status_enum_coverage.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/meshcode-tasks-wt/comms_v4.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/meshcode-tasks-wt/meshcode/__init__.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/meshcode-tasks-wt/meshcode/ascii_art.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/meshcode-tasks-wt/meshcode/cli.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/meshcode-tasks-wt/meshcode/comms_v4.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/meshcode-tasks-wt/meshcode/compat.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/meshcode-tasks-wt/meshcode/error_hints.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/meshcode-tasks-wt/meshcode/exceptions.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/meshcode-tasks-wt/meshcode/invites.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/meshcode-tasks-wt/meshcode/launcher.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/meshcode-tasks-wt/meshcode/launcher_install.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/meshcode-tasks-wt/meshcode/meshcode_mcp/__init__.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/meshcode-tasks-wt/meshcode/meshcode_mcp/__main__.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/meshcode-tasks-wt/meshcode/meshcode_mcp/backend.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/meshcode-tasks-wt/meshcode/meshcode_mcp/realtime.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/meshcode-tasks-wt/meshcode/meshcode_mcp/server.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/meshcode-tasks-wt/meshcode/meshcode_mcp/test_backend.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/meshcode-tasks-wt/meshcode/meshcode_mcp/test_realtime.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/meshcode-tasks-wt/meshcode/meshcode_mcp/test_server_wrapper.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/meshcode-tasks-wt/meshcode/preferences.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/meshcode-tasks-wt/meshcode/protocol_v2.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/meshcode-tasks-wt/meshcode/quickstart.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/meshcode-tasks-wt/meshcode/run_agent.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/meshcode-tasks-wt/meshcode/secrets.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/meshcode-tasks-wt/meshcode/self_update.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/meshcode-tasks-wt/meshcode/setup_clients.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/meshcode-tasks-wt/meshcode/supervisor.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/meshcode-tasks-wt/meshcode/upload.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/meshcode-tasks-wt/scripts/sentinel.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/meshcode-tasks-wt/tests/test_core.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/meshcode-tasks-wt/tests/test_cross_agent_messaging.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/meshcode-tasks-wt/tests/test_esc_deaf_state.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/meshcode-tasks-wt/tests/test_exceptions.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/meshcode-tasks-wt/tests/test_mark_read_batch.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/meshcode-tasks-wt/tests/test_migration_integrity.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/meshcode-tasks-wt/tests/test_realtime_event_freshness.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/meshcode-tasks-wt/tests/test_rls_cross_tenant.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/meshcode-tasks-wt/tests/test_rpc_migrations.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/meshcode-tasks-wt/tests/test_security_regressions.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/meshcode-tasks-wt/tests/test_sentinel.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/meshcode-tasks-wt/tests/test_status_enum_coverage.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/meshcode.egg-info/SOURCES.txt +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/meshcode.egg-info/dependency_links.txt +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/meshcode.egg-info/entry_points.txt +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/meshcode.egg-info/requires.txt +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/meshcode.egg-info/top_level.txt +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/setup.cfg +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/tests/test_boot_bug_regression.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/tests/test_color_truecolor.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/tests/test_core.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/tests/test_cross_agent_messaging.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/tests/test_date_parse.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/tests/test_doctor.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/tests/test_epistemic_v1_python_sdk.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/tests/test_epistemic_v1_stop_conditions.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/tests/test_esc_deaf_state.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/tests/test_exceptions.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/tests/test_init_device_code.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/tests/test_install_guard.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/tests/test_lease_sigterm_release.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/tests/test_mark_read_batch.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/tests/test_migration_integrity.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/tests/test_realtime_event_freshness.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/tests/test_rls_cross_tenant.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/tests/test_rpc_grants.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/tests/test_rpc_migrations.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/tests/test_run_agent_dry_run.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/tests/test_run_agent_no_server_import.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/tests/test_security_regressions.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/tests/test_self_update_user_site.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/tests/test_sentinel.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/tests/test_setup_path.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/tests/test_sleep_signals.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/tests/test_status_enum_coverage.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/tests/test_stay_on_loop_hook.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.31}/tests/test_wait_open_tasks_contradiction.py +0 -0
|
@@ -227,18 +227,18 @@ def _kill_stale_mcp_process() -> None:
|
|
|
227
227
|
_force_clear_lease_by_name(reason="legacy-lockfile-orphan")
|
|
228
228
|
return
|
|
229
229
|
_mc_log(f"Killing stale MCP process (PID {old_pid})")
|
|
230
|
+
# 2026-05-21 (Samuel directive RCA): the dying MCP server installs
|
|
231
|
+
# _diag_ignore for SIGTERM to keep the channel alive during tool
|
|
232
|
+
# cancellation (see run_server). SIGTERM is therefore always ignored
|
|
233
|
+
# by stale meshcode servers — sending it + sleeping 1s before SIGKILL
|
|
234
|
+
# was pure dead weight on the lifespan pre-yield critical path. Going
|
|
235
|
+
# straight to SIGKILL saves ~1s on every cold boot where a stale
|
|
236
|
+
# process exists. SIGKILL is uncatchable, so the kill is instant.
|
|
230
237
|
try:
|
|
231
|
-
os.kill(old_pid, _signal.SIGTERM)
|
|
232
|
-
except OSError:
|
|
233
|
-
pass
|
|
234
|
-
import time
|
|
235
|
-
time.sleep(1)
|
|
236
|
-
try:
|
|
237
|
-
os.kill(old_pid, 0)
|
|
238
238
|
os.kill(old_pid, _signal.SIGKILL)
|
|
239
239
|
_mc_log(f"Force-killed stale MCP process (PID {old_pid})")
|
|
240
240
|
except OSError:
|
|
241
|
-
pass # already dead
|
|
241
|
+
pass # already dead — race with previous process's own shutdown
|
|
242
242
|
if old_instance_id:
|
|
243
243
|
_release_lease_for_instance(old_instance_id, reason="post-sigkill")
|
|
244
244
|
else:
|
|
@@ -3299,6 +3299,33 @@ def _get_pending_tasks_summary() -> Optional[List[Dict[str, str]]]:
|
|
|
3299
3299
|
return None
|
|
3300
3300
|
|
|
3301
3301
|
|
|
3302
|
+
def _attach_pending_tasks_to_resp(resp: Dict[str, Any]) -> Dict[str, Any]:
|
|
3303
|
+
"""Surface this agent's open/in_progress assigned tasks on EVERY wait response.
|
|
3304
|
+
|
|
3305
|
+
Samuel directive 2026-05-21T23:54Z: agents must always advance open tasks.
|
|
3306
|
+
Previously `pending_tasks` only appeared in the timeout branch; when
|
|
3307
|
+
messages kept arriving the agent ping-ponged replies and never saw the
|
|
3308
|
+
hint, so tasks piled up. Now: every wait response (refused-by-messages,
|
|
3309
|
+
got_message, timeout) carries pending_tasks + pending_directive when
|
|
3310
|
+
this agent has open work. The agent's instruction prompt treats the
|
|
3311
|
+
directive as priority-1 over optional message replies.
|
|
3312
|
+
"""
|
|
3313
|
+
try:
|
|
3314
|
+
pending = _get_pending_tasks_summary()
|
|
3315
|
+
if pending and isinstance(resp, dict):
|
|
3316
|
+
resp["pending_tasks"] = pending
|
|
3317
|
+
resp["pending_tasks_count"] = len(pending)
|
|
3318
|
+
titles = ", ".join(t.get("title", "")[:40] for t in pending[:3])
|
|
3319
|
+
resp["pending_directive"] = (
|
|
3320
|
+
f"You have {len(pending)} open task(s) assigned. Advance at least one "
|
|
3321
|
+
f"(claim / progress / complete) BEFORE processing optional messages or "
|
|
3322
|
+
f"re-entering wait. Tasks: {titles}"
|
|
3323
|
+
)
|
|
3324
|
+
except Exception:
|
|
3325
|
+
pass
|
|
3326
|
+
return resp
|
|
3327
|
+
|
|
3328
|
+
|
|
3302
3329
|
def _try_auto_claim_task() -> Optional[Dict[str, str]]:
|
|
3303
3330
|
"""Auto-claim the oldest open task matching this agent's role.
|
|
3304
3331
|
|
|
@@ -3405,7 +3432,7 @@ async def meshcode_wait(timeout_seconds: int = 20, include_acks: bool = False) -
|
|
|
3405
3432
|
if split["done_signals"]:
|
|
3406
3433
|
resp["must_exit"] = True
|
|
3407
3434
|
resp["exit_reason"] = "sleep authorization received — set status=sleeping and end session"
|
|
3408
|
-
return resp
|
|
3435
|
+
return _attach_pending_tasks_to_resp(resp)
|
|
3409
3436
|
# Ack-only batch — fall through to wait loop
|
|
3410
3437
|
except Exception:
|
|
3411
3438
|
pass
|
|
@@ -3516,7 +3543,7 @@ async def meshcode_wait(timeout_seconds: int = 20, include_acks: bool = False) -
|
|
|
3516
3543
|
result.setdefault("must_exit", True)
|
|
3517
3544
|
result.setdefault("exit_reason",
|
|
3518
3545
|
"sleep authorization received — set status=sleeping and end session")
|
|
3519
|
-
return result
|
|
3546
|
+
return _attach_pending_tasks_to_resp(result) if isinstance(result, dict) else result
|
|
3520
3547
|
finally:
|
|
3521
3548
|
_IN_WAIT = False
|
|
3522
3549
|
|
|
@@ -6104,6 +6131,18 @@ def _auto_update() -> None:
|
|
|
6104
6131
|
# legitimate upgrade check. Per task 8d5eed7a.
|
|
6105
6132
|
os.environ.pop("MESHCODE_UPDATED", None)
|
|
6106
6133
|
return
|
|
6134
|
+
# MCP-serve guard: this function runs synchronously at the top of
|
|
6135
|
+
# run_server(), BEFORE FastMCP starts serving JSON-RPC. A blocking
|
|
6136
|
+
# `pip install --upgrade` (timeout 60s) here easily blows Claude
|
|
6137
|
+
# Code's MCP handshake window (~5s) — tools never register and the
|
|
6138
|
+
# agent boots into "MCP tools not available". The CLI-side
|
|
6139
|
+
# self_update.py (spawned by `meshcode go` before execv into the
|
|
6140
|
+
# editor) already handles user-facing upgrades; in MCP serve context
|
|
6141
|
+
# we should never block the handshake to chase a newer version.
|
|
6142
|
+
# Detected via the MESHCODE_MCP_SERVE=1 sentinel set in __main__.py.
|
|
6143
|
+
if os.environ.get("MESHCODE_MCP_SERVE") == "1":
|
|
6144
|
+
log.debug("[meshcode] Auto-update skipped in MCP serve subprocess (CLI handles upgrades)")
|
|
6145
|
+
return
|
|
6107
6146
|
|
|
6108
6147
|
# Time-gate (task c0e7de87, 2026-05-19): the PyPI HEAD GET below has a 3s
|
|
6109
6148
|
# timeout (line ~5430) and pip-install another 60s. Hammering PyPI on
|
|
@@ -565,6 +565,46 @@ errors when the source actually broke. Lovable build then ships the
|
|
|
565
565
|
broken bundle.
|
|
566
566
|
|
|
567
567
|
**Why:** practiced manually for weeks; codify so new FE agents inherit.
|
|
568
|
+
""",
|
|
569
|
+
"mobile-first-verify.md": """# /mobile-first-verify — 3-viewport check before task_complete
|
|
570
|
+
|
|
571
|
+
Before calling `meshcode_task_complete` on any UI-touching task, run
|
|
572
|
+
Playwright at three viewports and attach the result in the summary.
|
|
573
|
+
|
|
574
|
+
Viewports (canonical):
|
|
575
|
+
- iPhone SE 375 x 667
|
|
576
|
+
- iPhone 15 Pro 390 x 844
|
|
577
|
+
- iPad 768 x 1024
|
|
578
|
+
|
|
579
|
+
Recipe (load `mcp__playwright__browser_*` via ToolSearch first):
|
|
580
|
+
|
|
581
|
+
```
|
|
582
|
+
for w,h in [(375,667),(390,844),(768,1024)]:
|
|
583
|
+
browser_resize(width=w, height=h)
|
|
584
|
+
browser_navigate(url=<route>)
|
|
585
|
+
browser_take_screenshot(filename=f"verify_{w}x{h}.png")
|
|
586
|
+
browser_console_messages() # capture errors
|
|
587
|
+
```
|
|
588
|
+
|
|
589
|
+
Then `meshcode_task_complete(task_id, summary=<<EOF
|
|
590
|
+
verified: 3-viewport playwright
|
|
591
|
+
- 375x667: <path>
|
|
592
|
+
- 390x844: <path>
|
|
593
|
+
- 768x1024: <path>
|
|
594
|
+
console_errors: <count or "none">
|
|
595
|
+
EOF)`.
|
|
596
|
+
|
|
597
|
+
If the task is backend-only (DDL, RPCs, RLS, hooks, scripts — no user
|
|
598
|
+
surface), skip the playwright run but state `verified: backend-only,
|
|
599
|
+
no UI surface` in the summary so the auditor knows it was considered.
|
|
600
|
+
|
|
601
|
+
Reopen path: Samuel reviews; if visuals are broken he calls
|
|
602
|
+
`meshcode_task_reject(task_id, feedback=...)` which reopens with
|
|
603
|
+
review_feedback. No new RPC needed.
|
|
604
|
+
|
|
605
|
+
**Why:** MOBILE-FIRST-2 + Samuel mobile directive. Catches mobile
|
|
606
|
+
breakage at the agent before it reaches Samuel as a screenshot in
|
|
607
|
+
chat. Pairs with `/playwright-self-test` which covers desktop only.
|
|
568
608
|
""",
|
|
569
609
|
}
|
|
570
610
|
|
|
@@ -764,6 +804,134 @@ incidents from rapid-fire publish without bundling.
|
|
|
764
804
|
""",
|
|
765
805
|
}
|
|
766
806
|
|
|
807
|
+
# ============================================================
|
|
808
|
+
# SKILLS-6 — mobile-qa role bundle (MOBILE-FIRST-5)
|
|
809
|
+
# ============================================================
|
|
810
|
+
# Parallel verify lane: while front-end/front-2 ship code, a mobile-qa
|
|
811
|
+
# agent independently re-renders the affected route at 3 mobile/tablet
|
|
812
|
+
# viewports, captures screenshots + console errors, and reports findings
|
|
813
|
+
# back to the ship-er agent + commander. Removes verify-bottleneck from
|
|
814
|
+
# the coding agents and gives Samuel a second pair of eyes on every
|
|
815
|
+
# UI-touching commit.
|
|
816
|
+
#
|
|
817
|
+
# Agent type does NOT ship code. Pure verifier.
|
|
818
|
+
_MOBILE_QA_SKILLS = {
|
|
819
|
+
"mobile-qa-boot-loop.md": """# /mobile-qa-boot-loop — verify-only agent boot workflow
|
|
820
|
+
|
|
821
|
+
You are a mobile-qa agent. You DO NOT ship code. Your only job is to
|
|
822
|
+
re-render UI changes that other agents shipped, at three viewports,
|
|
823
|
+
and report what you see.
|
|
824
|
+
|
|
825
|
+
Boot sequence (after the standard meshcode boot):
|
|
826
|
+
|
|
827
|
+
1. `meshcode_tasks(status_filter="open")` filter assignee == this agent
|
|
828
|
+
OR title/description mentions `needs_mobile_qa` / `verify` / `qa`.
|
|
829
|
+
2. For each candidate task: claim → fetch the route or commit referenced
|
|
830
|
+
→ run `/viewports-3-recipe` → assemble `/mobile-qa-report-format` →
|
|
831
|
+
`meshcode_send` the report to the original ship-er (look at
|
|
832
|
+
parent_task_id chain or claimed_by on the parent task) AND to
|
|
833
|
+
commander.
|
|
834
|
+
3. `meshcode_task_complete` with the report inlined in summary.
|
|
835
|
+
|
|
836
|
+
If no verify tasks are queued: `meshcode_wait` and sit.
|
|
837
|
+
|
|
838
|
+
DO NOT:
|
|
839
|
+
- write code into `src/`
|
|
840
|
+
- propose RPC / DDL changes
|
|
841
|
+
- broadcast opinions about design
|
|
842
|
+
|
|
843
|
+
DO:
|
|
844
|
+
- screenshot + console + network requests
|
|
845
|
+
- report objective signals: layout overflow, console errors, network
|
|
846
|
+
500s, missing assets
|
|
847
|
+
|
|
848
|
+
**Why:** MOBILE-FIRST-5. Parallel verify lane keeps shipping agents
|
|
849
|
+
unblocked while still catching mobile regressions before Samuel does.
|
|
850
|
+
""",
|
|
851
|
+
"viewports-3-recipe.md": """# /viewports-3-recipe — canonical 3-viewport playwright run
|
|
852
|
+
|
|
853
|
+
Three viewports, every time, in this order:
|
|
854
|
+
|
|
855
|
+
| Device | Width | Height |
|
|
856
|
+
|----------------|-------:|-------:|
|
|
857
|
+
| iPhone SE | 375 | 667 |
|
|
858
|
+
| iPhone 15 Pro | 390 | 844 |
|
|
859
|
+
| iPad | 768 | 1024 |
|
|
860
|
+
|
|
861
|
+
Recipe (load `mcp__playwright__browser_*` via ToolSearch if deferred):
|
|
862
|
+
|
|
863
|
+
```python
|
|
864
|
+
for w, h in [(375, 667), (390, 844), (768, 1024)]:
|
|
865
|
+
browser_resize(width=w, height=h)
|
|
866
|
+
browser_navigate(url=<route>)
|
|
867
|
+
browser_wait_for(time=2) # let layout settle
|
|
868
|
+
browser_take_screenshot(filename=f"mqa_{w}x{h}.png")
|
|
869
|
+
console = browser_console_messages()
|
|
870
|
+
network = browser_network_requests()
|
|
871
|
+
# capture: scrollWidth > clientWidth → horizontal overflow flag
|
|
872
|
+
overflow = browser_evaluate(
|
|
873
|
+
function="() => document.documentElement.scrollWidth > "
|
|
874
|
+
"document.documentElement.clientWidth"
|
|
875
|
+
)
|
|
876
|
+
```
|
|
877
|
+
|
|
878
|
+
For each viewport collect:
|
|
879
|
+
- screenshot path
|
|
880
|
+
- console_messages count + first-3 errors verbatim
|
|
881
|
+
- network_requests with status >= 400 (path + status)
|
|
882
|
+
- horizontal_overflow: bool
|
|
883
|
+
|
|
884
|
+
**Why:** standard viewports make reports comparable across days /
|
|
885
|
+
across agents. Console + network + overflow are the cheap signals that
|
|
886
|
+
catch ~80% of mobile regressions.
|
|
887
|
+
""",
|
|
888
|
+
"mobile-qa-report-format.md": """# /mobile-qa-report-format — canonical report shape
|
|
889
|
+
|
|
890
|
+
Report back to ship-er + commander in this exact JSON shape so consumers
|
|
891
|
+
can parse without LLM cost:
|
|
892
|
+
|
|
893
|
+
```json
|
|
894
|
+
{
|
|
895
|
+
"type": "mobile_qa_report",
|
|
896
|
+
"parent_task_id": "<task that requested verify>",
|
|
897
|
+
"verified_commit": "<short sha>",
|
|
898
|
+
"route": "<path verified>",
|
|
899
|
+
"viewports": [
|
|
900
|
+
{
|
|
901
|
+
"label": "iPhone SE",
|
|
902
|
+
"size": "375x667",
|
|
903
|
+
"screenshot": "<abs path>",
|
|
904
|
+
"console_errors": 0,
|
|
905
|
+
"first_errors": [],
|
|
906
|
+
"network_4xx_5xx": [],
|
|
907
|
+
"horizontal_overflow": false
|
|
908
|
+
},
|
|
909
|
+
{ "label": "iPhone 15 Pro", "size": "390x844", "...": "..." },
|
|
910
|
+
{ "label": "iPad", "size": "768x1024", "...": "..." }
|
|
911
|
+
],
|
|
912
|
+
"verdict": "pass" | "fail" | "warn",
|
|
913
|
+
"fail_reasons": [],
|
|
914
|
+
"samuel_status_line": "mobile-qa: <route> OK on 3 viewports / FAIL on iPhone SE (horizontal overflow + 2 console errors)"
|
|
915
|
+
}
|
|
916
|
+
```
|
|
917
|
+
|
|
918
|
+
Verdict rubric:
|
|
919
|
+
- **pass**: 0 console_errors AND 0 network 4xx/5xx AND 0
|
|
920
|
+
horizontal_overflow on all 3 viewports.
|
|
921
|
+
- **warn**: any viewport has 1-2 console_errors that are clearly
|
|
922
|
+
third-party (analytics, etc) AND no overflow.
|
|
923
|
+
- **fail**: any console error from app code, any network 4xx/5xx, any
|
|
924
|
+
horizontal_overflow, OR layout clearly visually broken.
|
|
925
|
+
|
|
926
|
+
`samuel_status_line` is the 1-line summary Samuel sees in his feed;
|
|
927
|
+
make it actionable.
|
|
928
|
+
|
|
929
|
+
**Why:** structured reports let the FE agents auto-handle warn/fail
|
|
930
|
+
without commander intervention. Free-form text needs LLM parse on
|
|
931
|
+
every consumer; JSON does not.
|
|
932
|
+
""",
|
|
933
|
+
}
|
|
934
|
+
|
|
767
935
|
|
|
768
936
|
def _write_generic_skills_bundle(ws: Path, role: str = "") -> None:
|
|
769
937
|
"""Write skill bundles to {ws}/.claude/skills/.
|
|
@@ -789,6 +957,8 @@ def _write_generic_skills_bundle(ws: Path, role: str = "") -> None:
|
|
|
789
957
|
elif role_norm in ("commander", "mesh-commander", "zylo-commander",
|
|
790
958
|
"bemate-commander"):
|
|
791
959
|
role_bundle = _COMMANDER_SKILLS
|
|
960
|
+
elif role_norm in ("mobile-qa", "mobile_qa", "mobileqa", "mqa"):
|
|
961
|
+
role_bundle = _MOBILE_QA_SKILLS
|
|
792
962
|
|
|
793
963
|
for fname, body in role_bundle.items():
|
|
794
964
|
(skills_dir / fname).write_text(body, encoding="utf-8")
|
|
@@ -1004,6 +1174,44 @@ If `meshcode_wait()` times out, call it again with a 2× longer timeout (cap 180
|
|
|
1004
1174
|
- Memory: `meshcode_remember(key, value)` for reusable learnings. Don't dump
|
|
1005
1175
|
task summaries into memory — tasks already persist.
|
|
1006
1176
|
|
|
1177
|
+
## Mobile-first UI verification (before task_complete)
|
|
1178
|
+
|
|
1179
|
+
Before calling `meshcode_task_complete` on ANY task that touches user-visible
|
|
1180
|
+
UI (routes, components, layouts, styles, mobile chrome), you MUST run
|
|
1181
|
+
Playwright at three viewports and attach the result in the completion summary.
|
|
1182
|
+
|
|
1183
|
+
Viewports (canonical):
|
|
1184
|
+
- iPhone SE 375 x 667
|
|
1185
|
+
- iPhone 15 Pro 390 x 844
|
|
1186
|
+
- iPad 768 x 1024
|
|
1187
|
+
|
|
1188
|
+
Workflow (uses `mcp__playwright__browser_*` — load via ToolSearch if deferred):
|
|
1189
|
+
|
|
1190
|
+
1. For each viewport: `browser_resize` → `browser_navigate(<route>)` →
|
|
1191
|
+
`browser_take_screenshot(filename="verify_<W>x<H>.png")` →
|
|
1192
|
+
`browser_console_messages()`.
|
|
1193
|
+
2. Pass the three screenshot paths + console-error count in the
|
|
1194
|
+
`summary` arg of `meshcode_task_complete`:
|
|
1195
|
+
|
|
1196
|
+
```
|
|
1197
|
+
verified: 3-viewport playwright
|
|
1198
|
+
- 375x667: <path>
|
|
1199
|
+
- 390x844: <path>
|
|
1200
|
+
- 768x1024: <path>
|
|
1201
|
+
console_errors: <count or "none">
|
|
1202
|
+
```
|
|
1203
|
+
|
|
1204
|
+
3. Samuel reviews the summary. If visuals are broken he calls
|
|
1205
|
+
`meshcode_task_reject(task_id, feedback=...)` which reopens the task with
|
|
1206
|
+
`review_feedback`. No new RPC needed — uses the existing pipeline.
|
|
1207
|
+
|
|
1208
|
+
If the task is backend-only (DDL, RPCs, RLS, hooks, scripts — no UI surface)
|
|
1209
|
+
the playwright run is skipped, but state `verified: backend-only, no UI
|
|
1210
|
+
surface` in the summary so the rule is acknowledged.
|
|
1211
|
+
|
|
1212
|
+
**Why:** Samuel mobile directive (MOBILE-FIRST-2). Catches mobile breakage at
|
|
1213
|
+
the agent before it reaches Samuel as a screenshot in chat.
|
|
1214
|
+
|
|
1007
1215
|
## When to use sync vs async
|
|
1008
1216
|
|
|
1009
1217
|
| Pattern | Tool | Why |
|
|
@@ -37,12 +37,18 @@ def _check_boot_version_drift_inline():
|
|
|
37
37
|
|
|
38
38
|
|
|
39
39
|
def _auto_update_inline_skeleton():
|
|
40
|
-
"""Subset of _auto_update covering the env-var gates only.
|
|
40
|
+
"""Subset of _auto_update covering the env-var gates only.
|
|
41
|
+
|
|
42
|
+
Order matters: the MCP-serve gate must fire BEFORE any network /
|
|
43
|
+
pip work so the MCP handshake window is never blocked.
|
|
44
|
+
"""
|
|
41
45
|
if os.environ.get("MESHCODE_AUTO_UPDATE", "1").lower() in ("0", "false", "no"):
|
|
42
46
|
return "disabled"
|
|
43
47
|
if os.environ.get("MESHCODE_UPDATED") == "1":
|
|
44
48
|
os.environ.pop("MESHCODE_UPDATED", None)
|
|
45
49
|
return "post_exec_skip"
|
|
50
|
+
if os.environ.get("MESHCODE_MCP_SERVE") == "1":
|
|
51
|
+
return "mcp_serve_skip"
|
|
46
52
|
return "would_check_pypi"
|
|
47
53
|
|
|
48
54
|
|
|
@@ -114,6 +120,57 @@ def test_auto_update_disabled_case_variants(monkeypatch):
|
|
|
114
120
|
assert _auto_update_inline_skeleton() == "disabled", f"value {val!r} failed"
|
|
115
121
|
|
|
116
122
|
|
|
123
|
+
# ---------------------------------------------------------------------------
|
|
124
|
+
# 3b. MCP-serve gate (added 2026-05-20 / 2.11.28)
|
|
125
|
+
#
|
|
126
|
+
# Symptom: right after publishing 2.11.27, commander agents booted with
|
|
127
|
+
# "MCP meshcode tools are not available" — first-turn deferred-tools list
|
|
128
|
+
# missing all meshcode_* tools. RC: _auto_update runs synchronously at the
|
|
129
|
+
# top of run_server() and does a blocking `pip install --upgrade` (60s
|
|
130
|
+
# timeout). When PyPI advertises a newer version, the install easily
|
|
131
|
+
# exceeds Claude Code's ~5s MCP handshake window and tools never register.
|
|
132
|
+
# Fix: skip _auto_update entirely when MESHCODE_MCP_SERVE=1; the CLI's
|
|
133
|
+
# self_update.py handles user-facing upgrades before execv.
|
|
134
|
+
# ---------------------------------------------------------------------------
|
|
135
|
+
|
|
136
|
+
def test_mcp_serve_sentinel_skips_update(monkeypatch):
|
|
137
|
+
monkeypatch.setenv("MESHCODE_MCP_SERVE", "1")
|
|
138
|
+
monkeypatch.delenv("MESHCODE_AUTO_UPDATE", raising=False)
|
|
139
|
+
monkeypatch.delenv("MESHCODE_UPDATED", raising=False)
|
|
140
|
+
assert _auto_update_inline_skeleton() == "mcp_serve_skip"
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
def test_mcp_serve_gate_runs_before_pypi(monkeypatch):
|
|
144
|
+
"""MCP-serve gate must short-circuit before any 'would_check_pypi'
|
|
145
|
+
branch fires — otherwise the gate is moot because the slow path
|
|
146
|
+
runs anyway."""
|
|
147
|
+
monkeypatch.setenv("MESHCODE_MCP_SERVE", "1")
|
|
148
|
+
monkeypatch.delenv("MESHCODE_AUTO_UPDATE", raising=False)
|
|
149
|
+
monkeypatch.delenv("MESHCODE_UPDATED", raising=False)
|
|
150
|
+
assert _auto_update_inline_skeleton() != "would_check_pypi"
|
|
151
|
+
|
|
152
|
+
|
|
153
|
+
def test_disabled_still_wins_over_mcp_serve(monkeypatch):
|
|
154
|
+
"""Explicit MESHCODE_AUTO_UPDATE=0 must remain the highest-priority
|
|
155
|
+
opt-out — useful for CI / debugging where the user wants to be
|
|
156
|
+
100% certain no pip side-effects fire."""
|
|
157
|
+
monkeypatch.setenv("MESHCODE_AUTO_UPDATE", "0")
|
|
158
|
+
monkeypatch.setenv("MESHCODE_MCP_SERVE", "1")
|
|
159
|
+
monkeypatch.delenv("MESHCODE_UPDATED", raising=False)
|
|
160
|
+
assert _auto_update_inline_skeleton() == "disabled"
|
|
161
|
+
|
|
162
|
+
|
|
163
|
+
def test_post_exec_sentinel_still_wins_over_mcp_serve(monkeypatch):
|
|
164
|
+
"""If we just re-execed after an upgrade, the UPDATED sentinel
|
|
165
|
+
must still take precedence so it gets cleared (otherwise it
|
|
166
|
+
persists into subprocess children)."""
|
|
167
|
+
monkeypatch.setenv("MESHCODE_UPDATED", "1")
|
|
168
|
+
monkeypatch.setenv("MESHCODE_MCP_SERVE", "1")
|
|
169
|
+
monkeypatch.delenv("MESHCODE_AUTO_UPDATE", raising=False)
|
|
170
|
+
assert _auto_update_inline_skeleton() == "post_exec_skip"
|
|
171
|
+
assert "MESHCODE_UPDATED" not in os.environ
|
|
172
|
+
|
|
173
|
+
|
|
117
174
|
# ---------------------------------------------------------------------------
|
|
118
175
|
# 4. PyPI/pip behaviour matrix (mocked — covers the cells that don't need
|
|
119
176
|
# a live relaunch). Uses an inlined version of the post-gate _auto_update
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{meshcode-2.11.27 → meshcode-2.11.31}/meshcode-backend-wt/meshcode/meshcode_mcp/test_backend.py
RENAMED
|
File without changes
|
{meshcode-2.11.27 → meshcode-2.11.31}/meshcode-backend-wt/meshcode/meshcode_mcp/test_realtime.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{meshcode-2.11.27 → meshcode-2.11.31}/meshcode-backend-wt/tests/test_cross_agent_messaging.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{meshcode-2.11.27 → meshcode-2.11.31}/meshcode-backend-wt/tests/test_realtime_event_freshness.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|