meshcode 2.11.27__tar.gz → 2.11.29__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.29}/PKG-INFO +1 -1
- {meshcode-2.11.27 → meshcode-2.11.29}/meshcode/__init__.py +1 -1
- {meshcode-2.11.27 → meshcode-2.11.29}/meshcode/meshcode_mcp/backend.py +31 -5
- {meshcode-2.11.27 → meshcode-2.11.29}/meshcode/meshcode_mcp/server.py +14 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/meshcode/setup_clients.py +208 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/meshcode.egg-info/PKG-INFO +1 -1
- {meshcode-2.11.27 → meshcode-2.11.29}/pyproject.toml +1 -1
- {meshcode-2.11.27 → meshcode-2.11.29}/tests/test_auto_update_hardening.py +58 -1
- {meshcode-2.11.27 → meshcode-2.11.29}/README.md +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/meshcode/__main__.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/meshcode/_stop_hook_template.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/meshcode/ascii_art.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/meshcode/atomic_push.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/meshcode/cli.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/meshcode/comms_v4.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/meshcode/compat.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/meshcode/daemon.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/meshcode/date_parse.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/meshcode/doctor.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/meshcode/error_hints.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/meshcode/exceptions.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/meshcode/invites.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/meshcode/launcher.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/meshcode/launcher_install.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/meshcode/meshcode_mcp/__init__.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/meshcode/meshcode_mcp/__main__.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/meshcode/meshcode_mcp/realtime.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/meshcode/meshcode_mcp/sleep_signals.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/meshcode/meshcode_mcp/test_backend.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/meshcode/meshcode_mcp/test_boot_timing.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/meshcode/meshcode_mcp/test_install_guard.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/meshcode/meshcode_mcp/test_prefs_claude_version.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/meshcode/meshcode_mcp/test_realtime.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/meshcode/meshcode_mcp/test_server_wrapper.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/meshcode/preferences.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/meshcode/protocol_handler.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/meshcode/protocol_v2.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/meshcode/quickstart.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/meshcode/rpc_allowlist.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/meshcode/run_agent.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/meshcode/scripts/check_secrets.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/meshcode/scripts/race_rate_harness.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/meshcode/secrets.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/meshcode/self_update.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/meshcode/supervisor.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/meshcode/upload.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/meshcode-backend-wt/comms_v4.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/meshcode-backend-wt/meshcode/__init__.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/meshcode-backend-wt/meshcode/ascii_art.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/meshcode-backend-wt/meshcode/cli.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/meshcode-backend-wt/meshcode/comms_v4.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/meshcode-backend-wt/meshcode/compat.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/meshcode-backend-wt/meshcode/error_hints.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/meshcode-backend-wt/meshcode/exceptions.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/meshcode-backend-wt/meshcode/invites.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/meshcode-backend-wt/meshcode/launcher.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/meshcode-backend-wt/meshcode/launcher_install.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/meshcode-backend-wt/meshcode/meshcode_mcp/__init__.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/meshcode-backend-wt/meshcode/meshcode_mcp/__main__.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/meshcode-backend-wt/meshcode/meshcode_mcp/backend.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/meshcode-backend-wt/meshcode/meshcode_mcp/realtime.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/meshcode-backend-wt/meshcode/meshcode_mcp/server.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/meshcode-backend-wt/meshcode/meshcode_mcp/test_backend.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/meshcode-backend-wt/meshcode/meshcode_mcp/test_realtime.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/meshcode-backend-wt/meshcode/meshcode_mcp/test_server_wrapper.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/meshcode-backend-wt/meshcode/preferences.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/meshcode-backend-wt/meshcode/protocol_v2.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/meshcode-backend-wt/meshcode/quickstart.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/meshcode-backend-wt/meshcode/run_agent.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/meshcode-backend-wt/meshcode/secrets.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/meshcode-backend-wt/meshcode/self_update.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/meshcode-backend-wt/meshcode/setup_clients.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/meshcode-backend-wt/meshcode/supervisor.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/meshcode-backend-wt/meshcode/upload.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/meshcode-backend-wt/scripts/sentinel.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/meshcode-backend-wt/tests/test_core.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/meshcode-backend-wt/tests/test_cross_agent_messaging.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/meshcode-backend-wt/tests/test_esc_deaf_state.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/meshcode-backend-wt/tests/test_exceptions.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/meshcode-backend-wt/tests/test_mark_read_batch.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/meshcode-backend-wt/tests/test_migration_integrity.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/meshcode-backend-wt/tests/test_realtime_event_freshness.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/meshcode-backend-wt/tests/test_rls_cross_tenant.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/meshcode-backend-wt/tests/test_rpc_migrations.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/meshcode-backend-wt/tests/test_security_regressions.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/meshcode-backend-wt/tests/test_sentinel.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/meshcode-backend-wt/tests/test_status_enum_coverage.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/meshcode-noun-wt/build/lib/meshcode/__init__.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/meshcode-noun-wt/build/lib/meshcode/ascii_art.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/meshcode-noun-wt/build/lib/meshcode/cli.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/meshcode-noun-wt/build/lib/meshcode/comms_v4.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/meshcode-noun-wt/build/lib/meshcode/compat.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/meshcode-noun-wt/build/lib/meshcode/error_hints.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/meshcode-noun-wt/build/lib/meshcode/exceptions.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/meshcode-noun-wt/build/lib/meshcode/invites.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/meshcode-noun-wt/build/lib/meshcode/launcher.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/meshcode-noun-wt/build/lib/meshcode/launcher_install.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/meshcode-noun-wt/build/lib/meshcode/meshcode_mcp/__init__.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/meshcode-noun-wt/build/lib/meshcode/meshcode_mcp/__main__.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/meshcode-noun-wt/build/lib/meshcode/meshcode_mcp/backend.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/meshcode-noun-wt/build/lib/meshcode/meshcode_mcp/realtime.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/meshcode-noun-wt/build/lib/meshcode/meshcode_mcp/server.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/meshcode-noun-wt/build/lib/meshcode/meshcode_mcp/test_backend.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/meshcode-noun-wt/build/lib/meshcode/meshcode_mcp/test_realtime.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/meshcode-noun-wt/build/lib/meshcode/meshcode_mcp/test_server_wrapper.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/meshcode-noun-wt/build/lib/meshcode/preferences.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/meshcode-noun-wt/build/lib/meshcode/protocol_v2.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/meshcode-noun-wt/build/lib/meshcode/quickstart.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/meshcode-noun-wt/build/lib/meshcode/run_agent.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/meshcode-noun-wt/build/lib/meshcode/secrets.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/meshcode-noun-wt/build/lib/meshcode/self_update.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/meshcode-noun-wt/build/lib/meshcode/setup_clients.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/meshcode-noun-wt/build/lib/meshcode/supervisor.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/meshcode-noun-wt/build/lib/meshcode/upload.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/meshcode-noun-wt/comms_v4.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/meshcode-noun-wt/meshcode/__init__.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/meshcode-noun-wt/meshcode/ascii_art.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/meshcode-noun-wt/meshcode/cli.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/meshcode-noun-wt/meshcode/comms_v4.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/meshcode-noun-wt/meshcode/compat.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/meshcode-noun-wt/meshcode/error_hints.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/meshcode-noun-wt/meshcode/exceptions.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/meshcode-noun-wt/meshcode/invites.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/meshcode-noun-wt/meshcode/launcher.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/meshcode-noun-wt/meshcode/launcher_install.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/meshcode-noun-wt/meshcode/meshcode_mcp/__init__.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/meshcode-noun-wt/meshcode/meshcode_mcp/__main__.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/meshcode-noun-wt/meshcode/meshcode_mcp/backend.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/meshcode-noun-wt/meshcode/meshcode_mcp/realtime.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/meshcode-noun-wt/meshcode/meshcode_mcp/server.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/meshcode-noun-wt/meshcode/meshcode_mcp/test_backend.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/meshcode-noun-wt/meshcode/meshcode_mcp/test_realtime.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/meshcode-noun-wt/meshcode/meshcode_mcp/test_server_wrapper.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/meshcode-noun-wt/meshcode/preferences.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/meshcode-noun-wt/meshcode/protocol_v2.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/meshcode-noun-wt/meshcode/quickstart.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/meshcode-noun-wt/meshcode/run_agent.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/meshcode-noun-wt/meshcode/secrets.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/meshcode-noun-wt/meshcode/self_update.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/meshcode-noun-wt/meshcode/setup_clients.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/meshcode-noun-wt/meshcode/supervisor.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/meshcode-noun-wt/meshcode/upload.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/meshcode-noun-wt/scripts/sentinel.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/meshcode-noun-wt/tests/test_core.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/meshcode-noun-wt/tests/test_cross_agent_messaging.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/meshcode-noun-wt/tests/test_esc_deaf_state.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/meshcode-noun-wt/tests/test_exceptions.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/meshcode-noun-wt/tests/test_mark_read_batch.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/meshcode-noun-wt/tests/test_migration_integrity.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/meshcode-noun-wt/tests/test_realtime_event_freshness.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/meshcode-noun-wt/tests/test_rls_cross_tenant.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/meshcode-noun-wt/tests/test_rpc_migrations.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/meshcode-noun-wt/tests/test_security_regressions.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/meshcode-noun-wt/tests/test_sentinel.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/meshcode-noun-wt/tests/test_status_enum_coverage.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/meshcode-tasks-wt/comms_v4.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/meshcode-tasks-wt/meshcode/__init__.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/meshcode-tasks-wt/meshcode/ascii_art.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/meshcode-tasks-wt/meshcode/cli.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/meshcode-tasks-wt/meshcode/comms_v4.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/meshcode-tasks-wt/meshcode/compat.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/meshcode-tasks-wt/meshcode/error_hints.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/meshcode-tasks-wt/meshcode/exceptions.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/meshcode-tasks-wt/meshcode/invites.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/meshcode-tasks-wt/meshcode/launcher.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/meshcode-tasks-wt/meshcode/launcher_install.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/meshcode-tasks-wt/meshcode/meshcode_mcp/__init__.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/meshcode-tasks-wt/meshcode/meshcode_mcp/__main__.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/meshcode-tasks-wt/meshcode/meshcode_mcp/backend.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/meshcode-tasks-wt/meshcode/meshcode_mcp/realtime.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/meshcode-tasks-wt/meshcode/meshcode_mcp/server.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/meshcode-tasks-wt/meshcode/meshcode_mcp/test_backend.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/meshcode-tasks-wt/meshcode/meshcode_mcp/test_realtime.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/meshcode-tasks-wt/meshcode/meshcode_mcp/test_server_wrapper.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/meshcode-tasks-wt/meshcode/preferences.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/meshcode-tasks-wt/meshcode/protocol_v2.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/meshcode-tasks-wt/meshcode/quickstart.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/meshcode-tasks-wt/meshcode/run_agent.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/meshcode-tasks-wt/meshcode/secrets.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/meshcode-tasks-wt/meshcode/self_update.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/meshcode-tasks-wt/meshcode/setup_clients.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/meshcode-tasks-wt/meshcode/supervisor.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/meshcode-tasks-wt/meshcode/upload.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/meshcode-tasks-wt/scripts/sentinel.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/meshcode-tasks-wt/tests/test_core.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/meshcode-tasks-wt/tests/test_cross_agent_messaging.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/meshcode-tasks-wt/tests/test_esc_deaf_state.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/meshcode-tasks-wt/tests/test_exceptions.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/meshcode-tasks-wt/tests/test_mark_read_batch.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/meshcode-tasks-wt/tests/test_migration_integrity.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/meshcode-tasks-wt/tests/test_realtime_event_freshness.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/meshcode-tasks-wt/tests/test_rls_cross_tenant.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/meshcode-tasks-wt/tests/test_rpc_migrations.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/meshcode-tasks-wt/tests/test_security_regressions.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/meshcode-tasks-wt/tests/test_sentinel.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/meshcode-tasks-wt/tests/test_status_enum_coverage.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/meshcode.egg-info/SOURCES.txt +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/meshcode.egg-info/dependency_links.txt +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/meshcode.egg-info/entry_points.txt +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/meshcode.egg-info/requires.txt +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/meshcode.egg-info/top_level.txt +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/setup.cfg +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/tests/test_boot_bug_regression.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/tests/test_color_truecolor.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/tests/test_core.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/tests/test_cross_agent_messaging.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/tests/test_date_parse.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/tests/test_doctor.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/tests/test_epistemic_v1_python_sdk.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/tests/test_epistemic_v1_stop_conditions.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/tests/test_esc_deaf_state.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/tests/test_exceptions.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/tests/test_init_device_code.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/tests/test_install_guard.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/tests/test_lease_sigterm_release.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/tests/test_mark_read_batch.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/tests/test_migration_integrity.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/tests/test_realtime_event_freshness.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/tests/test_rls_cross_tenant.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/tests/test_rpc_grants.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/tests/test_rpc_migrations.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/tests/test_run_agent_dry_run.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/tests/test_run_agent_no_server_import.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/tests/test_security_regressions.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/tests/test_self_update_user_site.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/tests/test_sentinel.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/tests/test_setup_path.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/tests/test_sleep_signals.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/tests/test_status_enum_coverage.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/tests/test_stay_on_loop_hook.py +0 -0
- {meshcode-2.11.27 → meshcode-2.11.29}/tests/test_wait_open_tasks_contradiction.py +0 -0
|
@@ -428,10 +428,16 @@ _recording_project_id = ""
|
|
|
428
428
|
_recording_agent_name = ""
|
|
429
429
|
_recording_session_id = ""
|
|
430
430
|
|
|
431
|
-
# RPCs that should NOT be recorded (internal/heartbeat/recording itself)
|
|
431
|
+
# RPCs that should NOT be recorded (internal/heartbeat/recording itself).
|
|
432
|
+
# M3a (SUPABASE-PROD-QUOTA-CRITICAL 2026-05-22): added mc_task_list +
|
|
433
|
+
# mc_count_pending + mc_mark_message_read — these were generating 87% of
|
|
434
|
+
# all session_events (~46k of 53k in last 6h) as null-tool tool_call rows
|
|
435
|
+
# from the wait-loop polling. Pure infrastructure noise — no analytic
|
|
436
|
+
# value. The session_events table was 1.2 GB driven mostly by these.
|
|
432
437
|
_SKIP_RECORDING = {"mc_heartbeat", "mc_record_event", "mc_agent_set_status_by_api_key",
|
|
433
438
|
"mc_acquire_agent_lease", "mc_release_agent_lease",
|
|
434
|
-
"mc_update_agent", "mc_get_agents"
|
|
439
|
+
"mc_update_agent", "mc_get_agents",
|
|
440
|
+
"mc_task_list", "mc_count_pending", "mc_mark_message_read"}
|
|
435
441
|
|
|
436
442
|
|
|
437
443
|
def _get_api_key() -> Optional[str]:
|
|
@@ -963,13 +969,22 @@ def read_inbox(project_id: str, agent: str, mark_read: bool = True, api_key: Opt
|
|
|
963
969
|
|
|
964
970
|
|
|
965
971
|
def count_pending(project_id: str, agent: str, api_key: Optional[str] = None) -> int:
|
|
966
|
-
# Use SECURITY DEFINER RPC when api_key is available
|
|
972
|
+
# Use SECURITY DEFINER RPC when api_key is available.
|
|
973
|
+
# SEC-5 R-SEC5-A: call rate-limited _rl wrapper. Server-side returns
|
|
974
|
+
# cached payload on limit so Python contract stays {ok:true, count:int}.
|
|
975
|
+
# Falls back to non-rl on 404 if the wrapper isn't deployed yet.
|
|
967
976
|
if api_key:
|
|
968
|
-
result = sb_rpc("
|
|
977
|
+
result = sb_rpc("mc_count_pending_rl", {
|
|
969
978
|
"p_api_key": api_key,
|
|
970
979
|
"p_project_id": project_id,
|
|
971
980
|
"p_agent_name": agent,
|
|
972
981
|
})
|
|
982
|
+
if isinstance(result, dict) and result.get("error_code") == "404":
|
|
983
|
+
result = sb_rpc("mc_count_pending", {
|
|
984
|
+
"p_api_key": api_key,
|
|
985
|
+
"p_project_id": project_id,
|
|
986
|
+
"p_agent_name": agent,
|
|
987
|
+
})
|
|
973
988
|
if isinstance(result, dict) and result.get("ok"):
|
|
974
989
|
return result.get("count", 0)
|
|
975
990
|
# Fall through to direct query if RPC doesn't exist yet
|
|
@@ -1242,13 +1257,24 @@ def task_list(api_key, project_id, agent, status_filter=None, include_done=False
|
|
|
1242
1257
|
cached = _TASK_LIST_CACHE.get(cache_key)
|
|
1243
1258
|
if cached and (now - cached[1]) < _TASK_LIST_MIN_INTERVAL:
|
|
1244
1259
|
return cached[0]
|
|
1245
|
-
|
|
1260
|
+
# SEC-5 R-SEC5-A: call rate-limited _rl wrapper. Returns same shape as
|
|
1261
|
+
# original (with extra rate_limited/remaining metadata Python ignores).
|
|
1262
|
+
# Falls back to non-rl on 404 if wrapper isn't deployed.
|
|
1263
|
+
result = sb_rpc("mc_task_list_rl", {
|
|
1246
1264
|
"p_api_key": api_key,
|
|
1247
1265
|
"p_project_id": project_id,
|
|
1248
1266
|
"p_agent": agent,
|
|
1249
1267
|
"p_status_filter": status_filter,
|
|
1250
1268
|
"p_include_done": include_done,
|
|
1251
1269
|
})
|
|
1270
|
+
if isinstance(result, dict) and result.get("error_code") == "404":
|
|
1271
|
+
result = sb_rpc("mc_task_list", {
|
|
1272
|
+
"p_api_key": api_key,
|
|
1273
|
+
"p_project_id": project_id,
|
|
1274
|
+
"p_agent": agent,
|
|
1275
|
+
"p_status_filter": status_filter,
|
|
1276
|
+
"p_include_done": include_done,
|
|
1277
|
+
})
|
|
1252
1278
|
with _TASK_LIST_CACHE_LOCK:
|
|
1253
1279
|
if len(_TASK_LIST_CACHE) >= _TASK_LIST_CACHE_MAX:
|
|
1254
1280
|
oldest_key = min(_TASK_LIST_CACHE, key=lambda k: _TASK_LIST_CACHE[k][1])
|
|
@@ -1646,6 +1646,8 @@ def _build_instructions() -> str:
|
|
|
1646
1646
|
|
|
1647
1647
|
RULES: MCP tools only. Tasks > messages. Messages <100 tokens (long → task). No empty acks, JSON only. Thread via in_reply_to. sensitive=True for secrets. Sync vs async: for turn-based/shared-state work (chess, lock-step, "who goes first"), use meshcode_call (sync RPC, 30s) — async meshcode_send crosses ~50%/turn between same-model agents and yields-pongs.
|
|
1648
1648
|
|
|
1649
|
+
CLOSE TASKS IMMEDIATELY (#2 rule, sammybenu 2026-05-22T21:06Z): every time you finish/ship/deliver work for a claimed task, call meshcode_task_complete BEFORE re-entering wait. NO "I'll close it after one more thing." NO leaving claimed tasks lingering in_progress while you do something else — that creates phantom in-progress on the dashboard and the human gets angry. If the work needs human review, set requires_approval=true at task_create OR call meshcode_task_complete (it routes to in_review if reviewer set). The mesh dashboard reflects mc_tasks.status in real-time; stale in_progress = lying to the human.
|
|
1650
|
+
|
|
1649
1651
|
SESSION START (run NOW, don't wait for input). If tool schemas are deferred:
|
|
1650
1652
|
ToolSearch(query="select:meshcode_set_status,meshcode_check,meshcode_tasks,meshcode_auto_wake,meshcode_status,meshcode_wait,meshcode_send,meshcode_call,meshcode_claim,meshcode_task_claim,meshcode_task_complete,meshcode_remember,meshcode_recall")
|
|
1651
1653
|
Then: set_status(online,ready) → check() → tasks() → auto_wake() → status() → wait(). Don't ask user "what to work on" — the mesh tells you.
|
|
@@ -6104,6 +6106,18 @@ def _auto_update() -> None:
|
|
|
6104
6106
|
# legitimate upgrade check. Per task 8d5eed7a.
|
|
6105
6107
|
os.environ.pop("MESHCODE_UPDATED", None)
|
|
6106
6108
|
return
|
|
6109
|
+
# MCP-serve guard: this function runs synchronously at the top of
|
|
6110
|
+
# run_server(), BEFORE FastMCP starts serving JSON-RPC. A blocking
|
|
6111
|
+
# `pip install --upgrade` (timeout 60s) here easily blows Claude
|
|
6112
|
+
# Code's MCP handshake window (~5s) — tools never register and the
|
|
6113
|
+
# agent boots into "MCP tools not available". The CLI-side
|
|
6114
|
+
# self_update.py (spawned by `meshcode go` before execv into the
|
|
6115
|
+
# editor) already handles user-facing upgrades; in MCP serve context
|
|
6116
|
+
# we should never block the handshake to chase a newer version.
|
|
6117
|
+
# Detected via the MESHCODE_MCP_SERVE=1 sentinel set in __main__.py.
|
|
6118
|
+
if os.environ.get("MESHCODE_MCP_SERVE") == "1":
|
|
6119
|
+
log.debug("[meshcode] Auto-update skipped in MCP serve subprocess (CLI handles upgrades)")
|
|
6120
|
+
return
|
|
6107
6121
|
|
|
6108
6122
|
# Time-gate (task c0e7de87, 2026-05-19): the PyPI HEAD GET below has a 3s
|
|
6109
6123
|
# 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
|
{meshcode-2.11.27 → meshcode-2.11.29}/meshcode-backend-wt/meshcode/meshcode_mcp/test_backend.py
RENAMED
|
File without changes
|
{meshcode-2.11.27 → meshcode-2.11.29}/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.29}/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.29}/meshcode-backend-wt/tests/test_realtime_event_freshness.py
RENAMED
|
File without changes
|
|
File without changes
|