meshcode 2.11.37__tar.gz → 2.11.38__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.37 → meshcode-2.11.38}/PKG-INFO +1 -1
- {meshcode-2.11.37 → meshcode-2.11.38}/meshcode/__init__.py +1 -1
- {meshcode-2.11.37 → meshcode-2.11.38}/meshcode/meshcode_mcp/server.py +77 -154
- {meshcode-2.11.37 → meshcode-2.11.38}/meshcode.egg-info/PKG-INFO +1 -1
- {meshcode-2.11.37 → meshcode-2.11.38}/pyproject.toml +1 -1
- {meshcode-2.11.37 → meshcode-2.11.38}/README.md +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/meshcode/__main__.py +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/meshcode/_stop_hook_template.py +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/meshcode/ascii_art.py +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/meshcode/atomic_push.py +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/meshcode/cli.py +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/meshcode/comms_v4.py +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/meshcode/compat.py +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/meshcode/daemon.py +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/meshcode/date_parse.py +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/meshcode/doctor.py +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/meshcode/error_hints.py +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/meshcode/exceptions.py +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/meshcode/invites.py +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/meshcode/launcher.py +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/meshcode/launcher_install.py +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/meshcode/meshcode_mcp/__init__.py +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/meshcode/meshcode_mcp/__main__.py +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/meshcode/meshcode_mcp/backend.py +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/meshcode/meshcode_mcp/realtime.py +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/meshcode/meshcode_mcp/sleep_signals.py +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/meshcode/meshcode_mcp/test_backend.py +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/meshcode/meshcode_mcp/test_boot_timing.py +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/meshcode/meshcode_mcp/test_install_guard.py +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/meshcode/meshcode_mcp/test_prefs_claude_version.py +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/meshcode/meshcode_mcp/test_realtime.py +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/meshcode/meshcode_mcp/test_server_wrapper.py +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/meshcode/preferences.py +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/meshcode/protocol_handler.py +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/meshcode/protocol_v2.py +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/meshcode/quickstart.py +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/meshcode/rpc_allowlist.py +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/meshcode/run_agent.py +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/meshcode/scripts/check_secrets.py +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/meshcode/scripts/race_rate_harness.py +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/meshcode/secrets.py +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/meshcode/self_update.py +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/meshcode/setup_clients.py +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/meshcode/supervisor.py +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/meshcode/upload.py +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-backend-wt/comms_v4.py +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-backend-wt/meshcode/__init__.py +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-backend-wt/meshcode/ascii_art.py +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-backend-wt/meshcode/cli.py +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-backend-wt/meshcode/comms_v4.py +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-backend-wt/meshcode/compat.py +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-backend-wt/meshcode/error_hints.py +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-backend-wt/meshcode/exceptions.py +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-backend-wt/meshcode/invites.py +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-backend-wt/meshcode/launcher.py +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-backend-wt/meshcode/launcher_install.py +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-backend-wt/meshcode/meshcode_mcp/__init__.py +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-backend-wt/meshcode/meshcode_mcp/__main__.py +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-backend-wt/meshcode/meshcode_mcp/backend.py +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-backend-wt/meshcode/meshcode_mcp/realtime.py +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-backend-wt/meshcode/meshcode_mcp/server.py +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-backend-wt/meshcode/meshcode_mcp/test_backend.py +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-backend-wt/meshcode/meshcode_mcp/test_realtime.py +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-backend-wt/meshcode/meshcode_mcp/test_server_wrapper.py +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-backend-wt/meshcode/preferences.py +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-backend-wt/meshcode/protocol_v2.py +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-backend-wt/meshcode/quickstart.py +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-backend-wt/meshcode/run_agent.py +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-backend-wt/meshcode/secrets.py +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-backend-wt/meshcode/self_update.py +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-backend-wt/meshcode/setup_clients.py +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-backend-wt/meshcode/supervisor.py +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-backend-wt/meshcode/upload.py +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-backend-wt/scripts/sentinel.py +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-backend-wt/tests/test_core.py +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-backend-wt/tests/test_cross_agent_messaging.py +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-backend-wt/tests/test_esc_deaf_state.py +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-backend-wt/tests/test_exceptions.py +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-backend-wt/tests/test_mark_read_batch.py +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-backend-wt/tests/test_migration_integrity.py +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-backend-wt/tests/test_realtime_event_freshness.py +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-backend-wt/tests/test_rls_cross_tenant.py +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-backend-wt/tests/test_rpc_migrations.py +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-backend-wt/tests/test_security_regressions.py +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-backend-wt/tests/test_sentinel.py +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-backend-wt/tests/test_status_enum_coverage.py +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-noun-wt/build/lib/meshcode/__init__.py +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-noun-wt/build/lib/meshcode/ascii_art.py +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-noun-wt/build/lib/meshcode/cli.py +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-noun-wt/build/lib/meshcode/comms_v4.py +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-noun-wt/build/lib/meshcode/compat.py +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-noun-wt/build/lib/meshcode/error_hints.py +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-noun-wt/build/lib/meshcode/exceptions.py +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-noun-wt/build/lib/meshcode/invites.py +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-noun-wt/build/lib/meshcode/launcher.py +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-noun-wt/build/lib/meshcode/launcher_install.py +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-noun-wt/build/lib/meshcode/meshcode_mcp/__init__.py +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-noun-wt/build/lib/meshcode/meshcode_mcp/__main__.py +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-noun-wt/build/lib/meshcode/meshcode_mcp/backend.py +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-noun-wt/build/lib/meshcode/meshcode_mcp/realtime.py +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-noun-wt/build/lib/meshcode/meshcode_mcp/server.py +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-noun-wt/build/lib/meshcode/meshcode_mcp/test_backend.py +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-noun-wt/build/lib/meshcode/meshcode_mcp/test_realtime.py +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-noun-wt/build/lib/meshcode/meshcode_mcp/test_server_wrapper.py +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-noun-wt/build/lib/meshcode/preferences.py +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-noun-wt/build/lib/meshcode/protocol_v2.py +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-noun-wt/build/lib/meshcode/quickstart.py +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-noun-wt/build/lib/meshcode/run_agent.py +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-noun-wt/build/lib/meshcode/secrets.py +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-noun-wt/build/lib/meshcode/self_update.py +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-noun-wt/build/lib/meshcode/setup_clients.py +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-noun-wt/build/lib/meshcode/supervisor.py +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-noun-wt/build/lib/meshcode/upload.py +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-noun-wt/comms_v4.py +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-noun-wt/meshcode/__init__.py +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-noun-wt/meshcode/ascii_art.py +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-noun-wt/meshcode/cli.py +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-noun-wt/meshcode/comms_v4.py +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-noun-wt/meshcode/compat.py +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-noun-wt/meshcode/error_hints.py +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-noun-wt/meshcode/exceptions.py +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-noun-wt/meshcode/invites.py +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-noun-wt/meshcode/launcher.py +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-noun-wt/meshcode/launcher_install.py +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-noun-wt/meshcode/meshcode_mcp/__init__.py +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-noun-wt/meshcode/meshcode_mcp/__main__.py +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-noun-wt/meshcode/meshcode_mcp/backend.py +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-noun-wt/meshcode/meshcode_mcp/realtime.py +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-noun-wt/meshcode/meshcode_mcp/server.py +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-noun-wt/meshcode/meshcode_mcp/test_backend.py +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-noun-wt/meshcode/meshcode_mcp/test_realtime.py +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-noun-wt/meshcode/meshcode_mcp/test_server_wrapper.py +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-noun-wt/meshcode/preferences.py +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-noun-wt/meshcode/protocol_v2.py +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-noun-wt/meshcode/quickstart.py +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-noun-wt/meshcode/run_agent.py +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-noun-wt/meshcode/secrets.py +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-noun-wt/meshcode/self_update.py +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-noun-wt/meshcode/setup_clients.py +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-noun-wt/meshcode/supervisor.py +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-noun-wt/meshcode/upload.py +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-noun-wt/scripts/sentinel.py +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-noun-wt/tests/test_core.py +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-noun-wt/tests/test_cross_agent_messaging.py +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-noun-wt/tests/test_esc_deaf_state.py +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-noun-wt/tests/test_exceptions.py +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-noun-wt/tests/test_mark_read_batch.py +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-noun-wt/tests/test_migration_integrity.py +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-noun-wt/tests/test_realtime_event_freshness.py +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-noun-wt/tests/test_rls_cross_tenant.py +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-noun-wt/tests/test_rpc_migrations.py +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-noun-wt/tests/test_security_regressions.py +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-noun-wt/tests/test_sentinel.py +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-noun-wt/tests/test_status_enum_coverage.py +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-tasks-wt/comms_v4.py +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-tasks-wt/meshcode/__init__.py +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-tasks-wt/meshcode/ascii_art.py +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-tasks-wt/meshcode/cli.py +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-tasks-wt/meshcode/comms_v4.py +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-tasks-wt/meshcode/compat.py +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-tasks-wt/meshcode/error_hints.py +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-tasks-wt/meshcode/exceptions.py +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-tasks-wt/meshcode/invites.py +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-tasks-wt/meshcode/launcher.py +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-tasks-wt/meshcode/launcher_install.py +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-tasks-wt/meshcode/meshcode_mcp/__init__.py +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-tasks-wt/meshcode/meshcode_mcp/__main__.py +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-tasks-wt/meshcode/meshcode_mcp/backend.py +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-tasks-wt/meshcode/meshcode_mcp/realtime.py +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-tasks-wt/meshcode/meshcode_mcp/server.py +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-tasks-wt/meshcode/meshcode_mcp/test_backend.py +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-tasks-wt/meshcode/meshcode_mcp/test_realtime.py +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-tasks-wt/meshcode/meshcode_mcp/test_server_wrapper.py +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-tasks-wt/meshcode/preferences.py +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-tasks-wt/meshcode/protocol_v2.py +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-tasks-wt/meshcode/quickstart.py +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-tasks-wt/meshcode/run_agent.py +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-tasks-wt/meshcode/secrets.py +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-tasks-wt/meshcode/self_update.py +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-tasks-wt/meshcode/setup_clients.py +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-tasks-wt/meshcode/supervisor.py +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-tasks-wt/meshcode/upload.py +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-tasks-wt/scripts/sentinel.py +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-tasks-wt/tests/test_core.py +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-tasks-wt/tests/test_cross_agent_messaging.py +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-tasks-wt/tests/test_esc_deaf_state.py +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-tasks-wt/tests/test_exceptions.py +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-tasks-wt/tests/test_mark_read_batch.py +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-tasks-wt/tests/test_migration_integrity.py +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-tasks-wt/tests/test_realtime_event_freshness.py +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-tasks-wt/tests/test_rls_cross_tenant.py +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-tasks-wt/tests/test_rpc_migrations.py +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-tasks-wt/tests/test_security_regressions.py +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-tasks-wt/tests/test_sentinel.py +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/meshcode-tasks-wt/tests/test_status_enum_coverage.py +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/meshcode.egg-info/SOURCES.txt +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/meshcode.egg-info/dependency_links.txt +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/meshcode.egg-info/entry_points.txt +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/meshcode.egg-info/requires.txt +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/meshcode.egg-info/top_level.txt +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/setup.cfg +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/tests/test_auto_update_hardening.py +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/tests/test_boot_bug_regression.py +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/tests/test_color_truecolor.py +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/tests/test_core.py +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/tests/test_cross_agent_messaging.py +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/tests/test_date_parse.py +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/tests/test_doctor.py +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/tests/test_epistemic_v1_python_sdk.py +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/tests/test_epistemic_v1_stop_conditions.py +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/tests/test_esc_deaf_state.py +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/tests/test_exceptions.py +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/tests/test_init_device_code.py +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/tests/test_install_guard.py +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/tests/test_lease_sigterm_release.py +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/tests/test_mark_read_batch.py +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/tests/test_migration_integrity.py +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/tests/test_realtime_event_freshness.py +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/tests/test_rls_cross_tenant.py +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/tests/test_rpc_grants.py +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/tests/test_rpc_migrations.py +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/tests/test_run_agent_dry_run.py +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/tests/test_run_agent_no_server_import.py +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/tests/test_security_regressions.py +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/tests/test_self_update_user_site.py +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/tests/test_sentinel.py +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/tests/test_setup_path.py +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/tests/test_sleep_signals.py +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/tests/test_status_enum_coverage.py +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/tests/test_stay_on_loop_hook.py +0 -0
- {meshcode-2.11.37 → meshcode-2.11.38}/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.
|
|
237
230
|
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 after SIGTERM (rare — handler ignores it)
|
|
242
242
|
if old_instance_id:
|
|
243
243
|
_release_lease_for_instance(old_instance_id, reason="post-sigkill")
|
|
244
244
|
else:
|
|
@@ -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.
|
|
@@ -2835,36 +2837,10 @@ def meshcode_send(to: Union[str, List[str]], message: Any, in_reply_to: Optional
|
|
|
2835
2837
|
result["encrypted"] = True
|
|
2836
2838
|
return result
|
|
2837
2839
|
|
|
2838
|
-
|
|
2839
|
-
|
|
2840
|
-
|
|
2841
|
-
|
|
2842
|
-
|
|
2843
|
-
# C2 (BACKEND-AUDIT-TASK-FRICTION F4, 2026-05-22): detect payloads that
|
|
2844
|
-
# look like the agent is trying to "claim" a task via a status message
|
|
2845
|
-
# instead of calling meshcode_task_claim. The status_msg path does NOT
|
|
2846
|
-
# update mc_tasks.claimed_by → task sits open while the agent believes
|
|
2847
|
-
# it's working it. Soft hint, never refuse.
|
|
2848
|
-
try:
|
|
2849
|
-
if isinstance(_result, dict) and _result.get("sent"):
|
|
2850
|
-
_ptype = str(payload.get("type", "")).lower()
|
|
2851
|
-
_ptext = str(payload.get("text", "")).lower()
|
|
2852
|
-
_has_task_ref = any(k in payload for k in ("task", "task_id"))
|
|
2853
|
-
_looks_like_claim = (
|
|
2854
|
-
_ptype in {"claim", "claim_status", "status_claim"}
|
|
2855
|
-
or ("claim" in _ptext and _has_task_ref)
|
|
2856
|
-
or (_ptype.startswith("status") and "claim" in _ptext)
|
|
2857
|
-
)
|
|
2858
|
-
if _looks_like_claim:
|
|
2859
|
-
_result["hint"] = (
|
|
2860
|
-
"claim_via_status_msg_does_not_update_task_table — "
|
|
2861
|
-
"call meshcode_task_claim(<task_id>) for the actual "
|
|
2862
|
-
"claim. status_msg is fine as a peer notification "
|
|
2863
|
-
"but is not the system-of-record."
|
|
2864
|
-
)
|
|
2865
|
-
except Exception:
|
|
2866
|
-
pass
|
|
2867
|
-
return _result
|
|
2840
|
+
return be.send_message(_PROJECT_ID, AGENT_NAME, to, payload,
|
|
2841
|
+
msg_type=type or "msg",
|
|
2842
|
+
parent_msg_id=in_reply_to, sensitive=sensitive,
|
|
2843
|
+
api_key=_get_api_key(), encrypted=encrypted)
|
|
2868
2844
|
|
|
2869
2845
|
|
|
2870
2846
|
@mcp.tool()
|
|
@@ -3262,14 +3238,6 @@ _AUTO_SLEEP_THRESHOLD = int(os.environ.get("MESHCODE_AUTO_SLEEP_SECONDS", "600")
|
|
|
3262
3238
|
_STAY_AWAKE = False # Set by meshcode_set_status("online") — prevents auto-sleep
|
|
3263
3239
|
_LAST_SEEN_TS: Optional[str] = None # auto-persisted for message dedup
|
|
3264
3240
|
|
|
3265
|
-
# M2 (SUPABASE-PROD-QUOTA-CRITICAL 2026-05-22): when an agent has been idle
|
|
3266
|
-
# longer than _M2_IDLE_THRESHOLD seconds, skip the per-tick mc_tasks poll on
|
|
3267
|
-
# (n-1)/n of timeouts — effective task-poll rate drops 1/N. Cuts mc_tasks
|
|
3268
|
-
# RPC volume which accounted for ~26.95M cumulative calls in the audit.
|
|
3269
|
-
_M2_IDLE_THRESHOLD = int(os.environ.get("MESHCODE_WAIT_IDLE_TASK_POLL_SKIP", "300")) # secs
|
|
3270
|
-
_M2_POLL_EVERY_N = int(os.environ.get("MESHCODE_WAIT_IDLE_POLL_EVERY_N", "3"))
|
|
3271
|
-
_M2_TICK_COUNTER = 0
|
|
3272
|
-
|
|
3273
3241
|
# Hydrate _LAST_SEEN_TS from mesh memory on boot so restarts skip old messages
|
|
3274
3242
|
try:
|
|
3275
3243
|
_ls_result = be.sb_rpc("mc_memory_get", {
|
|
@@ -3333,83 +3301,6 @@ def _get_pending_tasks_summary() -> Optional[List[Dict[str, str]]]:
|
|
|
3333
3301
|
return None
|
|
3334
3302
|
|
|
3335
3303
|
|
|
3336
|
-
def _check_task_dedupe(title: str, assignee: str) -> Optional[Dict[str, Any]]:
|
|
3337
|
-
"""Find an open/in_progress task with similar title + same assignee.
|
|
3338
|
-
|
|
3339
|
-
Samuel directive 2026-05-21T23:41Z (`commander_dedupe_before_task_from_status_msg`):
|
|
3340
|
-
commanders kept creating duplicate tasks when reacting to status msgs from
|
|
3341
|
-
agents that had already claimed/shipped the same work. The 5ac1d9fe /
|
|
3342
|
-
dd41054d MOBILE-FIRST-3/4 dupes sat OPEN since 2026-05-20 because nobody
|
|
3343
|
-
deduped before creating new ones. Server-side soft guard surfaces a
|
|
3344
|
-
`dedupe_warning` in task_create responses when a likely duplicate
|
|
3345
|
-
exists — non-blocking, so legitimate near-titles still create, but the
|
|
3346
|
-
commander sees the dupe candidate and can cancel + reuse instead.
|
|
3347
|
-
"""
|
|
3348
|
-
try:
|
|
3349
|
-
api_key = _get_api_key()
|
|
3350
|
-
if not api_key:
|
|
3351
|
-
return None
|
|
3352
|
-
result = be.task_list(api_key, _PROJECT_ID, AGENT_NAME, status_filter=None)
|
|
3353
|
-
if not isinstance(result, dict) or not result.get("ok"):
|
|
3354
|
-
return None
|
|
3355
|
-
tasks = result.get("tasks", [])
|
|
3356
|
-
target = (title or "").strip().lower()
|
|
3357
|
-
if not target:
|
|
3358
|
-
return None
|
|
3359
|
-
target_prefix = target[:40]
|
|
3360
|
-
for t in tasks:
|
|
3361
|
-
if t.get("status") not in ("open", "in_progress"):
|
|
3362
|
-
continue
|
|
3363
|
-
if t.get("assignee") != assignee:
|
|
3364
|
-
continue
|
|
3365
|
-
t_title = (t.get("title") or "").strip().lower()
|
|
3366
|
-
if not t_title:
|
|
3367
|
-
continue
|
|
3368
|
-
t_prefix = t_title[:40]
|
|
3369
|
-
match = None
|
|
3370
|
-
if t_prefix == target_prefix:
|
|
3371
|
-
match = "prefix-40"
|
|
3372
|
-
elif target in t_title or t_title in target:
|
|
3373
|
-
match = "substring"
|
|
3374
|
-
if match:
|
|
3375
|
-
return {
|
|
3376
|
-
"dupe_task_id": t.get("id"),
|
|
3377
|
-
"dupe_title": t.get("title"),
|
|
3378
|
-
"dupe_status": t.get("status"),
|
|
3379
|
-
"match_type": match,
|
|
3380
|
-
}
|
|
3381
|
-
except Exception:
|
|
3382
|
-
pass
|
|
3383
|
-
return None
|
|
3384
|
-
|
|
3385
|
-
|
|
3386
|
-
def _attach_pending_tasks_to_resp(resp: Dict[str, Any]) -> Dict[str, Any]:
|
|
3387
|
-
"""Surface this agent's open/in_progress assigned tasks on EVERY wait response.
|
|
3388
|
-
|
|
3389
|
-
Samuel directive 2026-05-21T23:54Z: agents must always advance open tasks.
|
|
3390
|
-
Previously `pending_tasks` only appeared in the timeout branch; when
|
|
3391
|
-
messages kept arriving the agent ping-ponged replies and never saw the
|
|
3392
|
-
hint, so tasks piled up. Now: every wait response (refused-by-messages,
|
|
3393
|
-
got_message, timeout) carries pending_tasks + pending_directive when
|
|
3394
|
-
this agent has open work. The agent's instruction prompt treats the
|
|
3395
|
-
directive as priority-1 over optional message replies.
|
|
3396
|
-
"""
|
|
3397
|
-
try:
|
|
3398
|
-
pending = _get_pending_tasks_summary()
|
|
3399
|
-
if pending and isinstance(resp, dict):
|
|
3400
|
-
resp["pending_tasks"] = pending
|
|
3401
|
-
resp["pending_tasks_count"] = len(pending)
|
|
3402
|
-
titles = ", ".join(t.get("title", "")[:40] for t in pending[:3])
|
|
3403
|
-
resp["pending_directive"] = (
|
|
3404
|
-
f"You have {len(pending)} open task(s) assigned. Advance at least one "
|
|
3405
|
-
f"(claim / progress / complete) BEFORE processing optional messages or "
|
|
3406
|
-
f"re-entering wait. Tasks: {titles}"
|
|
3407
|
-
)
|
|
3408
|
-
except Exception:
|
|
3409
|
-
pass
|
|
3410
|
-
return resp
|
|
3411
|
-
|
|
3412
|
-
|
|
3413
3304
|
def _try_auto_claim_task() -> Optional[Dict[str, str]]:
|
|
3414
3305
|
"""Auto-claim the oldest open task matching this agent's role.
|
|
3415
3306
|
|
|
@@ -3451,6 +3342,53 @@ def _try_auto_claim_task() -> Optional[Dict[str, str]]:
|
|
|
3451
3342
|
return None
|
|
3452
3343
|
|
|
3453
3344
|
|
|
3345
|
+
# AGENT-INTEL-1-PY (task 38b1a0e2): mesh_online_snapshot in wait return.
|
|
3346
|
+
# Calls mc_roster_live (mig 348) and projects a compact list of live+idle
|
|
3347
|
+
# agents for the receiving agent's situational awareness. Cached 10s so
|
|
3348
|
+
# the common case (rapid wait cycles) doesn't hammer the roster RPC.
|
|
3349
|
+
_LAST_ROSTER_SNAPSHOT: Optional[List[Dict[str, Any]]] = None
|
|
3350
|
+
_LAST_ROSTER_SNAPSHOT_TS: float = 0.0
|
|
3351
|
+
|
|
3352
|
+
|
|
3353
|
+
def _get_mesh_online_snapshot(max_age_s: float = 10.0) -> Optional[List[Dict[str, Any]]]:
|
|
3354
|
+
global _LAST_ROSTER_SNAPSHOT, _LAST_ROSTER_SNAPSHOT_TS
|
|
3355
|
+
now_ts = _time.monotonic()
|
|
3356
|
+
if _LAST_ROSTER_SNAPSHOT is not None and (now_ts - _LAST_ROSTER_SNAPSHOT_TS) < max_age_s:
|
|
3357
|
+
return _LAST_ROSTER_SNAPSHOT
|
|
3358
|
+
try:
|
|
3359
|
+
api_key = _get_api_key()
|
|
3360
|
+
if not api_key:
|
|
3361
|
+
return None
|
|
3362
|
+
roster = be.sb_rpc("mc_roster_live", {
|
|
3363
|
+
"p_api_key": api_key,
|
|
3364
|
+
"p_project_id": _PROJECT_ID,
|
|
3365
|
+
})
|
|
3366
|
+
if not isinstance(roster, dict) or not roster.get("ok"):
|
|
3367
|
+
return None
|
|
3368
|
+
by_lane = (roster.get("roster") or {}).get("by_lane") or {}
|
|
3369
|
+
out: List[Dict[str, Any]] = []
|
|
3370
|
+
for lane, bucket in by_lane.items():
|
|
3371
|
+
if not isinstance(bucket, dict):
|
|
3372
|
+
continue
|
|
3373
|
+
for liveness in ("live", "idle"):
|
|
3374
|
+
for a in bucket.get(liveness) or []:
|
|
3375
|
+
if not isinstance(a, dict):
|
|
3376
|
+
continue
|
|
3377
|
+
out.append({
|
|
3378
|
+
"name": a.get("name"),
|
|
3379
|
+
"status": a.get("status"),
|
|
3380
|
+
"lane": lane,
|
|
3381
|
+
"last_heartbeat_age_s": a.get("hb_age_s"),
|
|
3382
|
+
})
|
|
3383
|
+
out.sort(key=lambda x: (x.get("lane") or "", x.get("name") or ""))
|
|
3384
|
+
_LAST_ROSTER_SNAPSHOT = out
|
|
3385
|
+
_LAST_ROSTER_SNAPSHOT_TS = now_ts
|
|
3386
|
+
return out
|
|
3387
|
+
except Exception as e:
|
|
3388
|
+
log.debug(f"[meshcode] mesh_online_snapshot fetch failed: {e}")
|
|
3389
|
+
return None
|
|
3390
|
+
|
|
3391
|
+
|
|
3454
3392
|
@mcp.tool()
|
|
3455
3393
|
@with_working_status
|
|
3456
3394
|
async def meshcode_wait(timeout_seconds: int = 20, include_acks: bool = False) -> Dict[str, Any]:
|
|
@@ -3516,7 +3454,12 @@ async def meshcode_wait(timeout_seconds: int = 20, include_acks: bool = False) -
|
|
|
3516
3454
|
if split["done_signals"]:
|
|
3517
3455
|
resp["must_exit"] = True
|
|
3518
3456
|
resp["exit_reason"] = "sleep authorization received — set status=sleeping and end session"
|
|
3519
|
-
|
|
3457
|
+
# AGENT-INTEL-1-PY: snapshot on refused-path too.
|
|
3458
|
+
if os.environ.get("MESHCODE_WAIT_NO_SNAPSHOT", "").lower() not in ("1", "true", "yes"):
|
|
3459
|
+
_snap = _get_mesh_online_snapshot()
|
|
3460
|
+
if _snap is not None:
|
|
3461
|
+
resp["mesh_online_snapshot"] = _snap
|
|
3462
|
+
return resp
|
|
3520
3463
|
# Ack-only batch — fall through to wait loop
|
|
3521
3464
|
except Exception:
|
|
3522
3465
|
pass
|
|
@@ -3549,16 +3492,8 @@ async def meshcode_wait(timeout_seconds: int = 20, include_acks: bool = False) -
|
|
|
3549
3492
|
if result.get("timed_out"):
|
|
3550
3493
|
_CONSECUTIVE_IDLE_SECONDS += capped_timeout
|
|
3551
3494
|
|
|
3552
|
-
# M2 (2026-05-22): when idle >5min, poll mc_tasks every Nth
|
|
3553
|
-
# tick instead of every tick. Active agents (recent msg)
|
|
3554
|
-
# keep checking every tick.
|
|
3555
|
-
global _M2_TICK_COUNTER
|
|
3556
|
-
_check_tasks = True
|
|
3557
|
-
if _CONSECUTIVE_IDLE_SECONDS >= _M2_IDLE_THRESHOLD and _M2_POLL_EVERY_N > 1:
|
|
3558
|
-
_M2_TICK_COUNTER = (_M2_TICK_COUNTER + 1) % _M2_POLL_EVERY_N
|
|
3559
|
-
_check_tasks = (_M2_TICK_COUNTER == 0)
|
|
3560
3495
|
# Check if new tasks appeared while we waited
|
|
3561
|
-
pending_tasks = _get_pending_tasks_summary()
|
|
3496
|
+
pending_tasks = _get_pending_tasks_summary()
|
|
3562
3497
|
if pending_tasks:
|
|
3563
3498
|
result["pending_tasks"] = pending_tasks
|
|
3564
3499
|
break # Return so agent can work tasks
|
|
@@ -3635,7 +3570,13 @@ async def meshcode_wait(timeout_seconds: int = 20, include_acks: bool = False) -
|
|
|
3635
3570
|
result.setdefault("must_exit", True)
|
|
3636
3571
|
result.setdefault("exit_reason",
|
|
3637
3572
|
"sleep authorization received — set status=sleeping and end session")
|
|
3638
|
-
|
|
3573
|
+
# AGENT-INTEL-1-PY: attach mesh_online_snapshot for situational
|
|
3574
|
+
# awareness (cached 10s). Env opt-out: MESHCODE_WAIT_NO_SNAPSHOT=1.
|
|
3575
|
+
if isinstance(result, dict) and os.environ.get("MESHCODE_WAIT_NO_SNAPSHOT", "").lower() not in ("1", "true", "yes"):
|
|
3576
|
+
_snapshot = _get_mesh_online_snapshot()
|
|
3577
|
+
if _snapshot is not None:
|
|
3578
|
+
result["mesh_online_snapshot"] = _snapshot
|
|
3579
|
+
return result
|
|
3639
3580
|
finally:
|
|
3640
3581
|
_IN_WAIT = False
|
|
3641
3582
|
|
|
@@ -4073,18 +4014,13 @@ def meshcode_set_status(status: str, task: str = "") -> Dict[str, Any]:
|
|
|
4073
4014
|
task: Optional human-readable task description.
|
|
4074
4015
|
"""
|
|
4075
4016
|
global _STAY_AWAKE, _CONSECUTIVE_IDLE_SECONDS
|
|
4076
|
-
# PRODUCT RULE: Cannot sleep/idle/standby with
|
|
4077
|
-
# or just assigned). Samuel directive 2026-05-22T01:01Z confirmed the
|
|
4078
|
-
# strict rule is intentional — agents MUST work their assigned queue
|
|
4079
|
-
# before sleeping. Reverting the 2026-05-22T00:55Z "claimed-only" relax
|
|
4080
|
-
# (2.11.34) per Samuel's correction. The wake-cron is BACKUP for
|
|
4081
|
-
# disconnected sessions, NOT a license to sleep on assignments.
|
|
4017
|
+
# PRODUCT RULE: Cannot sleep/idle/standby with open tasks. Work first.
|
|
4082
4018
|
if status in ("sleeping", "idle", "standby"):
|
|
4083
4019
|
pending_tasks = _get_pending_tasks_summary()
|
|
4084
4020
|
if pending_tasks:
|
|
4085
4021
|
return {
|
|
4086
4022
|
"refused": True,
|
|
4087
|
-
"reason": f"Cannot set status '{status}' — you have {len(pending_tasks)} open
|
|
4023
|
+
"reason": f"Cannot set status '{status}' — you have {len(pending_tasks)} open tasks. Work them first.",
|
|
4088
4024
|
"pending_tasks": pending_tasks,
|
|
4089
4025
|
}
|
|
4090
4026
|
# Setting online/working = stay awake (prevent auto-sleep)
|
|
@@ -4173,24 +4109,11 @@ def meshcode_task_create(title: str, description: str = "", assignee: Optional[s
|
|
|
4173
4109
|
except Exception as _de:
|
|
4174
4110
|
return {"error": f"due_parse_failed: {_de}"}
|
|
4175
4111
|
api_key = _get_api_key()
|
|
4176
|
-
# Soft dedupe guard (Samuel directive 2026-05-21): surface likely-duplicate
|
|
4177
|
-
# open/in_progress task with same assignee + similar title. Non-blocking —
|
|
4178
|
-
# caller still gets the new task_id, but sees `dedupe_warning` and can
|
|
4179
|
-
# cancel + reuse the existing task instead of accumulating dupes.
|
|
4180
|
-
dedupe_hit = _check_task_dedupe(title.strip(), assignee) if assignee != "auto" else None
|
|
4181
4112
|
result = be.task_create(api_key, _PROJECT_ID, AGENT_NAME, title.strip(),
|
|
4182
4113
|
description=description, assignee=assignee,
|
|
4183
4114
|
priority=priority, parent_task_id=parent_task_id,
|
|
4184
4115
|
due_at=parsed_due_at, due_label=parsed_due_label,
|
|
4185
4116
|
depends_on=depends_on or None)
|
|
4186
|
-
if isinstance(result, dict) and result.get("ok") and dedupe_hit:
|
|
4187
|
-
result["dedupe_warning"] = (
|
|
4188
|
-
f"Possible duplicate of task {dedupe_hit['dupe_task_id'][:8]} "
|
|
4189
|
-
f"('{dedupe_hit['dupe_title'][:60]}', status={dedupe_hit['dupe_status']}, "
|
|
4190
|
-
f"match={dedupe_hit['match_type']}). Consider canceling this new task "
|
|
4191
|
-
f"and reusing the existing one."
|
|
4192
|
-
)
|
|
4193
|
-
result["dedupe_candidate"] = dedupe_hit
|
|
4194
4117
|
# Auto-notify the resolved assignee so they wake from meshcode_wait.
|
|
4195
4118
|
# Read result["assignee"] (server may have resolved 'auto' to a real name).
|
|
4196
4119
|
if isinstance(result, dict) and result.get("ok"):
|
|
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
|
|
File without changes
|
{meshcode-2.11.37 → meshcode-2.11.38}/meshcode-backend-wt/meshcode/meshcode_mcp/test_backend.py
RENAMED
|
File without changes
|
{meshcode-2.11.37 → meshcode-2.11.38}/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.37 → meshcode-2.11.38}/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.37 → meshcode-2.11.38}/meshcode-backend-wt/tests/test_realtime_event_freshness.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{meshcode-2.11.37 → meshcode-2.11.38}/meshcode-backend-wt/tests/test_security_regressions.py
RENAMED
|
File without changes
|
|
File without changes
|
{meshcode-2.11.37 → meshcode-2.11.38}/meshcode-backend-wt/tests/test_status_enum_coverage.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
|
{meshcode-2.11.37 → meshcode-2.11.38}/meshcode-noun-wt/build/lib/meshcode/launcher_install.py
RENAMED
|
File without changes
|
{meshcode-2.11.37 → meshcode-2.11.38}/meshcode-noun-wt/build/lib/meshcode/meshcode_mcp/__init__.py
RENAMED
|
File without changes
|
{meshcode-2.11.37 → meshcode-2.11.38}/meshcode-noun-wt/build/lib/meshcode/meshcode_mcp/__main__.py
RENAMED
|
File without changes
|
{meshcode-2.11.37 → meshcode-2.11.38}/meshcode-noun-wt/build/lib/meshcode/meshcode_mcp/backend.py
RENAMED
|
File without changes
|
{meshcode-2.11.37 → meshcode-2.11.38}/meshcode-noun-wt/build/lib/meshcode/meshcode_mcp/realtime.py
RENAMED
|
File without changes
|
{meshcode-2.11.37 → meshcode-2.11.38}/meshcode-noun-wt/build/lib/meshcode/meshcode_mcp/server.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
|