swarph-cli 0.68.2__tar.gz → 0.69.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.68.2/src/swarph_cli.egg-info → swarph_cli-0.69.0}/PKG-INFO +1 -1
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/pyproject.toml +1 -1
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/src/swarph_cli/__init__.py +1 -1
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/src/swarph_cli/channel.py +4 -3
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/src/swarph_cli/commands/brain_ask.py +33 -22
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/src/swarph_cli/commands/codegraph.py +7 -8
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/src/swarph_cli/commands/codegraph_hook.py +2 -1
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/src/swarph_cli/commands/daemon.py +5 -8
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/src/swarph_cli/commands/gh_route.py +3 -2
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/src/swarph_cli/commands/highlight.py +14 -7
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/src/swarph_cli/commands/hooks.py +2 -5
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/src/swarph_cli/commands/install_postcompact_hook.py +2 -2
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/src/swarph_cli/commands/mcp_server.py +6 -3
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/src/swarph_cli/commands/memory.py +5 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/src/swarph_cli/commands/memory_emit_hook.py +12 -3
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/src/swarph_cli/commands/mesh.py +7 -10
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/src/swarph_cli/commands/monitor.py +2 -1
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/src/swarph_cli/commands/onboard.py +4 -3
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/src/swarph_cli/commands/wake_hook_output.py +2 -1
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/src/swarph_cli/commands/watchdog.py +8 -5
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/src/swarph_cli/gateway/server.py +11 -0
- swarph_cli-0.69.0/src/swarph_cli/identity.py +85 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0/src/swarph_cli.egg-info}/PKG-INFO +1 -1
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/src/swarph_cli.egg-info/SOURCES.txt +3 -0
- swarph_cli-0.69.0/tests/test_402_one_identity_resolver.py +229 -0
- swarph_cli-0.69.0/tests/test_472_register_caller_binding.py +101 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_brain_ask_env_diagnosis.py +12 -9
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_brain_ask_identity_explicitness.py +12 -12
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_postcompact_recall.py +3 -3
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_watchdog.py +8 -6
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/LICENSE +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/README.md +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/setup.cfg +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/src/swarph_cli/__main__.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/src/swarph_cli/bench/__init__.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/src/swarph_cli/bench/backends.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/src/swarph_cli/bench/pack.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/src/swarph_cli/bench/prices.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/src/swarph_cli/bench/providers.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/src/swarph_cli/bench/quality.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/src/swarph_cli/bench/refresh_prices.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/src/swarph_cli/bench/rules.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/src/swarph_cli/bench/runner.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/src/swarph_cli/bench/validate.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/src/swarph_cli/caller.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/src/swarph_cli/capture/__init__.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/src/swarph_cli/capture/harden.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/src/swarph_cli/capture/lineage.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/src/swarph_cli/capture/liveness.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/src/swarph_cli/capture/manifest.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/src/swarph_cli/capture/paths.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/src/swarph_cli/capture/verify.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/src/swarph_cli/cell.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/src/swarph_cli/chain_token.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/src/swarph_cli/commands/__init__.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/src/swarph_cli/commands/_content.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/src/swarph_cli/commands/_display.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/src/swarph_cli/commands/_gateway_client.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/src/swarph_cli/commands/add.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/src/swarph_cli/commands/bench.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/src/swarph_cli/commands/board.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/src/swarph_cli/commands/board_merge_check.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/src/swarph_cli/commands/brain.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/src/swarph_cli/commands/cell.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/src/swarph_cli/commands/cell_probe.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/src/swarph_cli/commands/cell_selfcheck.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/src/swarph_cli/commands/channel.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/src/swarph_cli/commands/chat.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/src/swarph_cli/commands/codex_hook_output.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/src/swarph_cli/commands/codex_waker.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/src/swarph_cli/commands/compress.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/src/swarph_cli/commands/dreaming.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/src/swarph_cli/commands/event.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/src/swarph_cli/commands/gateway.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/src/swarph_cli/commands/group.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/src/swarph_cli/commands/guide.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/src/swarph_cli/commands/hook_interpreter.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/src/swarph_cli/commands/hook_output.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/src/swarph_cli/commands/import_session.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/src/swarph_cli/commands/init.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/src/swarph_cli/commands/install_codex_hooks.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/src/swarph_cli/commands/install_hook.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/src/swarph_cli/commands/install_multiplexer.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/src/swarph_cli/commands/install_opencode_plugin.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/src/swarph_cli/commands/install_wake_hook.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/src/swarph_cli/commands/lane.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/src/swarph_cli/commands/memory_sync.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/src/swarph_cli/commands/okf_links.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/src/swarph_cli/commands/peer_reply_drain.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/src/swarph_cli/commands/postcompact_hook_output.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/src/swarph_cli/commands/protocol_handler.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/src/swarph_cli/commands/ratify.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/src/swarph_cli/commands/schedule.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/src/swarph_cli/commands/security.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/src/swarph_cli/commands/service.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/src/swarph_cli/commands/spawn.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/src/swarph_cli/commands/timeline.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/src/swarph_cli/commands/version.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/src/swarph_cli/compress/__init__.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/src/swarph_cli/compress/levers.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/src/swarph_cli/compress/marker.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/src/swarph_cli/compress/verify.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/src/swarph_cli/console_safe.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/src/swarph_cli/delivery_queue.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/src/swarph_cli/dm_frame.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/src/swarph_cli/dreaming/__init__.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/src/swarph_cli/dreaming/candidates.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/src/swarph_cli/dreaming/clone.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/src/swarph_cli/dreaming/enrich.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/src/swarph_cli/dreaming/index_check.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/src/swarph_cli/dreaming/notify.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/src/swarph_cli/dreaming/organize.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/src/swarph_cli/dreaming/probes.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/src/swarph_cli/dreaming/report.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/src/swarph_cli/dreaming/run.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/src/swarph_cli/dreaming/slm.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/src/swarph_cli/dreaming/transcripts.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/src/swarph_cli/dreaming/verify.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/src/swarph_cli/gateway/__init__.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/src/swarph_cli/gateway/feature_registry.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/src/swarph_cli/gateway/lanes_control.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/src/swarph_cli/gateway/schema.sql +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/src/swarph_cli/gateway/services_control.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/src/swarph_cli/gateway_default.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/src/swarph_cli/gh_identity.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/src/swarph_cli/guide/GUIDE.md +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/src/swarph_cli/main.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/src/swarph_cli/multiplexer.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/src/swarph_cli/orphan_daemons.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/src/swarph_cli/pane_probe.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/src/swarph_cli/parsers/__init__.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/src/swarph_cli/parsers/claude.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/src/swarph_cli/payloads/opencode/plugin.js +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/src/swarph_cli/payloads/postcompact/_shim.cmd +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/src/swarph_cli/payloads/postcompact/postcompact-recall-grok.sh +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/src/swarph_cli/payloads/postcompact/postcompact-recall.sh +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/src/swarph_cli/payloads/postcompact/posttooluse-emit-antigravity.sh +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/src/swarph_cli/payloads/postcompact/posttooluse-emit-claude.sh +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/src/swarph_cli/payloads/postcompact/posttooluse-emit-grok.sh +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/src/swarph_cli/payloads/postcompact/posttooluse-emit.sh +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/src/swarph_cli/payloads/postcompact/posttooluse-recall.sh +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/src/swarph_cli/payloads/postcompact/precompact-flag.sh +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/src/swarph_cli/payloads/postcompact/preinvocation-recall-antigravity.sh +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/src/swarph_cli/payloads/postcompact/sessionstart-recall.sh +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/src/swarph_cli/peer_executor.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/src/swarph_cli/peer_executor_windows.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/src/swarph_cli/peer_reconciliation.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/src/swarph_cli/peer_reply_outbox.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/src/swarph_cli/peer_service_host.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/src/swarph_cli/peer_service_payload.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/src/swarph_cli/peer_service_reply.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/src/swarph_cli/peer_staging.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/src/swarph_cli/query_filters.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/src/swarph_cli/scripts/__init__.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/src/swarph_cli/scripts/dm_notify_filter.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/src/swarph_cli/scripts/ensure_monitor.sh +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/src/swarph_cli/scripts/install_codex_waker_windows.ps1 +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/src/swarph_cli/scripts/install_monitor_task_windows.ps1 +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/src/swarph_cli/scripts/wake_watchdog.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/src/swarph_cli/service/__init__.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/src/swarph_cli/service/app.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/src/swarph_cli/service/providers.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/src/swarph_cli/session_bridge.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/src/swarph_cli/skills/i-have-adhd/LICENSE +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/src/swarph_cli/skills/i-have-adhd/SKILL.md +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/src/swarph_cli/source_text.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/src/swarph_cli/stall_alert.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/src/swarph_cli/systemd/codex-waker.default +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/src/swarph_cli/systemd/peer-reply-drain.default +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/src/swarph_cli/systemd/swarph-codex-outbox@.service +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/src/swarph_cli/systemd/swarph-codex-outbox@.timer +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/src/swarph_cli/systemd/swarph-codex-waker@.service +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/src/swarph_cli/systemd/swarph-codex-waker@.timer +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/src/swarph_cli/systemd/swarph-monitor-reexec.path +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/src/swarph_cli/systemd/swarph-monitor-reexec.service +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/src/swarph_cli/systemd/swarph-monitor@.service +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/src/swarph_cli/systemd/swarph-peer-reply-drain@.service +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/src/swarph_cli/systemd/swarph-peer-reply-drain@.timer +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/src/swarph_cli/systemd/swarph-watchdog.default +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/src/swarph_cli/systemd/swarph-watchdog.service +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/src/swarph_cli/systemd/swarph-watchdog.timer +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/src/swarph_cli/timeline_paths.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/src/swarph_cli/tokens.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/src/swarph_cli.egg-info/dependency_links.txt +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/src/swarph_cli.egg-info/entry_points.txt +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/src/swarph_cli.egg-info/requires.txt +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/src/swarph_cli.egg-info/top_level.txt +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_124_register_merge.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_126_pending_from_complete.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_132_ensure_monitor_state_dir.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_138_memory_navigate.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_139_tool_probe.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_183_card_anchor.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_184_notify_honesty.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_201_win32_bash_refusal.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_243_onboard_per_peer_token.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_307_task4_ask_reply.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_312_codegraph_fuzzy_verb.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_319_refusal_exit_codes.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_323_mistral_backend.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_332_report_organize_findings.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_356_query_filters.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_397_gh_identity_router.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_397_router_preflight.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_467b_onboard_operator_credential.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_523_guide.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_524_conftest_hermeticity.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_532_accept_flag.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_535_version_capability.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_546_default_gateway.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_547_verbs_from_registry.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_548_gateway_remainder.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_552_codegraph_gateway.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_555_relay_row_shape.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_556_relay_freshness.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_559_edges_truncated.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_564_bootstrap_first_peer.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_578_no_machine_specific_host_defaults.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_579_register_bootstrap_message.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_591_cli_step_graph.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_644_monitor_supervision.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_648_install_unit.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_654_reexec.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_656_owned_slm.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_684_dreaming_verb.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_689_pkg_version_order.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_716_timeline_one_path.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_724_ps1_ascii_or_bom.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_725_stdio_reconfigure.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_729_dm_once.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_729_wake_watchdog.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_734_dreaming_enrich_degrade.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_735_dm_mcp_tools.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_740_edit_project.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_762_cards_edit_priority.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_764_enrich_collapse.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_801_confirm_flow_cli.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_802_stage_history.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_825_codegraph_hook_noise.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_825_install_posttooluse_only.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_825_remaining_cap_shred_bind.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_829_counterfactual_column.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_830_hook_binding_version.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_84_cli_labels.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_866_doctrine_guide.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_872_identity_refuses_not_warns.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_874_source_text.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_888_opencode_data_dir_can_fail.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_937_dreaming_notify.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_938_organize_line_limit.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_941_bench_backends.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_941_harness_342.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_945_same_line_pairing.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_955_prompt_audit.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_957_auth_http.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_959_venv_interpreter.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_960_channel.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_963_plugin_manifest.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_964_channel_cell.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_965_mesh_wait.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_975_channel_hop.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_add_security_gate.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_artifact_add.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_artifact_hash.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_artifact_lib.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_artifact_mcp.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_artifact_skill.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_artifact_tool.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_artifact_uri.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_bench_backends.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_bench_command.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_bench_pack.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_bench_prices.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_bench_quality.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_bench_runner.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_bench_validate.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_board_card_thread.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_board_command.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_board_merge_check.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_board_obligation_close.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_brain_ask_command.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_brain_command.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_caller_meta_guard.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_capture_lineage.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_capture_liveness.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_capture_manifest.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_capture_paths.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_capture_security.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_cell_command_dispatch.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_cell_harden.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_cell_loader.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_cell_selfcheck.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_cell_verify.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_chain_token.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_channel_command.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_channel_poll_never_breaks_dms.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_channel_post.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_channel_wake_policy_filter.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_chat_command.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_claude_parser.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_claude_tmux_template.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_codegraph_caller_scope.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_codegraph_command.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_codegraph_hook.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_codegraph_mcp.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_codex_waker.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_compress_caller_convention.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_compress_command.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_compress_levers.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_compress_marker.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_compress_verify.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_console_encoding_e2e.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_content_composition.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_cursor_membrane.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_daemon_command.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_daemon_console_encoding.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_daemon_delivery.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_delivery_queue.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_display_sanitize.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_ensure_monitor_no_peer_default.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_event_emit.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_feature_to_uri.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_gateway_brain.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_gateway_client.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_gateway_command.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_gateway_message_idempotency.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_gh_route_doctor_mesh_name.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_group_command.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_guide_commands_parse.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_guide_selfcheck.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_heartbeat_check.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_highlight_command.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_hook_output.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_hooks_activity_marker.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_hooks_add.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_hooks_bundle.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_hooks_init.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_hooks_legacy_generation_removal.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_hooks_lifecycle.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_hooks_merge.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_hooks_verify.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_hooks_win32_bash_wrapper.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_hooks_win32_command_path.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_import_command.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_inbox_identity_provenance.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_init_command.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_init_provider_menu.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_install_codex_hooks.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_install_hook.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_install_multiplexer_command.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_install_postcompact_hook.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_install_wake_hook.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_lane_command.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_main.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_main_unknown_verb_guard.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_mcp_missing_hint.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_mcp_server.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_memory_command.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_memory_emit_snippet.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_memory_gateway.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_memory_sync.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_memory_sync_membrane.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_mesh_command.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_mesh_inbox_mark_read.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_mesh_inbox_sanitize.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_mesh_originate_thread_623.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_mesh_send_unknown_peer.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_mesh_sidecar.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_mesh_sidecar_cursor_decoupled.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_mesh_sidecar_wake_survives_read.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_meta_edge_identity.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_monitor_channel_poll.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_monitor_cli.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_monitor_daemon_collision.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_monitor_self_name_verification.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_monitor_state_split.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_multiplexer.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_muse_membrane.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_muse_own_cli.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_obligation_close_is_surfaced.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_okf_links.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_onboard_command.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_opencode_membrane.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_opencode_plugin.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_orphan_daemons.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_packaged_artifacts_exist.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_packaged_skills.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_peer_executor.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_peer_executor_windows.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_peer_reply_drain_command.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_peer_reply_drain_supervisor.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_peer_reply_outbox.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_peer_reply_transport.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_peer_service_e2e.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_peer_service_host.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_peer_service_payload.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_peer_service_reply.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_process_liveness.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_protocol_handler.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_providers_isolation.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_ratify_command.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_readme_claims_no_gateway_default.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_repl_caller_convention.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_schedule_command.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_schedule_create_contract.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_security.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_service_app.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_service_command.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_service_providers.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_session_bridge_inject.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_session_bridge_probe.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_session_bridge_resolve.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_session_path_role_gate.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_shipped_units_match_the_cli.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_smoke_chat.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_smoke_one_shot.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_smoke_phase_5_5.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_spawn_base_hoist.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_spawn_command.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_spawn_identity_stamp.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_spawn_live_pin.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_spawn_mitosis_lineage.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_spawn_tmux_session.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_spawn_windows_relaunch.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_stall_alert.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_subprocess_decode_encoding.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_timeline_command.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_tmux_wake_runstate_defer.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_tmux_wake_session_reanchor.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_tmux_wake_stale.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_tmux_wake_submit_verify.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_token_file_one_parser.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_token_precedence_explicit_first.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_unified_token_resolver.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_version_command.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_version_consistency.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_vibe_membrane.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_watchdog_dm_wake.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_watchdog_dm_wake_cooldown.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_watchdog_dm_wake_wiring.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_watchdog_emit_health.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_watchdog_install_flags.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_watchdog_model_rung.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.0}/tests/test_watchdog_stale_peers.py +0 -0
- {swarph_cli-0.68.2 → swarph_cli-0.69.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.69.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.69.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" }
|
|
@@ -13,6 +13,7 @@ import threading
|
|
|
13
13
|
import time
|
|
14
14
|
from pathlib import Path
|
|
15
15
|
|
|
16
|
+
from swarph_cli import identity
|
|
16
17
|
from swarph_cli.dm_frame import FIRST_START_GRACE_S, created_within, frame_text, rows
|
|
17
18
|
from swarph_cli.scripts.dm_notify_filter import is_real_dm
|
|
18
19
|
|
|
@@ -35,8 +36,8 @@ def channel_opted_in() -> bool:
|
|
|
35
36
|
|
|
36
37
|
def channel_serves() -> bool:
|
|
37
38
|
"""Only the cell spawn named in SWARPH_CHANNEL_CELL may poll."""
|
|
38
|
-
self_name =
|
|
39
|
-
named = os.environ.get("SWARPH_CHANNEL_CELL") or ""
|
|
39
|
+
self_name = identity.declared(env=identity.SELF_ONLY)[0] or ""
|
|
40
|
+
named = (os.environ.get("SWARPH_CHANNEL_CELL") or "").strip()
|
|
40
41
|
return channel_opted_in() and bool(named) and named == self_name
|
|
41
42
|
|
|
42
43
|
|
|
@@ -290,7 +291,7 @@ def serve(chan: Channel) -> None:
|
|
|
290
291
|
|
|
291
292
|
|
|
292
293
|
def main(argv: list[str] | None = None) -> int:
|
|
293
|
-
cell =
|
|
294
|
+
cell = identity.declared(env=identity.SELF_ONLY)[0] or ""
|
|
294
295
|
if not cell:
|
|
295
296
|
print("swarph channel: SWARPH_SELF is unset; refusing to start", file=sys.stderr)
|
|
296
297
|
return 2
|
|
@@ -31,6 +31,7 @@ import os
|
|
|
31
31
|
import sys
|
|
32
32
|
import urllib.request
|
|
33
33
|
|
|
34
|
+
from swarph_cli import identity
|
|
34
35
|
from swarph_cli import tokens
|
|
35
36
|
from pathlib import Path
|
|
36
37
|
from typing import Optional
|
|
@@ -108,22 +109,27 @@ def _peer_token_path(self_name: str) -> Path:
|
|
|
108
109
|
return Path.home() / ".config" / "swarph" / f"{self_name}.peer_token"
|
|
109
110
|
|
|
110
111
|
|
|
111
|
-
#
|
|
112
|
-
#
|
|
113
|
-
#
|
|
114
|
-
#
|
|
115
|
-
#
|
|
116
|
-
#
|
|
117
|
-
|
|
112
|
+
# card #402: there is NO default identity. The old fallback was ANOTHER CELL'S NAME
|
|
113
|
+
# ("lab-ovh"): harmless on lab-ovh, silently wrong everywhere else, and it made the
|
|
114
|
+
# cold-env failure report a TOKEN fault (with SWARPH_SELF unset the cell hunted
|
|
115
|
+
# lab-ovh.peer_token, found nothing and blamed the credential; measured 2026-07-29 on
|
|
116
|
+
# 6 of 6 cells). An undeclared cell now does no peer-token lookup at all: brain reads
|
|
117
|
+
# still work from GBRAIN_TOKEN / SWARPH_BRAIN_TOKEN / --token-file, and the gateway
|
|
118
|
+
# path, which needs the cell's own peer token, refuses with the missing variable named.
|
|
119
|
+
# The identity picks a CREDENTIAL file here, so this verb reads SWARPH_SELF (and its
|
|
120
|
+
# legacy SWARPH_NODE alias) only, like the mesh verbs: an ambient SWARPH_CELL, which
|
|
121
|
+
# psmux leaks from the spawning environment (#538), must not select another cell's
|
|
122
|
+
# peer token.
|
|
123
|
+
_IDENTITY_ENV = identity.SELF_ONLY + identity.NODE_ALIAS
|
|
118
124
|
|
|
119
125
|
|
|
120
|
-
def _self_name() -> str:
|
|
121
|
-
return
|
|
126
|
+
def _self_name() -> Optional[str]:
|
|
127
|
+
return identity.declared(env=_IDENTITY_ENV)[0]
|
|
122
128
|
|
|
123
129
|
|
|
124
|
-
def
|
|
125
|
-
"""True when no env
|
|
126
|
-
return
|
|
130
|
+
def _self_name_is_undeclared() -> bool:
|
|
131
|
+
"""True when no flag or env names this cell. There is no fallback name."""
|
|
132
|
+
return _self_name() is None
|
|
127
133
|
|
|
128
134
|
|
|
129
135
|
def env_diagnosis() -> str:
|
|
@@ -135,10 +141,9 @@ def env_diagnosis() -> str:
|
|
|
135
141
|
a sourced profile, a bashrc or a settings.json `env` block never applies.
|
|
136
142
|
"""
|
|
137
143
|
bits = []
|
|
138
|
-
if
|
|
139
|
-
bits.append(
|
|
140
|
-
|
|
141
|
-
f"wrong file)")
|
|
144
|
+
if _self_name_is_undeclared():
|
|
145
|
+
bits.append("SWARPH_SELF unset — no cell identity is declared, so no peer-token "
|
|
146
|
+
"lookup is attempted (there is no default identity; card #402)")
|
|
142
147
|
if not os.environ.get("SWARPH_BRAIN_GATEWAY"):
|
|
143
148
|
bits.append("SWARPH_BRAIN_GATEWAY unset — falling back to a direct brain "
|
|
144
149
|
"connection, which only works where the brain service is reachable "
|
|
@@ -167,8 +172,8 @@ def _resolve_token(token_file: Optional[str], self_name: str) -> Optional[str]:
|
|
|
167
172
|
reviewing #190, and it is the sharpest kind of catch: I had noticed the
|
|
168
173
|
hazard, written a comment about it, and not handled it.
|
|
169
174
|
|
|
170
|
-
`_self_name()` NEVER
|
|
171
|
-
("lab-ovh"). So `bool(self_name)`
|
|
175
|
+
`_self_name()` used to NEVER return empty — it fell back to a default peer
|
|
176
|
+
name ("lab-ovh"; removed by card #402). So `bool(self_name)` was always true, and passing that as
|
|
172
177
|
identity_is_explicit would promote `lab-ovh.peer_token` — ANOTHER CELL'S
|
|
173
178
|
CREDENTIAL — above GBRAIN_TOKEN on every invocation where nothing named the
|
|
174
179
|
cell. The comment above already says why that fallback is dangerous
|
|
@@ -183,15 +188,15 @@ def _resolve_token(token_file: Optional[str], self_name: str) -> Optional[str]:
|
|
|
183
188
|
rather than the resolver, because a unit test at the resolver cannot see
|
|
184
189
|
what the caller makes reachable.
|
|
185
190
|
|
|
186
|
-
Explicitness therefore comes from
|
|
187
|
-
truthiness
|
|
188
|
-
|
|
191
|
+
Explicitness therefore comes from whether a name was DECLARED, not from
|
|
192
|
+
truthiness. Since card #402 nothing is ever guessed, so a declared name is
|
|
193
|
+
the only kind there is, and an undeclared cell gets the env-first order.
|
|
189
194
|
"""
|
|
190
195
|
res = tokens.resolve_token(
|
|
191
196
|
self_name or None,
|
|
192
197
|
token_file,
|
|
193
198
|
env_keys=("GBRAIN_TOKEN", "SWARPH_BRAIN_TOKEN"),
|
|
194
|
-
identity_is_explicit=
|
|
199
|
+
identity_is_explicit=self_name is not None,
|
|
195
200
|
)
|
|
196
201
|
return res.token if res is not None else None
|
|
197
202
|
|
|
@@ -262,6 +267,12 @@ def run_brain_ask(argv: list) -> int:
|
|
|
262
267
|
gw = os.environ.get("SWARPH_BRAIN_GATEWAY")
|
|
263
268
|
if gw:
|
|
264
269
|
self_name = _self_name()
|
|
270
|
+
if self_name is None:
|
|
271
|
+
sys.stderr.write(env_diagnosis())
|
|
272
|
+
sys.stderr.write(
|
|
273
|
+
"swarph brain-ask: SWARPH_BRAIN_GATEWAY set but no cell identity is "
|
|
274
|
+
"declared, so there is no peer token to present (set SWARPH_SELF)\n")
|
|
275
|
+
return 2
|
|
265
276
|
try:
|
|
266
277
|
peer_token = _peer_token_path(self_name).read_text(encoding="utf-8").strip()
|
|
267
278
|
except OSError:
|
|
@@ -34,6 +34,7 @@ import re
|
|
|
34
34
|
import sqlite3
|
|
35
35
|
import sys
|
|
36
36
|
|
|
37
|
+
from swarph_cli import identity
|
|
37
38
|
from swarph_cli.commands.codegraph_hook import _match_quality
|
|
38
39
|
|
|
39
40
|
DEFAULT_INDEX = os.path.expanduser("~/.swarph/codegraph/index.db")
|
|
@@ -68,8 +69,8 @@ DEFAULT_INDEX = os.path.expanduser("~/.swarph/codegraph/index.db")
|
|
|
68
69
|
IDENTITY_UNSET = object() # sentinel: argparse default when --caller-cell is omitted
|
|
69
70
|
|
|
70
71
|
|
|
71
|
-
class
|
|
72
|
-
|
|
72
|
+
# card #402: one exception class for "nobody declared this cell", shared by every verb.
|
|
73
|
+
IdentityNotDeclared = identity.IdentityNotDeclared
|
|
73
74
|
|
|
74
75
|
|
|
75
76
|
def require_caller_cell(explicit=None, *, verb: str) -> str:
|
|
@@ -80,12 +81,10 @@ def require_caller_cell(explicit=None, *, verb: str) -> str:
|
|
|
80
81
|
The refusal names the verb and every way to satisfy it, because an error that
|
|
81
82
|
says only "identity unset" moves the work to the reader.
|
|
82
83
|
"""
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
if v:
|
|
88
|
-
return v
|
|
84
|
+
# card #402: the order lives in swarph_cli.identity, once, for every verb.
|
|
85
|
+
name, _ = identity.declared(None if explicit is IDENTITY_UNSET else explicit)
|
|
86
|
+
if name is not None:
|
|
87
|
+
return name
|
|
89
88
|
raise IdentityNotDeclared(
|
|
90
89
|
f"swarph {verb}: NO CALLER IDENTITY DECLARED, and there is no default.\n"
|
|
91
90
|
f" This used to fall back to 'lab-ovh', which meant an undeclared caller\n"
|
|
@@ -33,6 +33,7 @@ import urllib.request
|
|
|
33
33
|
from datetime import datetime, timezone
|
|
34
34
|
from pathlib import Path
|
|
35
35
|
from typing import Optional
|
|
36
|
+
from swarph_cli import identity
|
|
36
37
|
from swarph_cli.gateway_default import env_gateway
|
|
37
38
|
|
|
38
39
|
TIMEOUT_S = 6
|
|
@@ -477,7 +478,7 @@ def supported_hook_events() -> frozenset:
|
|
|
477
478
|
def run_codegraph_hook(argv: Optional[list] = None) -> int:
|
|
478
479
|
"""ALWAYS exits 0 — must never fail a turn."""
|
|
479
480
|
argv = list(argv or [])
|
|
480
|
-
self_name =
|
|
481
|
+
self_name = identity.declared(env=identity.SELF_ONLY)[0] or ""
|
|
481
482
|
gateway = env_gateway()
|
|
482
483
|
for i, a in enumerate(argv):
|
|
483
484
|
if a == "--as" and i + 1 < len(argv):
|
|
@@ -49,6 +49,7 @@ from contextlib import suppress
|
|
|
49
49
|
from pathlib import Path
|
|
50
50
|
from typing import Optional
|
|
51
51
|
|
|
52
|
+
from swarph_cli import identity
|
|
52
53
|
from swarph_cli import session_bridge, stall_alert
|
|
53
54
|
from swarph_cli.console_safe import print_safe
|
|
54
55
|
from swarph_cli.delivery_queue import DeliveryQueue
|
|
@@ -115,18 +116,14 @@ def _build_parser() -> argparse.ArgumentParser:
|
|
|
115
116
|
|
|
116
117
|
|
|
117
118
|
def _resolve_self_name(arg: Optional[str], state_dir: Path) -> str:
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
env = os.environ.get("SWARPH_SELF")
|
|
121
|
-
if env:
|
|
122
|
-
return env
|
|
123
|
-
return state_dir.name
|
|
119
|
+
name, _ = identity.declared(arg, env=identity.SELF_ONLY)
|
|
120
|
+
return name if name is not None else state_dir.name
|
|
124
121
|
|
|
125
122
|
|
|
126
123
|
def _resolve_state_dir(arg: Optional[str], self_name_arg: Optional[str]) -> Path:
|
|
127
124
|
if arg:
|
|
128
125
|
return Path(arg).expanduser()
|
|
129
|
-
self_name = self_name_arg
|
|
126
|
+
self_name = identity.declared(self_name_arg, env=identity.SELF_ONLY)[0]
|
|
130
127
|
if self_name:
|
|
131
128
|
return Path.home() / "swarph_state" / self_name
|
|
132
129
|
# Last resort — a self_name is needed to disambiguate; surface error.
|
|
@@ -550,7 +547,7 @@ def run_daemon(argv: list[str]) -> int:
|
|
|
550
547
|
args = _build_parser().parse_args(argv)
|
|
551
548
|
|
|
552
549
|
# Resolve identity + state path
|
|
553
|
-
self_name = args.self_name
|
|
550
|
+
self_name = identity.declared(args.self_name, env=identity.SELF_ONLY)[0]
|
|
554
551
|
if args.state_dir:
|
|
555
552
|
state_dir = Path(args.state_dir).expanduser()
|
|
556
553
|
if not self_name:
|
|
@@ -24,6 +24,7 @@ import os
|
|
|
24
24
|
import sys
|
|
25
25
|
from typing import Optional
|
|
26
26
|
|
|
27
|
+
from swarph_cli import identity
|
|
27
28
|
from swarph_cli import gh_identity as ghid
|
|
28
29
|
from swarph_cli.cell import cells_dir
|
|
29
30
|
from swarph_cli.console_safe import print_safe
|
|
@@ -69,7 +70,7 @@ def run_hook(stdin_text: Optional[str] = None) -> int:
|
|
|
69
70
|
# The caller named a credential. #332: an explicit argument is a decision.
|
|
70
71
|
return _allow_unchanged()
|
|
71
72
|
|
|
72
|
-
peer =
|
|
73
|
+
peer = identity.declared(env=identity.SELF_ONLY)[0] or ""
|
|
73
74
|
try:
|
|
74
75
|
res = ghid.resolve(peer or None)
|
|
75
76
|
except ghid.RouterRefusal as exc:
|
|
@@ -93,7 +94,7 @@ def run_hook(stdin_text: Optional[str] = None) -> int:
|
|
|
93
94
|
|
|
94
95
|
|
|
95
96
|
def run_show() -> int:
|
|
96
|
-
peer =
|
|
97
|
+
peer = identity.declared(env=identity.SELF_ONLY)[0] or ""
|
|
97
98
|
try:
|
|
98
99
|
res = ghid.resolve(peer or None)
|
|
99
100
|
except ghid.RouterRefusal as exc:
|
|
@@ -31,6 +31,7 @@ import sys
|
|
|
31
31
|
from datetime import datetime, timezone
|
|
32
32
|
from pathlib import Path
|
|
33
33
|
|
|
34
|
+
from swarph_cli import identity
|
|
34
35
|
from swarph_cli.commands.mesh import _post_json, _resolve_token
|
|
35
36
|
from swarph_cli.timeline_paths import timeline_dir
|
|
36
37
|
|
|
@@ -177,7 +178,12 @@ def _log_via_gateway(gateway: str, cell: str, highlight: str,
|
|
|
177
178
|
if memory:
|
|
178
179
|
body["memory"] = memory
|
|
179
180
|
try:
|
|
180
|
-
token
|
|
181
|
+
# card #402: only a DECLARED identity may select its own peer token over the
|
|
182
|
+
# ambient one. A name guessed from git user.name or the hostname is
|
|
183
|
+
# attribution only: on a shared box it can be ANOTHER cell's name, and its
|
|
184
|
+
# peer token must not be presented as this caller's.
|
|
185
|
+
token = _resolve_token(cell, token_file,
|
|
186
|
+
identity_is_explicit=cell_source in _DECLARED_SOURCES)
|
|
181
187
|
except RuntimeError as exc:
|
|
182
188
|
print(_credential_error(cell, cell_source, exc), file=sys.stderr)
|
|
183
189
|
return 1
|
|
@@ -247,6 +253,10 @@ def _is_git_repo(repo: Path) -> bool:
|
|
|
247
253
|
return r.returncode == 0 and r.stdout.strip() == "true"
|
|
248
254
|
|
|
249
255
|
|
|
256
|
+
# Sources that DECLARE an identity (as opposed to guessing one), card #402.
|
|
257
|
+
_DECLARED_SOURCES = ("--cell", "$SWARPH_SELF", "$SWARPH_CELL")
|
|
258
|
+
|
|
259
|
+
|
|
250
260
|
def _resolve_cell(arg, repo: Path) -> tuple[str, str]:
|
|
251
261
|
"""Return ``(cell, source)``.
|
|
252
262
|
|
|
@@ -257,12 +267,9 @@ def _resolve_cell(arg, repo: Path) -> tuple[str, str]:
|
|
|
257
267
|
"""
|
|
258
268
|
if arg:
|
|
259
269
|
return _collapse(arg), "--cell"
|
|
260
|
-
|
|
261
|
-
if
|
|
262
|
-
return _collapse(
|
|
263
|
-
cell_env = os.environ.get("SWARPH_CELL")
|
|
264
|
-
if cell_env:
|
|
265
|
-
return _collapse(cell_env), "$SWARPH_CELL"
|
|
270
|
+
name, source = identity.declared()
|
|
271
|
+
if name is not None:
|
|
272
|
+
return _collapse(name), source
|
|
266
273
|
if _is_git_repo(repo):
|
|
267
274
|
r = _git(repo, "config", "user.name")
|
|
268
275
|
if r.returncode == 0 and r.stdout.strip():
|
|
@@ -47,6 +47,7 @@ import tempfile
|
|
|
47
47
|
from dataclasses import dataclass
|
|
48
48
|
from pathlib import Path
|
|
49
49
|
|
|
50
|
+
from swarph_cli import identity
|
|
50
51
|
from swarph_cli import __version__ as _SWARPH_CLI_VERSION
|
|
51
52
|
|
|
52
53
|
# Placeholder substituted at install time into generated scripts (#830).
|
|
@@ -309,11 +310,7 @@ def touch_activity(argv: list[str] | None = None) -> int:
|
|
|
309
310
|
from swarph_cli.cell import discover_cell_in_cwd, load_cell
|
|
310
311
|
from swarph_cli.commands.watchdog import _resolve_activity_marker_path
|
|
311
312
|
|
|
312
|
-
role = (
|
|
313
|
-
os.environ.get("SWARPH_SELF")
|
|
314
|
-
or os.environ.get("SWARPH_CELL")
|
|
315
|
-
or "unidentified-cell"
|
|
316
|
-
)
|
|
313
|
+
role = identity.or_sentinel()
|
|
317
314
|
cell_marker = None
|
|
318
315
|
cell_path = discover_cell_in_cwd()
|
|
319
316
|
if cell_path is not None:
|
|
@@ -59,6 +59,7 @@ from importlib import resources
|
|
|
59
59
|
from pathlib import Path
|
|
60
60
|
from typing import Any, Optional
|
|
61
61
|
|
|
62
|
+
from swarph_cli import identity
|
|
62
63
|
from swarph_cli.cell import _atomic_write_text
|
|
63
64
|
from swarph_cli.commands.hook_interpreter import hook_interpreter, refuse_unless_importable
|
|
64
65
|
from swarph_cli.commands.install_wake_hook import _detect_harness
|
|
@@ -392,8 +393,7 @@ def run_install_postcompact_hook(argv: Optional[list[str]] = None) -> int:
|
|
|
392
393
|
)
|
|
393
394
|
return 2
|
|
394
395
|
|
|
395
|
-
cell = args.cell
|
|
396
|
-
or os.environ.get("SWARPH_CELL") or None
|
|
396
|
+
cell = identity.declared(args.cell)[0]
|
|
397
397
|
memory_dir: Optional[Path] = None
|
|
398
398
|
if args.memory_dir:
|
|
399
399
|
memory_dir = Path(os.path.expanduser(args.memory_dir))
|
|
@@ -39,6 +39,7 @@ import os
|
|
|
39
39
|
import urllib.error
|
|
40
40
|
import urllib.request
|
|
41
41
|
|
|
42
|
+
from swarph_cli import identity
|
|
42
43
|
from swarph_cli.commands import add
|
|
43
44
|
from swarph_cli.commands import codegraph
|
|
44
45
|
from swarph_cli.commands import brain_ask, memory, timeline
|
|
@@ -152,7 +153,7 @@ def _codegraph_query(query: str, *, limit: int = 8) -> list[dict]:
|
|
|
152
153
|
"""Structural code search over the local codegraph index (Task 1).
|
|
153
154
|
|
|
154
155
|
Delegates to :func:`codegraph.structural_query` against the module-level
|
|
155
|
-
``_CODEGRAPH_INDEX`` path, using ``SWARPH_CELL
|
|
156
|
+
``_CODEGRAPH_INDEX`` path, using the house identity order (``SWARPH_SELF``, then ``SWARPH_CELL``; else
|
|
156
157
|
``codegraph.require_caller_cell``, which REFUSES rather than defaulting) as
|
|
157
158
|
the A8 caller identity and the
|
|
158
159
|
default operate-what-you-own allowlist (``allowlist=None``).
|
|
@@ -170,8 +171,10 @@ def _codegraph_query(query: str, *, limit: int = 8) -> list[dict]:
|
|
|
170
171
|
# authority. require_caller_cell raises IdentityNotDeclared, which the
|
|
171
172
|
# NEVER-RAISES contract below turns into an empty result — FAIL-CLOSED: the
|
|
172
173
|
# MCP host gets nothing rather than somebody else's answer.
|
|
173
|
-
|
|
174
|
-
|
|
174
|
+
# card #402: SWARPH_CELL used to be passed as the EXPLICIT identity here,
|
|
175
|
+
# so it outranked SWARPH_SELF, the CELL-first order #538 measured posting
|
|
176
|
+
# under another cell's name. The house order now decides.
|
|
177
|
+
caller_cell = codegraph.require_caller_cell(None, verb="mcp codegraph_query")
|
|
175
178
|
rows = codegraph.structural_query(
|
|
176
179
|
query,
|
|
177
180
|
index_path=_CODEGRAPH_INDEX,
|
|
@@ -85,6 +85,11 @@ def _via_gateway(op: str, arguments: dict):
|
|
|
85
85
|
if not gw:
|
|
86
86
|
return False, None
|
|
87
87
|
self_name = brain_ask._self_name()
|
|
88
|
+
if self_name is None:
|
|
89
|
+
# card #402: no default identity, so no peer token to present. OSError keeps
|
|
90
|
+
# run_memory's CLI fail-safe; the text names the variable to set.
|
|
91
|
+
raise OSError("SWARPH_BRAIN_GATEWAY is set but no cell identity is declared, "
|
|
92
|
+
"so there is no peer token to present (set SWARPH_SELF)")
|
|
88
93
|
peer_token = brain_ask._peer_token_path(self_name).read_text(encoding="utf-8").strip()
|
|
89
94
|
return True, _gateway_call(gw, peer_token, op, arguments)
|
|
90
95
|
|
|
@@ -36,6 +36,7 @@ import tempfile
|
|
|
36
36
|
from pathlib import Path
|
|
37
37
|
from typing import Optional
|
|
38
38
|
|
|
39
|
+
from swarph_cli import identity
|
|
39
40
|
from swarph_cli.commands.highlight import _log_via_gateway, _resolve_gateway
|
|
40
41
|
|
|
41
42
|
_SUPPRESS_WINDOW = dt.timedelta(minutes=30)
|
|
@@ -137,8 +138,14 @@ def _cell() -> str:
|
|
|
137
138
|
# leaks SWARPH_CELL from the spawning environment, so a CELL-first order
|
|
138
139
|
# posts this cell's highlight under ANOTHER cell's name and token
|
|
139
140
|
# (measured by cursor-win on the Windows membrane, 2026-08-22).
|
|
140
|
-
return (
|
|
141
|
-
|
|
141
|
+
return _cell_with_source()[0]
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
def _cell_with_source() -> tuple:
|
|
145
|
+
name, source = identity.declared()
|
|
146
|
+
if name is not None:
|
|
147
|
+
return name, source
|
|
148
|
+
return socket.gethostname(), "hostname"
|
|
142
149
|
|
|
143
150
|
|
|
144
151
|
def run_memory_emit_hook(argv: list[str] | None = None) -> int:
|
|
@@ -167,7 +174,9 @@ def run_memory_emit_hook(argv: list[str] | None = None) -> int:
|
|
|
167
174
|
gateway = _resolve_gateway(None)
|
|
168
175
|
if not gateway:
|
|
169
176
|
return 0 # no gateway configured -> nowhere to emit; silent by design
|
|
170
|
-
|
|
177
|
+
cell, cell_source = _cell_with_source()
|
|
178
|
+
rc = _log_via_gateway(gateway, cell, text, f"[[{slug}]]", None, None,
|
|
179
|
+
cell_source=cell_source)
|
|
171
180
|
if rc == 0:
|
|
172
181
|
_mark_emitted(slug)
|
|
173
182
|
except Exception:
|
|
@@ -31,6 +31,7 @@ import urllib.error
|
|
|
31
31
|
import urllib.parse
|
|
32
32
|
import uuid
|
|
33
33
|
|
|
34
|
+
from swarph_cli import identity
|
|
34
35
|
import swarph_cli
|
|
35
36
|
import urllib.request
|
|
36
37
|
from collections import deque
|
|
@@ -301,11 +302,9 @@ def _resolve_self_name(
|
|
|
301
302
|
*,
|
|
302
303
|
state_dir: Optional[Path] = None,
|
|
303
304
|
) -> str:
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
if env:
|
|
308
|
-
return env
|
|
305
|
+
name, _ = identity.declared(arg, env=identity.SELF_ONLY)
|
|
306
|
+
if name is not None:
|
|
307
|
+
return name
|
|
309
308
|
if state_dir is not None:
|
|
310
309
|
return state_dir.name
|
|
311
310
|
raise RuntimeError("cannot resolve self identity; pass --as or set SWARPH_SELF")
|
|
@@ -323,11 +322,9 @@ def _resolve_self_with_source(arg: Optional[str]) -> tuple:
|
|
|
323
322
|
Reading consumes, so an unlucky first command marks another peer's queue read,
|
|
324
323
|
silently, exit 0. Same family as board #360 (identity fails TOWARD lab-ovh).
|
|
325
324
|
"""
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
if env:
|
|
330
|
-
return env, "$SWARPH_SELF"
|
|
325
|
+
name, source = identity.declared(arg, env=identity.SELF_ONLY)
|
|
326
|
+
if name is not None:
|
|
327
|
+
return name, ("--as" if source == "flag" else source)
|
|
331
328
|
raise RuntimeError("cannot resolve self identity; pass --as or set SWARPH_SELF")
|
|
332
329
|
|
|
333
330
|
|
|
@@ -44,6 +44,7 @@ import sys
|
|
|
44
44
|
import time
|
|
45
45
|
from pathlib import Path
|
|
46
46
|
|
|
47
|
+
from swarph_cli import identity
|
|
47
48
|
from swarph_cli.gateway_default import env_gateway
|
|
48
49
|
|
|
49
50
|
from . import mesh
|
|
@@ -359,7 +360,7 @@ def _self_name_was_derived(args: argparse.Namespace) -> bool:
|
|
|
359
360
|
That is the dangerous path: `--as` and $SWARPH_SELF are deliberate, a
|
|
360
361
|
directory name is incidental.
|
|
361
362
|
"""
|
|
362
|
-
return
|
|
363
|
+
return identity.declared(args.self_name, env=identity.SELF_ONLY)[0] is None
|
|
363
364
|
|
|
364
365
|
|
|
365
366
|
def _verify_self_is_registered(self_name, gateway, token):
|
|
@@ -33,6 +33,7 @@ import urllib.request
|
|
|
33
33
|
from getpass import getpass
|
|
34
34
|
from pathlib import Path
|
|
35
35
|
from typing import Optional
|
|
36
|
+
from swarph_cli import identity
|
|
36
37
|
from swarph_cli import tokens
|
|
37
38
|
from swarph_cli.console_safe import print_safe
|
|
38
39
|
from swarph_cli.gateway_default import env_gateway, require_gateway
|
|
@@ -294,7 +295,7 @@ def _resolve_token(token_file_arg: Optional[str], *,
|
|
|
294
295
|
# Limited to "SWARPH_SELF is set", so an operator who names no cell is
|
|
295
296
|
# unaffected and #243's additivity guarantee survives for that population.
|
|
296
297
|
env_tok = os.environ.get("MESH_GATEWAY_TOKEN")
|
|
297
|
-
self_name =
|
|
298
|
+
self_name = identity.declared(env=identity.SELF_ONLY)[0] or ""
|
|
298
299
|
# Set when a per-peer credential was found but is not usable for THIS target
|
|
299
300
|
# (#467b). Distinguishes "you have the WRONG credential" from "you have NO
|
|
300
301
|
# credential" at the refusal below — two different operator problems, and
|
|
@@ -387,7 +388,7 @@ def _resolve_token(token_file_arg: Optional[str], *,
|
|
|
387
388
|
#
|
|
388
389
|
# Placed AFTER the existing two so a working operator-token setup is
|
|
389
390
|
# unchanged; this only fills the hole where the verb used to prompt.
|
|
390
|
-
self_name =
|
|
391
|
+
self_name = identity.declared(env=identity.SELF_ONLY)[0] or ""
|
|
391
392
|
if self_name:
|
|
392
393
|
peer_tok = Path.home() / ".config" / "swarph" / f"{self_name}.peer_token"
|
|
393
394
|
if peer_tok.exists():
|
|
@@ -887,7 +888,7 @@ def run_onboard(argv: list[str]) -> int:
|
|
|
887
888
|
# swarph onboard`. Defer there leaves the first cells with no
|
|
888
889
|
# credential — they cannot use the tools. Detected only when GET
|
|
889
890
|
# /peers is readable; a failed read keeps established-mesh defer.
|
|
890
|
-
cell_context =
|
|
891
|
+
cell_context = identity.declared(env=identity.SELF_ONLY)[0] == canonical
|
|
891
892
|
rstatus, rpayload = _get_json(f"{args.gateway}/peers", token)
|
|
892
893
|
bootstrap_window = _registry_is_bootstrap_window(rstatus, rpayload)
|
|
893
894
|
defer_mint = (not cell_context) and (not bootstrap_window)
|
|
@@ -33,6 +33,7 @@ import sys
|
|
|
33
33
|
from pathlib import Path
|
|
34
34
|
from typing import Any, Optional
|
|
35
35
|
|
|
36
|
+
from swarph_cli import identity
|
|
36
37
|
from swarph_cli.cell import (
|
|
37
38
|
CellError,
|
|
38
39
|
cells_dir,
|
|
@@ -187,7 +188,7 @@ def _resolve_cell(explicit: Optional[str] = None) -> tuple[Optional[str], str]:
|
|
|
187
188
|
return name, source
|
|
188
189
|
if explicit:
|
|
189
190
|
return explicit, "install-time --cell"
|
|
190
|
-
env_self =
|
|
191
|
+
env_self = identity.declared(env=identity.SELF_ONLY)[0] or ""
|
|
191
192
|
if env_self:
|
|
192
193
|
return env_self, "$SWARPH_SELF"
|
|
193
194
|
cwd_local = discover_cell_in_cwd()
|
|
@@ -77,6 +77,7 @@ import urllib.request
|
|
|
77
77
|
from datetime import datetime, timedelta, timezone
|
|
78
78
|
from pathlib import Path
|
|
79
79
|
from typing import Optional
|
|
80
|
+
from swarph_cli import identity
|
|
80
81
|
from swarph_cli.gateway_default import env_gateway
|
|
81
82
|
|
|
82
83
|
from swarph_cli.commands.mesh import _post_json
|
|
@@ -1886,6 +1887,12 @@ def run_install_service(args: argparse.Namespace) -> int:
|
|
|
1886
1887
|
"""
|
|
1887
1888
|
files = _bundled_systemd_files()
|
|
1888
1889
|
cell = args.cell
|
|
1890
|
+
if cell == identity.SENTINEL:
|
|
1891
|
+
# card #402: an install is not a turn, so there is no reason to fall back.
|
|
1892
|
+
# Units named after the sentinel would supervise nobody, permanently.
|
|
1893
|
+
print("swarph watchdog --install-service: no cell identity declared. "
|
|
1894
|
+
"Pass --cell <cell> or set SWARPH_SELF.", file=sys.stderr)
|
|
1895
|
+
return 4
|
|
1889
1896
|
|
|
1890
1897
|
# v0.10.1: units are PER-CELL — swarph-watchdog-<cell>.{service,timer} +
|
|
1891
1898
|
# /etc/default/swarph-watchdog-<cell> — so a multi-cell host runs one
|
|
@@ -2044,11 +2051,7 @@ def _build_parser() -> argparse.ArgumentParser:
|
|
|
2044
2051
|
)
|
|
2045
2052
|
p.add_argument(
|
|
2046
2053
|
"--cell",
|
|
2047
|
-
default=(
|
|
2048
|
-
os.environ.get("SWARPH_SELF")
|
|
2049
|
-
or os.environ.get("SWARPH_CELL")
|
|
2050
|
-
or "unidentified-cell"
|
|
2051
|
-
),
|
|
2054
|
+
default=identity.or_sentinel(),
|
|
2052
2055
|
)
|
|
2053
2056
|
p.add_argument("--cursor", default=None)
|
|
2054
2057
|
p.add_argument(
|
|
@@ -1076,6 +1076,17 @@ async def peers_register(req: PeerRegisterRequest,
|
|
|
1076
1076
|
name. capabilities dict is the JSON snapshot from claude-service /health.
|
|
1077
1077
|
"""
|
|
1078
1078
|
ctx = _authorize(authorization)
|
|
1079
|
+
# #472: bind the caller to the name it registers. Without this, any
|
|
1080
|
+
# per-peer-authenticated caller could register ANY name and be handed a
|
|
1081
|
+
# freshly minted credential for it. Ported from the deployed gateway
|
|
1082
|
+
# (mesh-gateway #467b/#108), same field and site names so both trees'
|
|
1083
|
+
# telemetry agrees: UNCONDITIONAL (never gated on predicting whether a
|
|
1084
|
+
# mint will happen; #467b's race) and OUTSIDE the transaction below
|
|
1085
|
+
# (_check_caller_binding writes telemetry on its own connection, which
|
|
1086
|
+
# would wait out the busy timeout against a held write lock; #108).
|
|
1087
|
+
# The shared token stays unbound (C2's documented no-op; closure is C5).
|
|
1088
|
+
_check_caller_binding(ctx, req.name, field="register_mint_target",
|
|
1089
|
+
site="peers_register_mint")
|
|
1079
1090
|
# B2 owner-stamping (META_EDGE_IDENTITY_CONTRACT.md §Cell-join). A Meta-Edge
|
|
1080
1091
|
# principal ties the registered cell to its owner (the node-in-your-tailnet
|
|
1081
1092
|
# relationship); lab principals (shared/commander/per-peer token) leave owner
|