swarph-cli 0.69.8__tar.gz → 0.70.0__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.
- {swarph_cli-0.69.8/src/swarph_cli.egg-info → swarph_cli-0.70.0}/PKG-INFO +1 -1
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/pyproject.toml +1 -1
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/src/swarph_cli/__init__.py +1 -1
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/src/swarph_cli/commands/mesh.py +172 -30
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/src/swarph_cli/commands/monitor.py +44 -7
- swarph_cli-0.70.0/src/swarph_cli/scripts/wake_watchdog.py +385 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0/src/swarph_cli.egg-info}/PKG-INFO +1 -1
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/src/swarph_cli.egg-info/SOURCES.txt +2 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_644_monitor_supervision.py +107 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_729_wake_watchdog.py +2 -0
- swarph_cli-0.70.0/tests/test_739_wake_writer.py +479 -0
- swarph_cli-0.70.0/tests/test_961_cursor_grok_footer.py +331 -0
- swarph_cli-0.69.8/src/swarph_cli/scripts/wake_watchdog.py +0 -209
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/LICENSE +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/README.md +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/setup.cfg +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/src/swarph_cli/__main__.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/src/swarph_cli/bench/__init__.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/src/swarph_cli/bench/backends.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/src/swarph_cli/bench/claude_cli.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/src/swarph_cli/bench/pack.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/src/swarph_cli/bench/prices.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/src/swarph_cli/bench/providers.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/src/swarph_cli/bench/quality.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/src/swarph_cli/bench/refresh_prices.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/src/swarph_cli/bench/rules.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/src/swarph_cli/bench/runner.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/src/swarph_cli/bench/validate.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/src/swarph_cli/caller.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/src/swarph_cli/capture/__init__.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/src/swarph_cli/capture/harden.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/src/swarph_cli/capture/lineage.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/src/swarph_cli/capture/liveness.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/src/swarph_cli/capture/manifest.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/src/swarph_cli/capture/paths.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/src/swarph_cli/capture/verify.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/src/swarph_cli/cell.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/src/swarph_cli/chain_token.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/src/swarph_cli/channel.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/src/swarph_cli/commands/__init__.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/src/swarph_cli/commands/_content.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/src/swarph_cli/commands/_display.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/src/swarph_cli/commands/_gateway_client.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/src/swarph_cli/commands/add.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/src/swarph_cli/commands/bench.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/src/swarph_cli/commands/board.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/src/swarph_cli/commands/board_merge_check.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/src/swarph_cli/commands/brain.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/src/swarph_cli/commands/brain_ask.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/src/swarph_cli/commands/cell.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/src/swarph_cli/commands/cell_probe.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/src/swarph_cli/commands/cell_selfcheck.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/src/swarph_cli/commands/channel.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/src/swarph_cli/commands/chat.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/src/swarph_cli/commands/codegraph.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/src/swarph_cli/commands/codegraph_hook.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/src/swarph_cli/commands/codex_hook_output.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/src/swarph_cli/commands/codex_waker.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/src/swarph_cli/commands/compress.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/src/swarph_cli/commands/daemon.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/src/swarph_cli/commands/dreaming.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/src/swarph_cli/commands/event.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/src/swarph_cli/commands/gateway.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/src/swarph_cli/commands/gh_route.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/src/swarph_cli/commands/group.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/src/swarph_cli/commands/guide.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/src/swarph_cli/commands/highlight.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/src/swarph_cli/commands/hook_interpreter.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/src/swarph_cli/commands/hook_output.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/src/swarph_cli/commands/hooks.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/src/swarph_cli/commands/import_session.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/src/swarph_cli/commands/init.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/src/swarph_cli/commands/install_codex_hooks.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/src/swarph_cli/commands/install_hook.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/src/swarph_cli/commands/install_multiplexer.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/src/swarph_cli/commands/install_opencode_plugin.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/src/swarph_cli/commands/install_postcompact_hook.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/src/swarph_cli/commands/install_wake_hook.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/src/swarph_cli/commands/lane.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/src/swarph_cli/commands/mcp_server.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/src/swarph_cli/commands/memory.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/src/swarph_cli/commands/memory_emit_hook.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/src/swarph_cli/commands/memory_sync.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/src/swarph_cli/commands/okf_links.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/src/swarph_cli/commands/onboard.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/src/swarph_cli/commands/peer_reply_drain.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/src/swarph_cli/commands/postcompact_hook_output.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/src/swarph_cli/commands/protocol_handler.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/src/swarph_cli/commands/ratify.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/src/swarph_cli/commands/schedule.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/src/swarph_cli/commands/security.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/src/swarph_cli/commands/service.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/src/swarph_cli/commands/spawn.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/src/swarph_cli/commands/timeline.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/src/swarph_cli/commands/version.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/src/swarph_cli/commands/wake_hook_output.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/src/swarph_cli/commands/watchdog.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/src/swarph_cli/compress/__init__.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/src/swarph_cli/compress/levers.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/src/swarph_cli/compress/marker.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/src/swarph_cli/compress/verify.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/src/swarph_cli/console_safe.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/src/swarph_cli/delivery_queue.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/src/swarph_cli/dm_frame.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/src/swarph_cli/dreaming/__init__.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/src/swarph_cli/dreaming/candidates.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/src/swarph_cli/dreaming/clone.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/src/swarph_cli/dreaming/enrich.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/src/swarph_cli/dreaming/index_check.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/src/swarph_cli/dreaming/notify.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/src/swarph_cli/dreaming/organize.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/src/swarph_cli/dreaming/probes.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/src/swarph_cli/dreaming/report.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/src/swarph_cli/dreaming/run.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/src/swarph_cli/dreaming/slm.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/src/swarph_cli/dreaming/transcripts.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/src/swarph_cli/dreaming/verify.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/src/swarph_cli/gateway/__init__.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/src/swarph_cli/gateway/feature_registry.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/src/swarph_cli/gateway/lanes_control.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/src/swarph_cli/gateway/schema.sql +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/src/swarph_cli/gateway/server.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/src/swarph_cli/gateway/services_control.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/src/swarph_cli/gateway_default.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/src/swarph_cli/gh_identity.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/src/swarph_cli/guide/GUIDE.md +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/src/swarph_cli/identity.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/src/swarph_cli/main.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/src/swarph_cli/multiplexer.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/src/swarph_cli/orphan_daemons.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/src/swarph_cli/pane_probe.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/src/swarph_cli/parsers/__init__.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/src/swarph_cli/parsers/claude.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/src/swarph_cli/payloads/opencode/plugin.js +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/src/swarph_cli/payloads/postcompact/_shim.cmd +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/src/swarph_cli/payloads/postcompact/postcompact-recall-grok.sh +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/src/swarph_cli/payloads/postcompact/postcompact-recall.sh +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/src/swarph_cli/payloads/postcompact/posttooluse-emit-antigravity.sh +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/src/swarph_cli/payloads/postcompact/posttooluse-emit-claude.sh +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/src/swarph_cli/payloads/postcompact/posttooluse-emit-grok.sh +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/src/swarph_cli/payloads/postcompact/posttooluse-emit.sh +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/src/swarph_cli/payloads/postcompact/posttooluse-recall.sh +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/src/swarph_cli/payloads/postcompact/precompact-flag.sh +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/src/swarph_cli/payloads/postcompact/preinvocation-recall-antigravity.sh +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/src/swarph_cli/payloads/postcompact/sessionstart-recall.sh +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/src/swarph_cli/peer_executor.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/src/swarph_cli/peer_executor_windows.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/src/swarph_cli/peer_reconciliation.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/src/swarph_cli/peer_reply_outbox.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/src/swarph_cli/peer_service_host.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/src/swarph_cli/peer_service_payload.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/src/swarph_cli/peer_service_reply.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/src/swarph_cli/peer_staging.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/src/swarph_cli/query_filters.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/src/swarph_cli/scripts/__init__.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/src/swarph_cli/scripts/dm_notify_filter.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/src/swarph_cli/scripts/ensure_monitor.sh +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/src/swarph_cli/scripts/install_codex_waker_windows.ps1 +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/src/swarph_cli/scripts/install_monitor_task_windows.ps1 +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/src/swarph_cli/service/__init__.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/src/swarph_cli/service/app.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/src/swarph_cli/service/providers.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/src/swarph_cli/session_bridge.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/src/swarph_cli/skills/i-have-adhd/LICENSE +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/src/swarph_cli/skills/i-have-adhd/SKILL.md +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/src/swarph_cli/source_text.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/src/swarph_cli/stall_alert.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/src/swarph_cli/systemd/codex-waker.default +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/src/swarph_cli/systemd/peer-reply-drain.default +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/src/swarph_cli/systemd/swarph-codex-outbox@.service +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/src/swarph_cli/systemd/swarph-codex-outbox@.timer +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/src/swarph_cli/systemd/swarph-codex-waker@.service +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/src/swarph_cli/systemd/swarph-codex-waker@.timer +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/src/swarph_cli/systemd/swarph-monitor-reexec.path +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/src/swarph_cli/systemd/swarph-monitor-reexec.service +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/src/swarph_cli/systemd/swarph-monitor@.service +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/src/swarph_cli/systemd/swarph-peer-reply-drain@.service +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/src/swarph_cli/systemd/swarph-peer-reply-drain@.timer +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/src/swarph_cli/systemd/swarph-watchdog.default +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/src/swarph_cli/systemd/swarph-watchdog.service +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/src/swarph_cli/systemd/swarph-watchdog.timer +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/src/swarph_cli/timeline_paths.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/src/swarph_cli/tokens.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/src/swarph_cli.egg-info/dependency_links.txt +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/src/swarph_cli.egg-info/entry_points.txt +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/src/swarph_cli.egg-info/requires.txt +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/src/swarph_cli.egg-info/top_level.txt +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_1006_session_board.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_124_register_merge.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_126_pending_from_complete.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_132_ensure_monitor_state_dir.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_138_memory_navigate.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_139_tool_probe.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_183_card_anchor.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_184_notify_honesty.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_201_win32_bash_refusal.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_243_onboard_per_peer_token.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_307_task4_ask_reply.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_312_codegraph_fuzzy_verb.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_319_refusal_exit_codes.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_323_mistral_backend.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_332_report_organize_findings.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_356_query_filters.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_397_gh_identity_router.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_397_router_preflight.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_402_one_identity_resolver.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_467b_onboard_operator_credential.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_472_register_caller_binding.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_523_guide.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_524_conftest_hermeticity.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_532_accept_flag.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_535_version_capability.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_546_default_gateway.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_547_verbs_from_registry.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_548_gateway_remainder.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_552_codegraph_gateway.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_555_relay_row_shape.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_556_relay_freshness.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_559_edges_truncated.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_564_bootstrap_first_peer.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_578_no_machine_specific_host_defaults.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_579_register_bootstrap_message.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_591_cli_step_graph.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_648_install_unit.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_654_reexec.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_656_owned_slm.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_684_dreaming_verb.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_689_pkg_version_order.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_715_grok_wake.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_716_timeline_one_path.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_723_grok_0251.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_724_ps1_ascii_or_bom.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_725_stdio_reconfigure.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_726_grok_limit_screen.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_729_dm_once.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_734_dreaming_enrich_degrade.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_735_dm_mcp_tools.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_740_edit_project.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_762_cards_edit_priority.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_764_enrich_collapse.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_801_confirm_flow_cli.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_802_stage_history.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_825_codegraph_hook_noise.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_825_install_posttooluse_only.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_825_remaining_cap_shred_bind.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_829_counterfactual_column.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_830_hook_binding_version.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_84_cli_labels.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_866_doctrine_guide.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_872_identity_refuses_not_warns.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_874_source_text.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_888_opencode_data_dir_can_fail.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_937_dreaming_notify.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_938_organize_line_limit.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_941_bench_backends.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_941_harness_342.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_945_same_line_pairing.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_955_prompt_audit.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_957_auth_http.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_959_venv_interpreter.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_960_channel.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_960_ensure_monitor_heartbeat.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_963_plugin_manifest.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_964_channel_cell.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_965_mesh_wait.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_975_channel_hop.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_add_security_gate.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_artifact_add.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_artifact_hash.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_artifact_lib.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_artifact_mcp.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_artifact_skill.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_artifact_tool.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_artifact_uri.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_bench_backends.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_bench_claude_cli.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_bench_command.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_bench_pack.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_bench_prices.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_bench_quality.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_bench_runner.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_bench_validate.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_board_card_thread.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_board_command.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_board_merge_check.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_board_obligation_close.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_brain_ask_command.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_brain_ask_env_diagnosis.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_brain_ask_identity_explicitness.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_brain_command.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_caller_meta_guard.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_capture_lineage.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_capture_liveness.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_capture_manifest.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_capture_paths.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_capture_security.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_cell_command_dispatch.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_cell_harden.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_cell_loader.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_cell_selfcheck.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_cell_verify.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_chain_token.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_channel_command.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_channel_poll_never_breaks_dms.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_channel_post.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_channel_wake_policy_filter.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_chat_command.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_claude_parser.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_claude_tmux_template.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_codegraph_caller_scope.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_codegraph_command.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_codegraph_hook.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_codegraph_mcp.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_codex_waker.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_compress_caller_convention.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_compress_command.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_compress_levers.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_compress_marker.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_compress_verify.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_console_encoding_e2e.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_content_composition.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_cursor_membrane.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_daemon_command.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_daemon_console_encoding.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_daemon_delivery.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_delivery_queue.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_display_sanitize.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_ensure_monitor_no_peer_default.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_event_emit.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_feature_to_uri.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_gateway_brain.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_gateway_client.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_gateway_command.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_gateway_message_idempotency.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_gh_route_doctor_mesh_name.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_group_command.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_guide_commands_parse.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_guide_selfcheck.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_heartbeat_check.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_highlight_command.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_hook_output.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_hooks_activity_marker.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_hooks_add.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_hooks_bundle.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_hooks_init.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_hooks_legacy_generation_removal.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_hooks_lifecycle.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_hooks_merge.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_hooks_verify.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_hooks_win32_bash_wrapper.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_hooks_win32_command_path.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_import_command.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_inbox_identity_provenance.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_init_command.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_init_provider_menu.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_install_codex_hooks.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_install_hook.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_install_multiplexer_command.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_install_postcompact_hook.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_install_wake_hook.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_lane_command.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_main.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_main_unknown_verb_guard.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_mcp_missing_hint.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_mcp_server.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_memory_command.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_memory_emit_snippet.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_memory_gateway.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_memory_sync.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_memory_sync_membrane.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_mesh_command.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_mesh_inbox_mark_read.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_mesh_inbox_sanitize.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_mesh_originate_thread_623.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_mesh_send_unknown_peer.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_mesh_sidecar.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_mesh_sidecar_cursor_decoupled.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_mesh_sidecar_wake_survives_read.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_meta_edge_identity.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_monitor_channel_poll.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_monitor_cli.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_monitor_daemon_collision.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_monitor_self_name_verification.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_monitor_state_split.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_multiplexer.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_muse_membrane.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_muse_own_cli.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_obligation_close_is_surfaced.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_okf_links.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_onboard_command.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_opencode_membrane.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_opencode_plugin.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_orphan_daemons.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_packaged_artifacts_exist.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_packaged_skills.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_peer_executor.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_peer_executor_windows.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_peer_reply_drain_command.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_peer_reply_drain_supervisor.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_peer_reply_outbox.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_peer_reply_transport.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_peer_service_e2e.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_peer_service_host.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_peer_service_payload.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_peer_service_reply.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_postcompact_recall.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_process_liveness.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_protocol_handler.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_providers_isolation.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_ratify_command.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_readme_claims_no_gateway_default.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_repl_caller_convention.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_schedule_command.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_schedule_create_contract.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_security.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_service_app.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_service_command.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_service_providers.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_session_bridge_inject.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_session_bridge_probe.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_session_bridge_resolve.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_session_path_role_gate.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_shipped_units_match_the_cli.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_smoke_chat.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_smoke_one_shot.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_smoke_phase_5_5.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_spawn_base_hoist.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_spawn_command.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_spawn_identity_stamp.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_spawn_live_pin.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_spawn_mitosis_lineage.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_spawn_tmux_session.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_spawn_windows_relaunch.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_stall_alert.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_subprocess_decode_encoding.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_timeline_command.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_tmux_wake_runstate_defer.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_tmux_wake_session_reanchor.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_tmux_wake_stale.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_tmux_wake_submit_verify.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_token_file_one_parser.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_token_precedence_explicit_first.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_unified_token_resolver.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_version_command.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_version_consistency.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_vibe_membrane.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_watchdog.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_watchdog_dm_wake.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_watchdog_dm_wake_cooldown.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_watchdog_dm_wake_wiring.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_watchdog_emit_health.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_watchdog_install_flags.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_watchdog_model_rung.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_watchdog_stale_peers.py +0 -0
- {swarph_cli-0.69.8 → swarph_cli-0.70.0}/tests/test_windows_waker_installer.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: swarph-cli
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.70.0
|
|
4
4
|
Summary: The `swarph` binary — a multi-LLM CLI and mesh-gateway client + bundled server (`swarph gateway`): one-shot prompts across providers, interactive `chat`, multi-provider `spawn` (claude/codex/antigravity via a ProviderMembrane with subprocess billing-scrub), `mesh` send/inbox/register, `brain-ask` over the swarph-brain (gbrain) semantic memory, git-backed `assisted_memory`, per-invocation `gh` identity routing, a silent DM-wake hook, session `import`, and a stranded-session `watchdog`.
|
|
5
5
|
Author: Pierre Samson, Claude Opus
|
|
6
6
|
License: MIT
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "swarph-cli"
|
|
7
|
-
version = "0.
|
|
7
|
+
version = "0.70.0"
|
|
8
8
|
description = "The `swarph` binary — a multi-LLM CLI and mesh-gateway client + bundled server (`swarph gateway`): one-shot prompts across providers, interactive `chat`, multi-provider `spawn` (claude/codex/antigravity via a ProviderMembrane with subprocess billing-scrub), `mesh` send/inbox/register, `brain-ask` over the swarph-brain (gbrain) semantic memory, git-backed `assisted_memory`, per-invocation `gh` identity routing, a silent DM-wake hook, session `import`, and a stranded-session `watchdog`."
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
license = { text = "MIT" }
|
|
@@ -2136,6 +2136,33 @@ _COMPOSER_PLACEHOLDERS = ("Add a follow-up", "Ask Codex to do anything")
|
|
|
2136
2136
|
#: running agent into an idle one forever.
|
|
2137
2137
|
_CURSOR_RUN_HINT = "ctrl+c to stop"
|
|
2138
2138
|
|
|
2139
|
+
#: A live cursor turn draws a braille spinner and then ``Thinking``,
|
|
2140
|
+
#: ``Running``, or ``Working`` on the row directly above the Tip/composer
|
|
2141
|
+
#: block. A quote of that row anywhere else, including a code echo, is not
|
|
2142
|
+
#: a turn. The match is anchored: stripped text has to start with the glyph.
|
|
2143
|
+
_CURSOR_SPINNER_ROW = re.compile(
|
|
2144
|
+
r"^[\u2800-\u28FF]+\s*(?:Thinking|Running|Working)\b"
|
|
2145
|
+
)
|
|
2146
|
+
|
|
2147
|
+
#: How many non-empty rows at the bottom can hold the cursor composer.
|
|
2148
|
+
#: Measured on cursor-lin 2026-09-30: the composer is the 4th non-empty row
|
|
2149
|
+
#: from the bottom (composer, task count, model footer, tilde). A quote of
|
|
2150
|
+
#: that row higher in the pane is scrollback, not the composer. Blank rows
|
|
2151
|
+
#: between those chrome lines do not count: a raw tail of N lines drops the
|
|
2152
|
+
#: composer off the window when the screen interleaves blanks.
|
|
2153
|
+
_CURSOR_COMPOSER_TAIL = 6
|
|
2154
|
+
|
|
2155
|
+
#: The 1.18.33 permission dialog draws ``△ Permission required`` above a
|
|
2156
|
+
#: stack of option rows. On the measured screen that row is the 10th
|
|
2157
|
+
#: non-empty row from the bottom, outside the composer tail.
|
|
2158
|
+
_OPENCODE_PERMISSION_TAIL = 12
|
|
2159
|
+
|
|
2160
|
+
|
|
2161
|
+
def _nonempty_tail(lines: list[str], n: int) -> list[str]:
|
|
2162
|
+
"""The last ``n`` rows that contain text. Blank rows are not rows."""
|
|
2163
|
+
filled = [ln for ln in lines if ln.strip()]
|
|
2164
|
+
return filled[-n:]
|
|
2165
|
+
|
|
2139
2166
|
|
|
2140
2167
|
def _only_wake_text(content: str) -> bool:
|
|
2141
2168
|
"""True when the composer holds wake text and nothing else.
|
|
@@ -2172,19 +2199,21 @@ def _opencode_permission_row(line: str) -> bool:
|
|
|
2172
2199
|
return s.startswith("┃") and "△" in s and "Permission required" in s
|
|
2173
2200
|
|
|
2174
2201
|
|
|
2202
|
+
def _is_opencode_composer_row(line: str) -> bool:
|
|
2203
|
+
"""One row of the opencode box: the mode row, the ``╹▀`` border, or the
|
|
2204
|
+
permission dialog. A quote of ``┃ Build ·`` above the tail is not this."""
|
|
2205
|
+
s = line.strip()
|
|
2206
|
+
return s.startswith("╹▀") or _opencode_mode_row(line) or _opencode_permission_row(line)
|
|
2207
|
+
|
|
2208
|
+
|
|
2175
2209
|
def _is_opencode_pane(lines: list[str]) -> bool:
|
|
2176
2210
|
"""The opencode composer box, measured on 1.18.33.
|
|
2177
2211
|
|
|
2178
|
-
|
|
2179
|
-
|
|
2180
|
-
|
|
2181
|
-
Cursor and claude do not draw any of these.
|
|
2212
|
+
Decided by ``_bottom_tui``: the mode row, the ``╹▀`` border, or the
|
|
2213
|
+
permission dialog has to be the bottom-most composer in the non-empty
|
|
2214
|
+
tail. A cursor pane that merely quotes ``┃ Build ·`` is not opencode.
|
|
2182
2215
|
"""
|
|
2183
|
-
|
|
2184
|
-
s = ln.strip()
|
|
2185
|
-
if s.startswith("╹▀") or _opencode_mode_row(ln) or _opencode_permission_row(ln):
|
|
2186
|
-
return True
|
|
2187
|
-
return False
|
|
2216
|
+
return bool(lines) and _bottom_tui(lines) == "opencode"
|
|
2188
2217
|
|
|
2189
2218
|
|
|
2190
2219
|
def _opencode_running(lines: list[str]) -> bool:
|
|
@@ -2281,29 +2310,115 @@ def _opencode_composer_state(lines: list[str]) -> Optional[str]:
|
|
|
2281
2310
|
return "busy"
|
|
2282
2311
|
|
|
2283
2312
|
|
|
2284
|
-
def
|
|
2285
|
-
"""
|
|
2313
|
+
def _is_grok_composer_row(lines: list[str], index: int) -> bool:
|
|
2314
|
+
"""A grok composer starts at a ``│ ❯`` row. Continuation rows that also
|
|
2315
|
+
start with ``│`` may sit between it and the ``╰`` footer, which is how
|
|
2316
|
+
a wrapped draft is drawn. A cursor diff hunk (``▎``) never counts."""
|
|
2317
|
+
row = lines[index].strip()
|
|
2318
|
+
if row.startswith("▎") or not (row.startswith("│") and "❯" in row):
|
|
2319
|
+
return False
|
|
2320
|
+
j = index + 1
|
|
2321
|
+
while j < len(lines):
|
|
2322
|
+
nxt = lines[j].strip()
|
|
2323
|
+
if nxt.startswith("▎"):
|
|
2324
|
+
return False
|
|
2325
|
+
if nxt.startswith("╰"):
|
|
2326
|
+
return True
|
|
2327
|
+
if nxt.startswith("│"):
|
|
2328
|
+
j += 1
|
|
2329
|
+
continue
|
|
2330
|
+
return False
|
|
2331
|
+
return False
|
|
2286
2332
|
|
|
2287
|
-
The footer names ``Grok 4.`` inside the box, or the splash prints
|
|
2288
|
-
``Grok Build``. History also draws a ``❯`` for the submitted prompt;
|
|
2289
|
-
that row has no box bar, so it is not the composer. A usage-limit
|
|
2290
|
-
modal drops both of those and is recognized by ``_grok_block_reason``.
|
|
2291
|
-
"""
|
|
2292
|
-
return any("Grok 4." in ln or ln.strip().startswith("Grok Build") for ln in lines)
|
|
2293
2333
|
|
|
2334
|
+
def _is_cursor_composer_row(line: str) -> bool:
|
|
2335
|
+
"""Any cursor composer row, including a human draft. The empty one
|
|
2336
|
+
reads ``→ Add a follow-up``. A ``▎`` hunk never counts."""
|
|
2337
|
+
row = line.strip()
|
|
2338
|
+
return row.startswith("→") and not row.startswith("▎")
|
|
2294
2339
|
|
|
2295
|
-
|
|
2296
|
-
|
|
2297
|
-
row
|
|
2298
|
-
|
|
2299
|
-
|
|
2300
|
-
|
|
2301
|
-
|
|
2340
|
+
|
|
2341
|
+
def _bottom_tui(lines: list[str]) -> "str | None":
|
|
2342
|
+
"""Who owns the bottom-most composer row in the non-empty tail.
|
|
2343
|
+
|
|
2344
|
+
``"cursor"``, ``"grok"``, or ``"opencode"``. A match above that tail
|
|
2345
|
+
is scrollback. The lower composer wins, so a quoted grok box or a
|
|
2346
|
+
quoted ``┃ Build ·`` row above the cursor composer does not take the pane.
|
|
2347
|
+
"""
|
|
2348
|
+
tail = _nonempty_tail(lines, _CURSOR_COMPOSER_TAIL)
|
|
2349
|
+
for i in range(len(tail) - 1, -1, -1):
|
|
2350
|
+
if _is_cursor_composer_row(tail[i]):
|
|
2351
|
+
return "cursor"
|
|
2352
|
+
if _is_grok_composer_row(tail, i):
|
|
2353
|
+
return "grok"
|
|
2354
|
+
if _is_opencode_composer_row(tail[i]):
|
|
2355
|
+
return "opencode"
|
|
2356
|
+
# A permission dialog is taller than the composer tail. Look further
|
|
2357
|
+
# for that one row. A mode row or a cursor/grok composer in the same
|
|
2358
|
+
# stretch is a quote, not a reason to take the pane.
|
|
2359
|
+
wider = _nonempty_tail(lines, _OPENCODE_PERMISSION_TAIL)
|
|
2360
|
+
for i in range(len(wider) - 1, -1, -1):
|
|
2361
|
+
if _is_cursor_composer_row(wider[i]) or _is_grok_composer_row(wider, i):
|
|
2362
|
+
return None
|
|
2363
|
+
if not _is_opencode_composer_row(wider[i]):
|
|
2364
|
+
continue
|
|
2365
|
+
if _opencode_permission_row(wider[i]):
|
|
2366
|
+
return "opencode"
|
|
2302
2367
|
return None
|
|
2303
|
-
|
|
2368
|
+
return None
|
|
2369
|
+
|
|
2370
|
+
|
|
2371
|
+
def _is_cursor_composer(lines: list[str]) -> bool:
|
|
2372
|
+
"""The cursor composer ROW, not a quote of its placeholder.
|
|
2373
|
+
|
|
2374
|
+
The row is the bottom-most composer inside the non-empty tail, the
|
|
2375
|
+
same row ``_composer_state`` reads. Its stripped text has to start
|
|
2376
|
+
with ``→ Add a follow-up``. A mention of that placeholder anywhere
|
|
2377
|
+
else in the pane is not the composer.
|
|
2378
|
+
"""
|
|
2379
|
+
return bool(lines) and _bottom_tui(lines) == "cursor"
|
|
2380
|
+
|
|
2381
|
+
|
|
2382
|
+
def _is_grok_pane(lines: list[str]) -> bool:
|
|
2383
|
+
"""The grok TUI, by the composer row at the bottom of the pane.
|
|
2384
|
+
|
|
2385
|
+
Cursor's footer can read ``Grok 4.7``. That string is not the test.
|
|
2386
|
+
A grok composer is a ``│ ❯`` row immediately followed by ``╰``, and
|
|
2387
|
+
only when that pair is the bottom-most composer in the non-empty tail.
|
|
2388
|
+
A ``│``/``❯`` pair or a ``╰`` / ``always-approve`` pair anywhere else,
|
|
2389
|
+
including a cursor diff hunk that starts with ``▎``, is not a grok pane.
|
|
2390
|
+
A history ``❯`` without the box bar is not the composer. A usage-limit
|
|
2391
|
+
modal drops the box and is recognized by ``_grok_block_reason``.
|
|
2392
|
+
"""
|
|
2393
|
+
return bool(lines) and _bottom_tui(lines) == "grok"
|
|
2394
|
+
|
|
2395
|
+
|
|
2396
|
+
def _grok_box_text(lines: list[str], index: int) -> str:
|
|
2397
|
+
"""The draft inside a grok box, including ``│`` continuation rows."""
|
|
2398
|
+
after = lines[index].split("❯", 1)[1]
|
|
2304
2399
|
if "│" in after:
|
|
2305
2400
|
after = after.split("│", 1)[0]
|
|
2306
|
-
|
|
2401
|
+
parts = [after.strip()]
|
|
2402
|
+
j = index + 1
|
|
2403
|
+
while j < len(lines) and lines[j].strip().startswith("│"):
|
|
2404
|
+
body = lines[j].strip()[1:]
|
|
2405
|
+
if "│" in body:
|
|
2406
|
+
body = body.split("│", 1)[0]
|
|
2407
|
+
parts.append(body.strip())
|
|
2408
|
+
j += 1
|
|
2409
|
+
return " ".join(p for p in parts if p)
|
|
2410
|
+
|
|
2411
|
+
|
|
2412
|
+
def _grok_input(lines: list[str]) -> Optional[str]:
|
|
2413
|
+
"""Text in the live grok box, '' when empty, None if that box is not
|
|
2414
|
+
the bottom composer. Continuation rows count as part of the draft."""
|
|
2415
|
+
tail = _nonempty_tail(lines, _CURSOR_COMPOSER_TAIL)
|
|
2416
|
+
for i in range(len(tail) - 1, -1, -1):
|
|
2417
|
+
if _is_cursor_composer_row(tail[i]) or _is_opencode_composer_row(tail[i]):
|
|
2418
|
+
return None
|
|
2419
|
+
if _is_grok_composer_row(tail, i):
|
|
2420
|
+
return _grok_box_text(tail, i)
|
|
2421
|
+
return None
|
|
2307
2422
|
|
|
2308
2423
|
|
|
2309
2424
|
# One grok screen, measured on the live 0.2.51 pane (52 rows). Lines above
|
|
@@ -2421,10 +2536,28 @@ def _agent_running(target: str) -> Optional[bool]:
|
|
|
2421
2536
|
return _opencode_running(lines)
|
|
2422
2537
|
if _is_grok_pane(lines):
|
|
2423
2538
|
return _grok_running(lines)
|
|
2424
|
-
|
|
2425
|
-
|
|
2539
|
+
tail = _nonempty_tail(lines, _CURSOR_COMPOSER_TAIL)
|
|
2540
|
+
composer = _composer_line(tail)
|
|
2541
|
+
if composer is None or not composer.startswith("→"):
|
|
2426
2542
|
return None
|
|
2427
|
-
|
|
2543
|
+
if _CURSOR_RUN_HINT in composer:
|
|
2544
|
+
return True
|
|
2545
|
+
# The spinner is the non-empty row directly above the Tip/composer
|
|
2546
|
+
# block: the Tip row when it is present, otherwise the composer.
|
|
2547
|
+
# No other row in the tail can make the pane read as running.
|
|
2548
|
+
idx = None
|
|
2549
|
+
for i in range(len(tail) - 1, -1, -1):
|
|
2550
|
+
if _is_cursor_composer_row(tail[i]):
|
|
2551
|
+
idx = i
|
|
2552
|
+
break
|
|
2553
|
+
if idx is None or idx == 0:
|
|
2554
|
+
return False
|
|
2555
|
+
anchor = idx - 1
|
|
2556
|
+
if tail[anchor].strip().startswith("Tip:"):
|
|
2557
|
+
if anchor == 0:
|
|
2558
|
+
return False
|
|
2559
|
+
anchor -= 1
|
|
2560
|
+
return bool(_CURSOR_SPINNER_ROW.match(tail[anchor].strip()))
|
|
2428
2561
|
|
|
2429
2562
|
|
|
2430
2563
|
def _composer_state(target: str) -> Optional[str]:
|
|
@@ -2452,6 +2585,12 @@ def _composer_state(target: str) -> Optional[str]:
|
|
|
2452
2585
|
if _is_grok_pane(lines):
|
|
2453
2586
|
return _grok_composer_state(lines)
|
|
2454
2587
|
composer = _composer_line(lines)
|
|
2588
|
+
if composer is not None and composer.startswith("→"):
|
|
2589
|
+
# A cursor marker above the bottom tail is a quoted row. The
|
|
2590
|
+
# composer itself is off-screen, so this pane is not readable.
|
|
2591
|
+
composer = _composer_line(_nonempty_tail(lines, _CURSOR_COMPOSER_TAIL))
|
|
2592
|
+
if composer is None or not composer.startswith("→"):
|
|
2593
|
+
return None
|
|
2455
2594
|
if composer is None:
|
|
2456
2595
|
return None
|
|
2457
2596
|
content = composer[1:].strip()
|
|
@@ -2976,8 +3115,11 @@ def _monitor_loop(state: MonitorState) -> int:
|
|
|
2976
3115
|
try:
|
|
2977
3116
|
_monitor_iteration(state)
|
|
2978
3117
|
except KeyboardInterrupt:
|
|
3118
|
+
# An interrupt during an iteration is not a clean return. Swallowing
|
|
3119
|
+
# it and returning 0 made _run_pinned delete monitor.pid, so the
|
|
3120
|
+
# watchdog then reported the cell unsupervised.
|
|
2979
3121
|
state.shutdown_requested = True
|
|
2980
|
-
|
|
3122
|
+
raise
|
|
2981
3123
|
except Exception as exc:
|
|
2982
3124
|
print(f"{state.log_prefix} iteration error: {type(exc).__name__}: {exc}",
|
|
2983
3125
|
file=sys.stderr)
|
|
@@ -326,6 +326,38 @@ def _read_cgroup(pid: int) -> "str | None":
|
|
|
326
326
|
return None
|
|
327
327
|
|
|
328
328
|
|
|
329
|
+
def _service_leaf(text: "str | None") -> "str | None":
|
|
330
|
+
"""The .service leaf of a cgroup, or None.
|
|
331
|
+
|
|
332
|
+
user@<uid>.service is the session manager, not a supervisor. The leaf
|
|
333
|
+
keeps its .service suffix so a later reader can name the unit after
|
|
334
|
+
this process is gone.
|
|
335
|
+
"""
|
|
336
|
+
if not text:
|
|
337
|
+
return None
|
|
338
|
+
for line in text.splitlines():
|
|
339
|
+
leaf = line.rsplit("/", 1)[-1].strip()
|
|
340
|
+
if leaf.endswith(".service") and not leaf.startswith("user@"):
|
|
341
|
+
return leaf
|
|
342
|
+
return None
|
|
343
|
+
|
|
344
|
+
|
|
345
|
+
def _supervisor_for_pidfile(explicit: "str | None") -> "str | None":
|
|
346
|
+
"""What start writes into monitor.pid.
|
|
347
|
+
|
|
348
|
+
An explicit claim wins over the cgroup. Otherwise record a unit only
|
|
349
|
+
when its name says it supervises a monitor (swarph-monitor*.service).
|
|
350
|
+
A foreign leaf such as claude-tmux@X.service is not a monitor supervisor.
|
|
351
|
+
The read is this process's own cgroup, taken now, while the pid is ours.
|
|
352
|
+
"""
|
|
353
|
+
if explicit:
|
|
354
|
+
return explicit
|
|
355
|
+
leaf = _service_leaf(_read_cgroup(os.getpid()))
|
|
356
|
+
if leaf and leaf.startswith("swarph-monitor"):
|
|
357
|
+
return leaf
|
|
358
|
+
return None
|
|
359
|
+
|
|
360
|
+
|
|
329
361
|
def _derive_systemd_unit(pid: "int | None") -> "str | None":
|
|
330
362
|
"""The supervisor Linux already knows (#344 review): Windows has no
|
|
331
363
|
pid→task map so the pidfile CLAIM is the whole answer there, but on
|
|
@@ -589,10 +621,11 @@ def _cmd_start(args: argparse.Namespace) -> int:
|
|
|
589
621
|
)
|
|
590
622
|
return 0
|
|
591
623
|
|
|
624
|
+
recorded = _supervisor_for_pidfile(supervisor)
|
|
592
625
|
if args.once:
|
|
593
626
|
mesh.write_pidfile(
|
|
594
627
|
pidfile, self_name=self_name, sinks=sinks, poll_s=args.poll_s,
|
|
595
|
-
supervisor=
|
|
628
|
+
supervisor=recorded,
|
|
596
629
|
)
|
|
597
630
|
mesh._monitor_iteration(state)
|
|
598
631
|
return 0
|
|
@@ -602,22 +635,26 @@ def _cmd_start(args: argparse.Namespace) -> int:
|
|
|
602
635
|
print("swarph monitor: no fork() on this platform — running in the "
|
|
603
636
|
"foreground", file=sys.stderr)
|
|
604
637
|
return _run_pinned(state, pidfile, self_name, sinks, args.poll_s,
|
|
605
|
-
supervisor=
|
|
638
|
+
supervisor=recorded)
|
|
606
639
|
|
|
607
640
|
return _start_detached(state, pidfile, self_name, sinks, args.poll_s,
|
|
608
|
-
supervisor=
|
|
641
|
+
supervisor=recorded)
|
|
609
642
|
|
|
610
643
|
|
|
611
644
|
def _run_pinned(state, pidfile: Path, self_name: str, sinks: list, poll_s: int,
|
|
612
645
|
supervisor: "str | None" = None) -> int:
|
|
613
646
|
mesh.write_pidfile(pidfile, self_name=self_name, sinks=sinks, poll_s=poll_s,
|
|
614
647
|
supervisor=supervisor)
|
|
648
|
+
clean = False
|
|
615
649
|
try:
|
|
616
|
-
|
|
650
|
+
result = mesh._monitor_loop(state)
|
|
651
|
+
clean = True
|
|
652
|
+
return result
|
|
617
653
|
finally:
|
|
618
|
-
#
|
|
619
|
-
#
|
|
620
|
-
|
|
654
|
+
# A clean return can drop the file. SIGINT and any other unwind must
|
|
655
|
+
# not: the recorded supervisor is what the watchdog names after the
|
|
656
|
+
# process is gone. `monitor stop` still deletes the file itself.
|
|
657
|
+
if clean and mesh.pidfile_status(pidfile)[0] == "live_ours":
|
|
621
658
|
pidfile.unlink(missing_ok=True)
|
|
622
659
|
|
|
623
660
|
|