meshcode 2.11.158__tar.gz → 2.11.159__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.
Files changed (122) hide show
  1. {meshcode-2.11.158 → meshcode-2.11.159}/PKG-INFO +1 -1
  2. {meshcode-2.11.158 → meshcode-2.11.159}/meshcode/__init__.py +1 -1
  3. {meshcode-2.11.158 → meshcode-2.11.159}/meshcode/__main__.py +1 -1
  4. {meshcode-2.11.158 → meshcode-2.11.159}/meshcode/_session_handoff_template.py +16 -70
  5. {meshcode-2.11.158 → meshcode-2.11.159}/meshcode/comms_v4.py +17 -21
  6. {meshcode-2.11.158 → meshcode-2.11.159}/meshcode/hostd.py +159 -394
  7. {meshcode-2.11.158 → meshcode-2.11.159}/meshcode/meshcode_mcp/backend.py +2 -2
  8. {meshcode-2.11.158 → meshcode-2.11.159}/meshcode/meshcode_mcp/realtime.py +0 -11
  9. {meshcode-2.11.158 → meshcode-2.11.159}/meshcode/meshcode_mcp/server.py +27 -316
  10. {meshcode-2.11.158 → meshcode-2.11.159}/meshcode/meshcode_mcp/sleep_signals.py +1 -45
  11. {meshcode-2.11.158 → meshcode-2.11.159}/meshcode/protocol_handler.py +7 -41
  12. {meshcode-2.11.158 → meshcode-2.11.159}/meshcode/run_agent.py +11 -29
  13. {meshcode-2.11.158 → meshcode-2.11.159}/meshcode/self_update.py +3 -3
  14. {meshcode-2.11.158 → meshcode-2.11.159}/meshcode/setup_clients.py +4 -69
  15. {meshcode-2.11.158 → meshcode-2.11.159}/meshcode/up.py +4 -31
  16. {meshcode-2.11.158 → meshcode-2.11.159}/meshcode.egg-info/PKG-INFO +1 -1
  17. {meshcode-2.11.158 → meshcode-2.11.159}/meshcode.egg-info/SOURCES.txt +0 -5
  18. {meshcode-2.11.158 → meshcode-2.11.159}/pyproject.toml +1 -1
  19. {meshcode-2.11.158 → meshcode-2.11.159}/tests/test_fleet_reaper.py +1 -1
  20. {meshcode-2.11.158 → meshcode-2.11.159}/tests/test_hostd_zombie_sessions.py +2 -2
  21. meshcode-2.11.158/meshcode/helper_visuals.py +0 -142
  22. meshcode-2.11.158/meshcode/meshcode_mcp/swarm.py +0 -472
  23. meshcode-2.11.158/meshcode/meshcode_mcp/test_swarm.py +0 -469
  24. meshcode-2.11.158/tests/test_helper_visuals.py +0 -214
  25. meshcode-2.11.158/tests/test_swarm_events.py +0 -115
  26. {meshcode-2.11.158 → meshcode-2.11.159}/README.md +0 -0
  27. {meshcode-2.11.158 → meshcode-2.11.159}/meshcode/_launch_smoke.py +0 -0
  28. {meshcode-2.11.158 → meshcode-2.11.159}/meshcode/_stop_hook_template.py +0 -0
  29. {meshcode-2.11.158 → meshcode-2.11.159}/meshcode/_update_guard.py +0 -0
  30. {meshcode-2.11.158 → meshcode-2.11.159}/meshcode/ascii_art.py +0 -0
  31. {meshcode-2.11.158 → meshcode-2.11.159}/meshcode/atomic_push.py +0 -0
  32. {meshcode-2.11.158 → meshcode-2.11.159}/meshcode/claude_update.py +0 -0
  33. {meshcode-2.11.158 → meshcode-2.11.159}/meshcode/cli.py +0 -0
  34. {meshcode-2.11.158 → meshcode-2.11.159}/meshcode/compat.py +0 -0
  35. {meshcode-2.11.158 → meshcode-2.11.159}/meshcode/daemon.py +0 -0
  36. {meshcode-2.11.158 → meshcode-2.11.159}/meshcode/date_parse.py +0 -0
  37. {meshcode-2.11.158 → meshcode-2.11.159}/meshcode/doctor.py +0 -0
  38. {meshcode-2.11.158 → meshcode-2.11.159}/meshcode/error_hints.py +0 -0
  39. {meshcode-2.11.158 → meshcode-2.11.159}/meshcode/exceptions.py +0 -0
  40. {meshcode-2.11.158 → meshcode-2.11.159}/meshcode/hooks/__init__.py +0 -0
  41. {meshcode-2.11.158 → meshcode-2.11.159}/meshcode/hooks/push_guard.py +0 -0
  42. {meshcode-2.11.158 → meshcode-2.11.159}/meshcode/hooks/repo_path_lock.py +0 -0
  43. {meshcode-2.11.158 → meshcode-2.11.159}/meshcode/invites.py +0 -0
  44. {meshcode-2.11.158 → meshcode-2.11.159}/meshcode/launcher.py +0 -0
  45. {meshcode-2.11.158 → meshcode-2.11.159}/meshcode/launcher_install.py +0 -0
  46. {meshcode-2.11.158 → meshcode-2.11.159}/meshcode/meshcode_mcp/__init__.py +0 -0
  47. {meshcode-2.11.158 → meshcode-2.11.159}/meshcode/meshcode_mcp/__main__.py +0 -0
  48. {meshcode-2.11.158 → meshcode-2.11.159}/meshcode/meshcode_mcp/test_backend.py +0 -0
  49. {meshcode-2.11.158 → meshcode-2.11.159}/meshcode/meshcode_mcp/test_boot_timing.py +0 -0
  50. {meshcode-2.11.158 → meshcode-2.11.159}/meshcode/meshcode_mcp/test_install_guard.py +0 -0
  51. {meshcode-2.11.158 → meshcode-2.11.159}/meshcode/meshcode_mcp/test_prefs_claude_version.py +0 -0
  52. {meshcode-2.11.158 → meshcode-2.11.159}/meshcode/meshcode_mcp/test_realtime.py +0 -0
  53. {meshcode-2.11.158 → meshcode-2.11.159}/meshcode/meshcode_mcp/test_server_wrapper.py +0 -0
  54. {meshcode-2.11.158 → meshcode-2.11.159}/meshcode/preferences.py +0 -0
  55. {meshcode-2.11.158 → meshcode-2.11.159}/meshcode/protocol_v2.py +0 -0
  56. {meshcode-2.11.158 → meshcode-2.11.159}/meshcode/quickstart.py +0 -0
  57. {meshcode-2.11.158 → meshcode-2.11.159}/meshcode/rpc_allowlist.py +0 -0
  58. {meshcode-2.11.158 → meshcode-2.11.159}/meshcode/scripts/check_secrets.py +0 -0
  59. {meshcode-2.11.158 → meshcode-2.11.159}/meshcode/scripts/race_rate_harness.py +0 -0
  60. {meshcode-2.11.158 → meshcode-2.11.159}/meshcode/secrets.py +0 -0
  61. {meshcode-2.11.158 → meshcode-2.11.159}/meshcode/supervisor.py +0 -0
  62. {meshcode-2.11.158 → meshcode-2.11.159}/meshcode/upload.py +0 -0
  63. {meshcode-2.11.158 → meshcode-2.11.159}/meshcode.egg-info/dependency_links.txt +0 -0
  64. {meshcode-2.11.158 → meshcode-2.11.159}/meshcode.egg-info/entry_points.txt +0 -0
  65. {meshcode-2.11.158 → meshcode-2.11.159}/meshcode.egg-info/requires.txt +0 -0
  66. {meshcode-2.11.158 → meshcode-2.11.159}/meshcode.egg-info/top_level.txt +0 -0
  67. {meshcode-2.11.158 → meshcode-2.11.159}/setup.cfg +0 -0
  68. {meshcode-2.11.158 → meshcode-2.11.159}/tests/test_auto_update_hardening.py +0 -0
  69. {meshcode-2.11.158 → meshcode-2.11.159}/tests/test_autonomous_closegap_1.py +0 -0
  70. {meshcode-2.11.158 → meshcode-2.11.159}/tests/test_autonomous_closegap_2.py +0 -0
  71. {meshcode-2.11.158 → meshcode-2.11.159}/tests/test_autonomous_closegap_3.py +0 -0
  72. {meshcode-2.11.158 → meshcode-2.11.159}/tests/test_autonomous_prompt_inject.py +0 -0
  73. {meshcode-2.11.158 → meshcode-2.11.159}/tests/test_boot_bug_regression.py +0 -0
  74. {meshcode-2.11.158 → meshcode-2.11.159}/tests/test_color_truecolor.py +0 -0
  75. {meshcode-2.11.158 → meshcode-2.11.159}/tests/test_core.py +0 -0
  76. {meshcode-2.11.158 → meshcode-2.11.159}/tests/test_cross_agent_messaging.py +0 -0
  77. {meshcode-2.11.158 → meshcode-2.11.159}/tests/test_date_parse.py +0 -0
  78. {meshcode-2.11.158 → meshcode-2.11.159}/tests/test_doctor.py +0 -0
  79. {meshcode-2.11.158 → meshcode-2.11.159}/tests/test_ensure_boot_env_urgent_wake.py +0 -0
  80. {meshcode-2.11.158 → meshcode-2.11.159}/tests/test_epistemic_v1_python_sdk.py +0 -0
  81. {meshcode-2.11.158 → meshcode-2.11.159}/tests/test_epistemic_v1_stop_conditions.py +0 -0
  82. {meshcode-2.11.158 → meshcode-2.11.159}/tests/test_esc_deaf_state.py +0 -0
  83. {meshcode-2.11.158 → meshcode-2.11.159}/tests/test_exceptions.py +0 -0
  84. {meshcode-2.11.158 → meshcode-2.11.159}/tests/test_file_upload.py +0 -0
  85. {meshcode-2.11.158 → meshcode-2.11.159}/tests/test_hostd_launch_pinned_env.py +0 -0
  86. {meshcode-2.11.158 → meshcode-2.11.159}/tests/test_hostd_serve_discovery_split.py +0 -0
  87. {meshcode-2.11.158 → meshcode-2.11.159}/tests/test_init_device_code.py +0 -0
  88. {meshcode-2.11.158 → meshcode-2.11.159}/tests/test_install_guard.py +0 -0
  89. {meshcode-2.11.158 → meshcode-2.11.159}/tests/test_launch_smoke.py +0 -0
  90. {meshcode-2.11.158 → meshcode-2.11.159}/tests/test_lease_sigterm_release.py +0 -0
  91. {meshcode-2.11.158 → meshcode-2.11.159}/tests/test_live_mesh_guard.py +0 -0
  92. {meshcode-2.11.158 → meshcode-2.11.159}/tests/test_mark_read_batch.py +0 -0
  93. {meshcode-2.11.158 → meshcode-2.11.159}/tests/test_marketplace_ratings.py +0 -0
  94. {meshcode-2.11.158 → meshcode-2.11.159}/tests/test_migration_integrity.py +0 -0
  95. {meshcode-2.11.158 → meshcode-2.11.159}/tests/test_no_appleevents_on_sweep.py +0 -0
  96. {meshcode-2.11.158 → meshcode-2.11.159}/tests/test_preflight_hb_gate.py +0 -0
  97. {meshcode-2.11.158 → meshcode-2.11.159}/tests/test_pretrust_claude.py +0 -0
  98. {meshcode-2.11.158 → meshcode-2.11.159}/tests/test_push_guard.py +0 -0
  99. {meshcode-2.11.158 → meshcode-2.11.159}/tests/test_realtime_event_freshness.py +0 -0
  100. {meshcode-2.11.158 → meshcode-2.11.159}/tests/test_replica_base_workspace_fallback.py +0 -0
  101. {meshcode-2.11.158 → meshcode-2.11.159}/tests/test_replica_boot_protocol_unconditional.py +0 -0
  102. {meshcode-2.11.158 → meshcode-2.11.159}/tests/test_rls_cross_tenant.py +0 -0
  103. {meshcode-2.11.158 → meshcode-2.11.159}/tests/test_rm_guard.py +0 -0
  104. {meshcode-2.11.158 → meshcode-2.11.159}/tests/test_rpc_grants.py +0 -0
  105. {meshcode-2.11.158 → meshcode-2.11.159}/tests/test_rpc_migrations.py +0 -0
  106. {meshcode-2.11.158 → meshcode-2.11.159}/tests/test_run_agent_dry_run.py +0 -0
  107. {meshcode-2.11.158 → meshcode-2.11.159}/tests/test_run_agent_no_server_import.py +0 -0
  108. {meshcode-2.11.158 → meshcode-2.11.159}/tests/test_security_regressions.py +0 -0
  109. {meshcode-2.11.158 → meshcode-2.11.159}/tests/test_self_update_user_site.py +0 -0
  110. {meshcode-2.11.158 → meshcode-2.11.159}/tests/test_sentinel.py +0 -0
  111. {meshcode-2.11.158 → meshcode-2.11.159}/tests/test_session_replay_gate.py +0 -0
  112. {meshcode-2.11.158 → meshcode-2.11.159}/tests/test_setup_path.py +0 -0
  113. {meshcode-2.11.158 → meshcode-2.11.159}/tests/test_sleep_signals.py +0 -0
  114. {meshcode-2.11.158 → meshcode-2.11.159}/tests/test_status_enum_coverage.py +0 -0
  115. {meshcode-2.11.158 → meshcode-2.11.159}/tests/test_stay_on_loop_hook.py +0 -0
  116. {meshcode-2.11.158 → meshcode-2.11.159}/tests/test_stop_ghost_terminal.py +0 -0
  117. {meshcode-2.11.158 → meshcode-2.11.159}/tests/test_task_progress.py +0 -0
  118. {meshcode-2.11.158 → meshcode-2.11.159}/tests/test_terminal_lifecycle.py +0 -0
  119. {meshcode-2.11.158 → meshcode-2.11.159}/tests/test_up_launch_cmd.py +0 -0
  120. {meshcode-2.11.158 → meshcode-2.11.159}/tests/test_update_guard.py +0 -0
  121. {meshcode-2.11.158 → meshcode-2.11.159}/tests/test_urgent_wake_tmux.py +0 -0
  122. {meshcode-2.11.158 → meshcode-2.11.159}/tests/test_wait_open_tasks_contradiction.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: meshcode
3
- Version: 2.11.158
3
+ Version: 2.11.159
4
4
  Summary: Real-time communication between AI agents — Supabase-backed CLI
5
5
  Author-email: MeshCode <hello@meshcode.io>
6
6
  License: MIT
@@ -1,5 +1,5 @@
1
1
  """MeshCode — Real-time communication between AI agents."""
2
- __version__ = "2.11.158"
2
+ __version__ = "2.11.159"
3
3
 
4
4
  # Exception hierarchy — eagerly imported (lightweight, no deps)
5
5
  from meshcode.exceptions import ( # noqa: F401
@@ -13,7 +13,7 @@ def main():
13
13
  # (comms_v4), not just setup-path. hostd spawns agents via `python -m meshcode run <target>`
14
14
  # (so a bg pip can replace the .exe) — that MUST route to the `run` dispatch, NOT fall through
15
15
  # to the PATH-help error. Previously only setup-path dispatched, so every `python -m meshcode
16
- # run` died with the misleading "meshcode not on PATH" message (qa/recycle-demo/respawn boots).
16
+ # run` died with the misleading "meshcode not on PATH" message (qa/respawn boots).
17
17
  if len(sys.argv) > 1:
18
18
  # runpy imports + executes comms_v4 as __main__; do NOT pre-import it here (a prior
19
19
  # `import meshcode.comms_v4` triggers a runpy "found in sys.modules" double-exec warning).
@@ -1,12 +1,12 @@
1
1
  """Session-handoff hook templates — single source of truth for the
2
2
  PreCompact (write) + SessionStart (read) hooks.
3
3
 
4
- CTX-CLOSE-RELAUNCH (task bcd157a9, backend2): when a commander/agent session
5
- gets recycled at high context — either by Claude Code's in-place autocompact
6
- or by a clean close+relaunch — the IN-FLIGHT working context (which task I was
7
- mid-executing, what I just edited/decided this session) is lost. meshcode_boot
8
- restores mesh state (tasks, inbox, memory) authoritatively, but NOT the
9
- conversational thread. These two hooks bridge that gap:
4
+ SESSION HANDOFF (task bcd157a9, backend2): when a session ends or compacts at
5
+ high context — either by Claude Code's in-place autocompact or by a manual
6
+ relaunch — the IN-FLIGHT working context (which task I was mid-executing, what
7
+ I just edited/decided this session) is lost. meshcode_boot restores mesh state
8
+ (tasks, inbox, memory) authoritatively, but NOT the conversational thread.
9
+ These two hooks bridge that gap:
10
10
 
11
11
  * PreCompact -> session_handoff_write.py: dump a compact snapshot of the
12
12
  recent transcript tail to .claude/handoff.json BEFORE the context is
@@ -18,11 +18,8 @@ conversational thread. These two hooks bridge that gap:
18
18
 
19
19
  Stored as string constants (same pattern as _stop_hook_template.py) so
20
20
  `meshcode patch-hooks` can backfill existing workspaces without a full
21
- re-scaffold. The recycle TRIGGER itself (mc_request_recycle / wait-loop
22
- must_exit=recycle / hostd context branch) is owned by the daemon/server side
23
- and is intentionally NOT in these scripts — handoff preservation is decoupled
24
- from whatever causes the restart, so it works for autocompact, clean recycle,
25
- crash-respawn, or a manual relaunch alike.
21
+ re-scaffold. Handoff preservation is decoupled from whatever causes the
22
+ restart, so it works for autocompact, crash-respawn, or a manual relaunch alike.
26
23
  """
27
24
 
28
25
  # Shared constants kept in sync between the two bodies.
@@ -33,9 +30,9 @@ _HANDOFF_MAX_AGE_S = 24 * 3600 # ignore stale handoffs on read
33
30
 
34
31
  HANDOFF_WRITE_BODY = '''#!/usr/bin/env python3
35
32
  """PreCompact hook: snapshot the recent transcript tail to .claude/handoff.json
36
- so a fresh post-recycle session can resume the in-flight thread.
33
+ so a fresh post-restart session can resume the in-flight thread.
37
34
 
38
- CTX-CLOSE-RELAUNCH (task bcd157a9). Pure local file I/O — never touches the
35
+ SESSION HANDOFF (task bcd157a9). Pure local file I/O — never touches the
39
36
  network, never imports meshcode, never blocks. Any failure is swallowed and the
40
37
  hook exits 0 so it can NEVER stall or break a Claude Code compaction/exit.
41
38
 
@@ -113,61 +110,13 @@ def _extract_tail(transcript_path: str):
113
110
  return rows[-MAX_TURNS:]
114
111
 
115
112
 
116
- def _request_recycle_if_marked(project_dir) -> None:
117
- """CTX-CLOSE-RELAUNCH (task 400fc536): commander-tier sessions ask the
118
- server to recycle (close+relaunch fresh) at the next task-edge, right after
119
- the handoff is snapshotted. Gated by the scaffold-baked
120
- .claude/meshcode_hook_ctx.json recycle_on_compact flag (commander-only v1).
121
-
122
- Best-effort in every dimension: missing marker/flag, missing creds, import
123
- failure, network error -> silently skip. handoff.json is already written, so
124
- a context-recycle still relaunches WITH context; and the actual exit is the
125
- server's call (mc_consume_recycle at a task boundary), never this hook.
126
- """
127
- try:
128
- ctx_path = project_dir / ".claude" / "meshcode_hook_ctx.json"
129
- if not ctx_path.exists():
130
- return
131
- if not json.loads(ctx_path.read_text(encoding="utf-8")).get("recycle_on_compact"):
132
- return # non-commander -> in-place autocompact, no recycle
133
- mcp = json.loads((project_dir / ".mcp.json").read_text(encoding="utf-8"))
134
- env = (next(iter((mcp.get("mcpServers") or {}).values()), {}) or {}).get("env", {}) or {}
135
- url = env.get("SUPABASE_URL"); key = env.get("SUPABASE_KEY")
136
- pid = env.get("MESHCODE_PROJECT_ID"); agent = env.get("MESHCODE_AGENT")
137
- if not (url and key and pid and agent):
138
- return
139
- api_key = os.environ.get("MESHCODE_API_KEY")
140
- if not api_key:
141
- try:
142
- import importlib
143
- api_key = importlib.import_module("meshcode.secrets").get_api_key(
144
- profile=env.get("MESHCODE_KEYCHAIN_PROFILE") or "default")
145
- except Exception:
146
- api_key = None
147
- if not api_key:
148
- return
149
- import urllib.request as _u
150
- body = json.dumps({
151
- "p_api_key": api_key, "p_project_id": pid,
152
- "p_agent_name": agent, "p_allow_busy": True, # flag-now; exit deferred to wait-loop
153
- }).encode("utf-8")
154
- req = _u.Request(
155
- url.rstrip("/") + "/rest/v1/rpc/mc_request_recycle",
156
- data=body, method="POST",
157
- headers={"apikey": key, "Authorization": "Bearer " + key,
158
- "Content-Type": "application/json"})
159
- _u.urlopen(req, timeout=5).read() # best-effort; ignore result per backend contract
160
- except Exception as e: # noqa: BLE001 — never block compaction
161
- sys.stderr.write(f"[session_handoff_write] recycle-request skipped: {e}\\n")
162
-
163
-
164
113
  def _persist_handoff_to_memory(project_dir, handoff) -> None:
165
114
  """L6 M6.1 (task 84c426d4, 2.11.114): mirror the handoff into
166
115
  mc_agent_memory key='session_handoff' so the server-side boot
167
116
  continuity_capsule (mig 456) can surface it on the NEXT session even
168
117
  when the local handoff.json is gone (new host, wiped workspace).
169
- Same best-effort creds pattern as _request_recycle_if_marked
170
- any failure silently skips; handoff.json already covers the local path.
118
+ Best-effort creds pattern any failure silently skips; handoff.json
119
+ already covers the local path.
171
120
  """
172
121
  try:
173
122
  mcp = json.loads((project_dir / ".mcp.json").read_text(encoding="utf-8"))
@@ -305,9 +254,6 @@ def main() -> int:
305
254
  _persist_handoff_to_memory(_project_dir(), handoff)
306
255
  # py-half 4aee4739: dedicated handoff capsule -> mc_boot continuity_capsule.last_handoff.
307
256
  _send_session_handoff_capsule(_project_dir(), handoff)
308
- # CTX-CLOSE-RELAUNCH (task 400fc536): now that the thread is snapshotted,
309
- # commander-tier sessions ask the server to recycle at the next task-edge.
310
- _request_recycle_if_marked(_project_dir())
311
257
  return 0
312
258
 
313
259
 
@@ -321,10 +267,10 @@ if __name__ == "__main__":
321
267
 
322
268
  HANDOFF_READ_BODY = '''#!/usr/bin/env python3
323
269
  """SessionStart hook: if a handoff snapshot exists, inject it as
324
- additionalContext so a freshly-recycled session resumes the in-flight thread,
270
+ additionalContext so a freshly-relaunched session resumes the in-flight thread,
325
271
  then archive it so it is injected exactly once.
326
272
 
327
- CTX-CLOSE-RELAUNCH (task bcd157a9). Pure local file I/O — no network, no
273
+ SESSION HANDOFF (task bcd157a9). Pure local file I/O — no network, no
328
274
  meshcode import, never blocks. meshcode_boot remains authoritative for mesh
329
275
  state; this only restores the conversational thread.
330
276
 
@@ -360,9 +306,9 @@ def _render(handoff: dict) -> str:
360
306
  if not turns:
361
307
  return ""
362
308
  lines = [
363
- "## Recovered session handoff (CTX-CLOSE-RELAUNCH)",
309
+ "## Recovered session handoff",
364
310
  "",
365
- "Your previous session was recycled at high context. meshcode_boot has "
311
+ "Your previous session ended or compacted at high context. meshcode_boot has "
366
312
  "the authoritative mesh state (tasks/inbox/memory); the thread tail "
367
313
  "below is the in-flight context that boot does not restore. Use it to "
368
314
  "resume what you were mid-doing, then run the normal boot loop.",
@@ -2509,7 +2509,7 @@ AGENT CONTROL:
2509
2509
  disconnect <proj> <name> Graceful disconnect
2510
2510
  whoami Show logged-in identity
2511
2511
 
2512
- SWARM (agent replicas):
2512
+ REPLICAS (agent clones):
2513
2513
  replicate <agent> --count N [--no-launch] Clone agent into <agent>-1..N (launches by default)
2514
2514
  replica-power <group_id> running|stopped Stop/Start a whole replica group [--restart]
2515
2515
  profile [agent] Show/set agent profile
@@ -2540,16 +2540,14 @@ Run `meshcode <command> --help` for help on a specific command.
2540
2540
 
2541
2541
  # Per-subcommand help texts
2542
2542
  SUBCOMMAND_HELP = {
2543
- "up": """meshcode up <project> [--agents a,b] [--recycle <ctx%|Nh>] [--visible]
2543
+ "up": """meshcode up <project> [--agents a,b] [--visible]
2544
2544
 
2545
2545
  Launch-All: opens a visible terminal for each agent in the project and
2546
2546
  registers them as hostd-managed (so the watchdog daemon auto-relaunches
2547
- and recycles them). The fast way to bring a whole team online at once.
2547
+ them if they crash). The fast way to bring a whole team online at once.
2548
2548
 
2549
2549
  meshcode up myproject launch every agent in the roster
2550
2550
  meshcode up myproject --agents a,b launch only a and b
2551
- meshcode up myproject --recycle 80 set context-% recycle policy
2552
- meshcode up myproject --recycle 12h set uptime recycle policy
2553
2551
 
2554
2552
  Roster comes from the cloud (exact names). Pair with `meshcode hostd
2555
2553
  install` so the launched team stays alive across crashes.
@@ -2557,18 +2555,16 @@ install` so the launched team stays alive across crashes.
2557
2555
  "hostd": """meshcode hostd run|status|install|uninstall
2558
2556
 
2559
2557
  Host-side watchdog daemon: auto-relaunches dead/stale managed agents
2560
- (respawn) and recycles long-running ones (uptime/context, at task
2561
- boundary). Complements supervisor.py (launchd KeepAlive = process-exit
2562
- only); hostd polls the cloud for heartbeat staleness + recycle triggers.
2558
+ (respawn). Complements supervisor.py (launchd KeepAlive = process-exit
2559
+ only); hostd polls the cloud for heartbeat staleness.
2563
2560
 
2564
2561
  meshcode hostd run run the poll loop in the foreground
2565
2562
  meshcode hostd status show agents this host would respawn (JSON)
2566
2563
  meshcode hostd install install the launchd agent (auto-start, KeepAlive)
2567
2564
  meshcode hostd uninstall remove the launchd agent
2568
2565
 
2569
- Agents are managed via mc_host_set_agents (desired_state=running) +
2570
- mc_host_config_set (recycle policy). NOT autostart-login; the Launch
2571
- button (meshcode://) kickstarts it.
2566
+ Agents are managed via mc_host_set_agents (desired_state=running).
2567
+ NOT autostart-login; the Launch button (meshcode://) kickstarts it.
2572
2568
  """,
2573
2569
  "init": """meshcode init
2574
2570
 
@@ -3404,9 +3400,9 @@ if __name__ == "__main__":
3404
3400
  # rows get desired_state='running' so hostd auto-spawns them as persistent
3405
3401
  # terminals within ~one sweep; --no-launch creates them dormant (Start later
3406
3402
  # from the dashboard or `meshcode replica-power <group> running`). The shared
3407
- # replica_group_id (== swarm_id) lets the whole group be powered as a unit
3408
- # while per-replica desired_state still allows killing one without the group.
3409
- # Backend for task 069b5550.
3403
+ # replica_group_id (stored in the swarm_id column) lets the whole group be
3404
+ # powered as a unit while per-replica desired_state still allows killing one
3405
+ # without the group. Backend for task 069b5550.
3410
3406
  _ak = _load_api_key_for_cli()
3411
3407
  base = pos[0] if len(pos) > 0 else flags.get("agent", "")
3412
3408
  proj = flags.get("project")
@@ -3424,9 +3420,9 @@ if __name__ == "__main__":
3424
3420
  print("[meshcode] ERROR: --count must be an integer in 1..16")
3425
3421
  sys.exit(1)
3426
3422
  desired = None if flags.get("no-launch") else "running"
3427
- # p_mode (task 986947b5): copilotos = shared swarm_id (coordinate via one tray) |
3428
- # independientes = distinct swarm_id per replica (isolated). Default copilotos
3429
- # (Samuel's canonical spec). DB mig586 honors it on both overloads.
3423
+ # p_mode (task 986947b5): copilotos = one shared replica group (coordinate
3424
+ # together) | independientes = a distinct group per replica (isolated).
3425
+ # Default copilotos (Samuel's canonical spec). DB mig586 honors it on both overloads.
3430
3426
  mode = str(flags.get("mode", "copilotos")).lower()
3431
3427
  if mode not in ("copilotos", "independientes"):
3432
3428
  print("[meshcode] ERROR: --mode must be 'copilotos' (shared/coordinate) or "
@@ -3475,9 +3471,9 @@ if __name__ == "__main__":
3475
3471
  # meshcode replica-power <group_id> running|stopped [--restart]
3476
3472
  #
3477
3473
  # Sets desired_state for EVERY agent sharing replica_group_id (Stop/Start the
3478
- # whole swarm as a unit). CLI/agent path = mc_replica_group_power_as_agent
3474
+ # whole replica group as a unit). CLI/agent path = mc_replica_group_power_as_agent
3479
3475
  # (DB mig 20260616_573); the FE buttons call mc_replica_group_power (auth.uid,
3480
- # no api_key in the browser). --restart requests a recycle on launch.
3476
+ # no api_key in the browser). --restart relaunches the group's terminals on power-on.
3481
3477
  # Backend for task 069b5550 (FE Stop/Start/Launch route through here).
3482
3478
  _ak = _load_api_key_for_cli()
3483
3479
  group = pos[0] if len(pos) > 0 else flags.get("group", "")
@@ -4097,14 +4093,14 @@ if __name__ == "__main__":
4097
4093
  print(f"Usage: meshcode supervisor [start|stop|status|--simple] <project> <agent>")
4098
4094
 
4099
4095
  elif cmd == "hostd":
4100
- # meshcode hostd run|status — local respawn/recycle watchdog daemon
4096
+ # meshcode hostd run|status — local respawn watchdog daemon
4101
4097
  # (auto-relaunch of stale/dead managed agents; mesh-core incident fix).
4102
4098
  import importlib
4103
4099
  _hostd = importlib.import_module("meshcode.hostd")
4104
4100
  sys.exit(_hostd.cmd_hostd(pos))
4105
4101
 
4106
4102
  elif cmd == "up":
4107
- # meshcode up <project> [--agents a,b] [--recycle <ctx%|Nh>] — Launch-All:
4103
+ # meshcode up <project> [--agents a,b] — Launch-All:
4108
4104
  # opens a visible terminal per agent + registers them as hostd-managed.
4109
4105
  import importlib
4110
4106
  _up = importlib.import_module("meshcode.up")