swarph-cli 0.65.0__tar.gz → 0.66.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.65.0/src/swarph_cli.egg-info → swarph_cli-0.66.0}/PKG-INFO +2 -2
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/README.md +1 -1
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/pyproject.toml +1 -1
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/src/swarph_cli/__init__.py +1 -1
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/src/swarph_cli/bench/backends.py +223 -2
- swarph_cli-0.66.0/src/swarph_cli/bench/rules.py +40 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/src/swarph_cli/bench/runner.py +12 -5
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/src/swarph_cli/commands/bench.py +4 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/src/swarph_cli/commands/board.py +3 -1
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/src/swarph_cli/commands/brain_ask.py +1 -1
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/src/swarph_cli/commands/mcp_server.py +194 -15
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/src/swarph_cli/commands/monitor.py +84 -22
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/src/swarph_cli/commands/wake_hook_output.py +3 -5
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/src/swarph_cli/compress/levers.py +1 -1
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/src/swarph_cli/compress/verify.py +9 -5
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/src/swarph_cli/dreaming/candidates.py +19 -5
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/src/swarph_cli/systemd/swarph-monitor-reexec.path +5 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/src/swarph_cli/systemd/swarph-monitor-reexec.service +8 -1
- {swarph_cli-0.65.0 → swarph_cli-0.66.0/src/swarph_cli.egg-info}/PKG-INFO +2 -2
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/src/swarph_cli.egg-info/SOURCES.txt +6 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_654_reexec.py +154 -20
- swarph_cli-0.66.0/tests/test_735_dm_mcp_tools.py +173 -0
- swarph_cli-0.66.0/tests/test_941_bench_backends.py +136 -0
- swarph_cli-0.66.0/tests/test_941_harness_342.py +114 -0
- swarph_cli-0.66.0/tests/test_945_same_line_pairing.py +116 -0
- swarph_cli-0.66.0/tests/test_955_prompt_audit.py +60 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_board_command.py +13 -1
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/LICENSE +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/setup.cfg +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/src/swarph_cli/__main__.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/src/swarph_cli/bench/__init__.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/src/swarph_cli/bench/pack.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/src/swarph_cli/bench/prices.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/src/swarph_cli/bench/quality.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/src/swarph_cli/bench/refresh_prices.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/src/swarph_cli/bench/validate.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/src/swarph_cli/caller.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/src/swarph_cli/capture/__init__.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/src/swarph_cli/capture/harden.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/src/swarph_cli/capture/lineage.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/src/swarph_cli/capture/liveness.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/src/swarph_cli/capture/manifest.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/src/swarph_cli/capture/paths.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/src/swarph_cli/capture/verify.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/src/swarph_cli/cell.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/src/swarph_cli/chain_token.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/src/swarph_cli/commands/__init__.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/src/swarph_cli/commands/_content.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/src/swarph_cli/commands/_display.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/src/swarph_cli/commands/_gateway_client.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/src/swarph_cli/commands/add.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/src/swarph_cli/commands/board_merge_check.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/src/swarph_cli/commands/brain.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/src/swarph_cli/commands/cell.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/src/swarph_cli/commands/cell_probe.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/src/swarph_cli/commands/cell_selfcheck.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/src/swarph_cli/commands/channel.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/src/swarph_cli/commands/chat.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/src/swarph_cli/commands/codegraph.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/src/swarph_cli/commands/codegraph_hook.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/src/swarph_cli/commands/codex_hook_output.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/src/swarph_cli/commands/codex_waker.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/src/swarph_cli/commands/compress.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/src/swarph_cli/commands/daemon.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/src/swarph_cli/commands/dreaming.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/src/swarph_cli/commands/event.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/src/swarph_cli/commands/gateway.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/src/swarph_cli/commands/gh_route.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/src/swarph_cli/commands/group.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/src/swarph_cli/commands/guide.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/src/swarph_cli/commands/highlight.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/src/swarph_cli/commands/hook_output.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/src/swarph_cli/commands/hooks.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/src/swarph_cli/commands/import_session.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/src/swarph_cli/commands/init.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/src/swarph_cli/commands/install_codex_hooks.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/src/swarph_cli/commands/install_hook.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/src/swarph_cli/commands/install_multiplexer.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/src/swarph_cli/commands/install_opencode_plugin.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/src/swarph_cli/commands/install_postcompact_hook.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/src/swarph_cli/commands/install_wake_hook.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/src/swarph_cli/commands/lane.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/src/swarph_cli/commands/memory.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/src/swarph_cli/commands/memory_emit_hook.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/src/swarph_cli/commands/memory_sync.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/src/swarph_cli/commands/mesh.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/src/swarph_cli/commands/okf_links.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/src/swarph_cli/commands/onboard.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/src/swarph_cli/commands/peer_reply_drain.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/src/swarph_cli/commands/postcompact_hook_output.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/src/swarph_cli/commands/protocol_handler.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/src/swarph_cli/commands/ratify.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/src/swarph_cli/commands/schedule.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/src/swarph_cli/commands/security.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/src/swarph_cli/commands/service.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/src/swarph_cli/commands/spawn.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/src/swarph_cli/commands/timeline.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/src/swarph_cli/commands/version.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/src/swarph_cli/commands/watchdog.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/src/swarph_cli/compress/__init__.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/src/swarph_cli/compress/marker.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/src/swarph_cli/console_safe.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/src/swarph_cli/delivery_queue.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/src/swarph_cli/dreaming/__init__.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/src/swarph_cli/dreaming/clone.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/src/swarph_cli/dreaming/enrich.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/src/swarph_cli/dreaming/index_check.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/src/swarph_cli/dreaming/notify.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/src/swarph_cli/dreaming/organize.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/src/swarph_cli/dreaming/probes.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/src/swarph_cli/dreaming/report.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/src/swarph_cli/dreaming/run.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/src/swarph_cli/dreaming/slm.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/src/swarph_cli/dreaming/transcripts.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/src/swarph_cli/dreaming/verify.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/src/swarph_cli/gateway/__init__.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/src/swarph_cli/gateway/feature_registry.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/src/swarph_cli/gateway/lanes_control.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/src/swarph_cli/gateway/schema.sql +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/src/swarph_cli/gateway/server.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/src/swarph_cli/gateway/services_control.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/src/swarph_cli/gateway_default.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/src/swarph_cli/gh_identity.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/src/swarph_cli/guide/GUIDE.md +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/src/swarph_cli/main.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/src/swarph_cli/multiplexer.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/src/swarph_cli/orphan_daemons.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/src/swarph_cli/pane_probe.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/src/swarph_cli/parsers/__init__.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/src/swarph_cli/parsers/claude.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/src/swarph_cli/payloads/opencode/plugin.js +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/src/swarph_cli/payloads/postcompact/_shim.cmd +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/src/swarph_cli/payloads/postcompact/postcompact-recall-grok.sh +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/src/swarph_cli/payloads/postcompact/postcompact-recall.sh +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/src/swarph_cli/payloads/postcompact/posttooluse-emit-antigravity.sh +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/src/swarph_cli/payloads/postcompact/posttooluse-emit-claude.sh +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/src/swarph_cli/payloads/postcompact/posttooluse-emit-grok.sh +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/src/swarph_cli/payloads/postcompact/posttooluse-emit.sh +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/src/swarph_cli/payloads/postcompact/posttooluse-recall.sh +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/src/swarph_cli/payloads/postcompact/precompact-flag.sh +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/src/swarph_cli/payloads/postcompact/preinvocation-recall-antigravity.sh +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/src/swarph_cli/payloads/postcompact/sessionstart-recall.sh +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/src/swarph_cli/peer_executor.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/src/swarph_cli/peer_executor_windows.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/src/swarph_cli/peer_reconciliation.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/src/swarph_cli/peer_reply_outbox.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/src/swarph_cli/peer_service_host.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/src/swarph_cli/peer_service_payload.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/src/swarph_cli/peer_service_reply.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/src/swarph_cli/peer_staging.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/src/swarph_cli/query_filters.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/src/swarph_cli/scripts/__init__.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/src/swarph_cli/scripts/dm_notify_filter.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/src/swarph_cli/scripts/ensure_monitor.sh +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/src/swarph_cli/scripts/install_codex_waker_windows.ps1 +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/src/swarph_cli/scripts/install_monitor_task_windows.ps1 +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/src/swarph_cli/service/__init__.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/src/swarph_cli/service/app.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/src/swarph_cli/service/providers.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/src/swarph_cli/session_bridge.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/src/swarph_cli/skills/i-have-adhd/LICENSE +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/src/swarph_cli/skills/i-have-adhd/SKILL.md +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/src/swarph_cli/source_text.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/src/swarph_cli/stall_alert.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/src/swarph_cli/systemd/codex-waker.default +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/src/swarph_cli/systemd/peer-reply-drain.default +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/src/swarph_cli/systemd/swarph-codex-outbox@.service +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/src/swarph_cli/systemd/swarph-codex-outbox@.timer +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/src/swarph_cli/systemd/swarph-codex-waker@.service +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/src/swarph_cli/systemd/swarph-codex-waker@.timer +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/src/swarph_cli/systemd/swarph-monitor@.service +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/src/swarph_cli/systemd/swarph-peer-reply-drain@.service +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/src/swarph_cli/systemd/swarph-peer-reply-drain@.timer +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/src/swarph_cli/systemd/swarph-watchdog.default +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/src/swarph_cli/systemd/swarph-watchdog.service +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/src/swarph_cli/systemd/swarph-watchdog.timer +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/src/swarph_cli/timeline_paths.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/src/swarph_cli/tokens.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/src/swarph_cli.egg-info/dependency_links.txt +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/src/swarph_cli.egg-info/entry_points.txt +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/src/swarph_cli.egg-info/requires.txt +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/src/swarph_cli.egg-info/top_level.txt +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_124_register_merge.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_126_pending_from_complete.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_132_ensure_monitor_state_dir.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_139_tool_probe.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_183_card_anchor.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_201_win32_bash_refusal.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_243_onboard_per_peer_token.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_307_task4_ask_reply.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_312_codegraph_fuzzy_verb.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_319_refusal_exit_codes.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_323_mistral_backend.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_332_report_organize_findings.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_356_query_filters.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_397_gh_identity_router.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_397_router_preflight.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_467b_onboard_operator_credential.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_523_guide.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_524_conftest_hermeticity.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_532_accept_flag.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_535_version_capability.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_546_default_gateway.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_547_verbs_from_registry.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_548_gateway_remainder.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_552_codegraph_gateway.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_555_relay_row_shape.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_556_relay_freshness.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_564_bootstrap_first_peer.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_578_no_machine_specific_host_defaults.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_579_register_bootstrap_message.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_591_cli_step_graph.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_644_monitor_supervision.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_648_install_unit.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_656_owned_slm.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_684_dreaming_verb.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_689_pkg_version_order.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_716_timeline_one_path.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_724_ps1_ascii_or_bom.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_725_stdio_reconfigure.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_734_dreaming_enrich_degrade.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_740_edit_project.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_762_cards_edit_priority.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_764_enrich_collapse.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_801_confirm_flow_cli.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_802_stage_history.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_825_codegraph_hook_noise.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_825_remaining_cap_shred_bind.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_829_counterfactual_column.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_830_hook_binding_version.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_84_cli_labels.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_866_doctrine_guide.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_872_identity_refuses_not_warns.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_874_source_text.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_888_opencode_data_dir_can_fail.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_937_dreaming_notify.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_938_organize_line_limit.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_add_security_gate.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_artifact_add.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_artifact_hash.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_artifact_lib.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_artifact_mcp.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_artifact_skill.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_artifact_tool.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_artifact_uri.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_bench_backends.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_bench_command.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_bench_pack.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_bench_prices.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_bench_quality.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_bench_runner.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_bench_validate.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_board_card_thread.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_board_merge_check.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_board_obligation_close.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_brain_ask_command.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_brain_ask_env_diagnosis.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_brain_ask_identity_explicitness.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_brain_command.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_caller_meta_guard.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_capture_lineage.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_capture_liveness.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_capture_manifest.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_capture_paths.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_capture_security.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_cell_command_dispatch.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_cell_harden.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_cell_loader.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_cell_selfcheck.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_cell_verify.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_chain_token.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_channel_command.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_channel_poll_never_breaks_dms.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_channel_post.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_channel_wake_policy_filter.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_chat_command.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_claude_parser.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_claude_tmux_template.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_codegraph_caller_scope.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_codegraph_command.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_codegraph_hook.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_codegraph_mcp.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_codex_waker.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_compress_caller_convention.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_compress_command.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_compress_levers.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_compress_marker.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_compress_verify.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_console_encoding_e2e.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_content_composition.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_cursor_membrane.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_daemon_command.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_daemon_console_encoding.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_daemon_delivery.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_delivery_queue.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_display_sanitize.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_ensure_monitor_no_peer_default.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_event_emit.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_feature_to_uri.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_gateway_brain.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_gateway_client.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_gateway_command.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_gateway_message_idempotency.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_gh_route_doctor_mesh_name.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_group_command.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_guide_commands_parse.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_guide_selfcheck.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_heartbeat_check.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_highlight_command.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_hook_output.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_hooks_activity_marker.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_hooks_add.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_hooks_bundle.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_hooks_init.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_hooks_legacy_generation_removal.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_hooks_lifecycle.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_hooks_merge.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_hooks_verify.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_hooks_win32_bash_wrapper.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_hooks_win32_command_path.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_import_command.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_inbox_identity_provenance.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_init_command.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_init_provider_menu.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_install_codex_hooks.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_install_hook.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_install_multiplexer_command.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_install_postcompact_hook.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_install_wake_hook.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_lane_command.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_main.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_main_unknown_verb_guard.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_mcp_missing_hint.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_mcp_server.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_memory_command.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_memory_emit_snippet.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_memory_gateway.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_memory_sync.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_memory_sync_membrane.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_mesh_command.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_mesh_inbox_mark_read.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_mesh_inbox_sanitize.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_mesh_send_unknown_peer.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_mesh_sidecar.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_mesh_sidecar_cursor_decoupled.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_mesh_sidecar_wake_survives_read.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_meta_edge_identity.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_monitor_channel_poll.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_monitor_cli.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_monitor_daemon_collision.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_monitor_self_name_verification.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_monitor_state_split.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_multiplexer.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_muse_membrane.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_muse_own_cli.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_obligation_close_is_surfaced.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_okf_links.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_onboard_command.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_opencode_membrane.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_opencode_plugin.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_orphan_daemons.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_packaged_artifacts_exist.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_packaged_skills.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_peer_executor.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_peer_executor_windows.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_peer_reply_drain_command.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_peer_reply_drain_supervisor.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_peer_reply_outbox.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_peer_reply_transport.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_peer_service_e2e.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_peer_service_host.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_peer_service_payload.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_peer_service_reply.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_postcompact_recall.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_process_liveness.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_protocol_handler.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_providers_isolation.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_ratify_command.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_readme_claims_no_gateway_default.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_repl_caller_convention.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_schedule_command.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_schedule_create_contract.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_security.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_service_app.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_service_command.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_service_providers.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_session_bridge_inject.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_session_bridge_probe.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_session_bridge_resolve.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_session_path_role_gate.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_shipped_units_match_the_cli.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_smoke_chat.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_smoke_one_shot.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_smoke_phase_5_5.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_spawn_base_hoist.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_spawn_command.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_spawn_identity_stamp.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_spawn_live_pin.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_spawn_mitosis_lineage.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_spawn_tmux_session.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_spawn_windows_relaunch.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_stall_alert.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_subprocess_decode_encoding.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_timeline_command.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_tmux_wake_runstate_defer.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_tmux_wake_session_reanchor.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_tmux_wake_stale.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_tmux_wake_submit_verify.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_token_file_one_parser.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_token_precedence_explicit_first.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_unified_token_resolver.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_version_command.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_version_consistency.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_vibe_membrane.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_watchdog.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_watchdog_dm_wake.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_watchdog_dm_wake_cooldown.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_watchdog_dm_wake_wiring.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_watchdog_emit_health.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_watchdog_install_flags.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_watchdog_model_rung.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.0}/tests/test_watchdog_stale_peers.py +0 -0
- {swarph_cli-0.65.0 → swarph_cli-0.66.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.66.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
|
|
@@ -347,7 +347,7 @@ $ swarph codegraph "cron expression validator" --json --limit 5
|
|
|
347
347
|
|
|
348
348
|
It queries a locally-built index at `~/.swarph/codegraph/index.db` (override with `--index` or `SWARPH_CODEGRAPH_INDEX`); the index is built out-of-band from your repos (tree-sitter → SQLite FTS5, BM25-ranked). If no index is present the verb simply returns no matches — it never touches the network and never reads code it wasn't pointed at. Results are scoped by an owner-allowlist gate (`--caller-cell` / `SWARPH_CELL`, default: your cell): public repos are always visible; private repos are visible to the owning cell.
|
|
349
349
|
|
|
350
|
-
The same capability is exposed as an **MCP tool** — running `swarph mcp-server` publishes `swarph_codegraph_query` alongside `swarph_search`/`swarph_add`/`swarph_describe`, so any MCP host's agent auto-discovers it and can reach for code-structure lookups while reading, writing, or debugging code. (Why a tool and not an always-on retrieval lane? Because *intent* to consult code structure lives with the calling agent — which already knows it's working on code — not in a similarity score.)
|
|
350
|
+
The same capability is exposed as an **MCP tool** — running `swarph mcp-server` publishes `swarph_codegraph_query` alongside `swarph_search`/`swarph_add`/`swarph_describe` (and the mesh DM tools `swarph_dm_unread`, which returns every unread DM with full bodies in one call without marking them read; `swarph_dm_reply`, which replies by message id and marks that message read; and `swarph_dm_thread`, which returns a DM's whole conversation), so any MCP host's agent auto-discovers it and can reach for code-structure lookups while reading, writing, or debugging code. (Why a tool and not an always-on retrieval lane? Because *intent* to consult code structure lives with the calling agent — which already knows it's working on code — not in a similarity score.)
|
|
351
351
|
|
|
352
352
|
### `swarph gateway`
|
|
353
353
|
|
|
@@ -299,7 +299,7 @@ $ swarph codegraph "cron expression validator" --json --limit 5
|
|
|
299
299
|
|
|
300
300
|
It queries a locally-built index at `~/.swarph/codegraph/index.db` (override with `--index` or `SWARPH_CODEGRAPH_INDEX`); the index is built out-of-band from your repos (tree-sitter → SQLite FTS5, BM25-ranked). If no index is present the verb simply returns no matches — it never touches the network and never reads code it wasn't pointed at. Results are scoped by an owner-allowlist gate (`--caller-cell` / `SWARPH_CELL`, default: your cell): public repos are always visible; private repos are visible to the owning cell.
|
|
301
301
|
|
|
302
|
-
The same capability is exposed as an **MCP tool** — running `swarph mcp-server` publishes `swarph_codegraph_query` alongside `swarph_search`/`swarph_add`/`swarph_describe`, so any MCP host's agent auto-discovers it and can reach for code-structure lookups while reading, writing, or debugging code. (Why a tool and not an always-on retrieval lane? Because *intent* to consult code structure lives with the calling agent — which already knows it's working on code — not in a similarity score.)
|
|
302
|
+
The same capability is exposed as an **MCP tool** — running `swarph mcp-server` publishes `swarph_codegraph_query` alongside `swarph_search`/`swarph_add`/`swarph_describe` (and the mesh DM tools `swarph_dm_unread`, which returns every unread DM with full bodies in one call without marking them read; `swarph_dm_reply`, which replies by message id and marks that message read; and `swarph_dm_thread`, which returns a DM's whole conversation), so any MCP host's agent auto-discovers it and can reach for code-structure lookups while reading, writing, or debugging code. (Why a tool and not an always-on retrieval lane? Because *intent* to consult code structure lives with the calling agent — which already knows it's working on code — not in a similarity score.)
|
|
303
303
|
|
|
304
304
|
### `swarph gateway`
|
|
305
305
|
|
|
@@ -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.66.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" }
|
|
@@ -7,7 +7,7 @@ thought / out, latency, text, whether tokens are ESTIMATED). ``system``
|
|
|
7
7
|
threads to every backend (metered: ``system_instruction``; a CLI-shelling
|
|
8
8
|
backend would prepend it — see :class:`SubscriptionBackend`).
|
|
9
9
|
|
|
10
|
-
Ships
|
|
10
|
+
Ships these backends:
|
|
11
11
|
|
|
12
12
|
- :class:`MeteredGeminiBackend` — google-genai Developer API, DEFAULT for v1
|
|
13
13
|
(real ``usage_metadata``: prompt/candidates/thoughts tokens). CRITICAL:
|
|
@@ -19,13 +19,21 @@ Ships two backends:
|
|
|
19
19
|
NOT couple to any specific subscription lane map; a caller wires an actual
|
|
20
20
|
$0 CLI/OIDC path in by passing ``call_fn``. Not exercised against a live
|
|
21
21
|
provider anywhere in this package.
|
|
22
|
+
- :class:`RuleBackend` — in-process ``rule:<module:callable>``. No credentials.
|
|
23
|
+
- :class:`TypedHttpBackend` — POST to a Jev-compatible ``/v1/systemone``
|
|
24
|
+
(laya-serve). No credentials; per-item latency is the HTTP round trip.
|
|
22
25
|
"""
|
|
23
26
|
from __future__ import annotations
|
|
24
27
|
|
|
28
|
+
import importlib
|
|
29
|
+
import inspect
|
|
30
|
+
import json
|
|
25
31
|
import os
|
|
26
32
|
import time
|
|
33
|
+
import urllib.error
|
|
34
|
+
import urllib.request
|
|
27
35
|
from dataclasses import dataclass
|
|
28
|
-
from typing import Callable, Optional, Protocol
|
|
36
|
+
from typing import Any, Callable, Optional, Protocol
|
|
29
37
|
|
|
30
38
|
|
|
31
39
|
@dataclass
|
|
@@ -275,3 +283,216 @@ class SubscriptionBackend:
|
|
|
275
283
|
latency_s=latency_s,
|
|
276
284
|
estimated=True,
|
|
277
285
|
)
|
|
286
|
+
|
|
287
|
+
|
|
288
|
+
def _load_rule(spec: str) -> Callable[..., Any]:
|
|
289
|
+
"""``module:callable`` -> the callable. The module path uses dots; the
|
|
290
|
+
callable name is the segment after the last colon."""
|
|
291
|
+
mod_name, sep, fn_name = spec.rpartition(":")
|
|
292
|
+
if not sep or not mod_name or not fn_name:
|
|
293
|
+
raise ValueError(f"rule model id must be module:callable, got {spec!r}")
|
|
294
|
+
fn = getattr(importlib.import_module(mod_name), fn_name)
|
|
295
|
+
if not callable(fn):
|
|
296
|
+
raise TypeError(f"{spec} is not callable")
|
|
297
|
+
return fn
|
|
298
|
+
|
|
299
|
+
|
|
300
|
+
def _rule_subject(prompt: str) -> Any:
|
|
301
|
+
"""A JSON bench prompt is the systemone template. The rule sees its
|
|
302
|
+
``state`` (the item), not the question text. A plain prompt is unchanged.
|
|
303
|
+
"""
|
|
304
|
+
try:
|
|
305
|
+
parsed = json.loads(prompt) if isinstance(prompt, str) else None
|
|
306
|
+
except json.JSONDecodeError:
|
|
307
|
+
parsed = None
|
|
308
|
+
if isinstance(parsed, dict) and "state" in parsed:
|
|
309
|
+
return parsed["state"]
|
|
310
|
+
return prompt
|
|
311
|
+
|
|
312
|
+
|
|
313
|
+
def _call_rule(fn: Callable[..., Any], prompt: Any, system: str) -> Any:
|
|
314
|
+
params = inspect.signature(fn).parameters
|
|
315
|
+
if len(params) >= 2:
|
|
316
|
+
return fn(prompt, system)
|
|
317
|
+
return fn(prompt)
|
|
318
|
+
|
|
319
|
+
|
|
320
|
+
def _request_body(prompt: str, system: str) -> dict:
|
|
321
|
+
"""The POST body for ``/v1/systemone``.
|
|
322
|
+
|
|
323
|
+
A prompt that is itself a JSON object with ``state`` and ``questions``
|
|
324
|
+
is sent unchanged. That is how a pack carries a pre-registered template
|
|
325
|
+
(question type, instructions, criteria) without this backend inventing
|
|
326
|
+
them. Anything else is wrapped as one choice question whose instructions
|
|
327
|
+
are the prompt. That wrapper has no criteria, so a live laya-serve
|
|
328
|
+
rejects it; the gold packs must send the JSON form.
|
|
329
|
+
"""
|
|
330
|
+
try:
|
|
331
|
+
parsed = json.loads(prompt) if isinstance(prompt, str) else None
|
|
332
|
+
except json.JSONDecodeError:
|
|
333
|
+
parsed = None
|
|
334
|
+
if isinstance(parsed, dict) and "state" in parsed and "questions" in parsed:
|
|
335
|
+
return parsed
|
|
336
|
+
return {
|
|
337
|
+
"state": {"system": system, "prompt": prompt},
|
|
338
|
+
"questions": {
|
|
339
|
+
"answer": {"type": "choice", "instructions": prompt},
|
|
340
|
+
},
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
|
|
344
|
+
def _systemone_url(model_id: str) -> str:
|
|
345
|
+
url = (model_id or "").strip()
|
|
346
|
+
if not url:
|
|
347
|
+
raise ValueError("typed-http model id is empty")
|
|
348
|
+
if url.rstrip("/").endswith("/v1/systemone"):
|
|
349
|
+
return url.rstrip("/")
|
|
350
|
+
return url.rstrip("/") + "/v1/systemone"
|
|
351
|
+
|
|
352
|
+
|
|
353
|
+
# Frozen on card #941 (lab-ovh msg 48915): the verdict uses 0.50 only.
|
|
354
|
+
_NOUL_THRESHOLD = 0.50
|
|
355
|
+
|
|
356
|
+
|
|
357
|
+
def _noul_question(body: dict) -> Optional[dict]:
|
|
358
|
+
questions = body.get("questions") if isinstance(body, dict) else None
|
|
359
|
+
if not isinstance(questions, dict):
|
|
360
|
+
return None
|
|
361
|
+
named = questions.get("answer")
|
|
362
|
+
if isinstance(named, dict) and named.get("type") == "noul":
|
|
363
|
+
return named
|
|
364
|
+
for block in questions.values():
|
|
365
|
+
if isinstance(block, dict) and block.get("type") == "noul":
|
|
366
|
+
return block
|
|
367
|
+
return None
|
|
368
|
+
|
|
369
|
+
|
|
370
|
+
def _noul_labels(question: Optional[dict]) -> tuple[str, str]:
|
|
371
|
+
"""Positive and negative labels named on the template.
|
|
372
|
+
|
|
373
|
+
``labels.true`` / ``labels.false`` when the pack set them. Otherwise the
|
|
374
|
+
frozen S1 pair YES / NO (msg 48915: P(true) >= 0.50 -> YES).
|
|
375
|
+
"""
|
|
376
|
+
labels = {}
|
|
377
|
+
if isinstance(question, dict) and isinstance(question.get("labels"), dict):
|
|
378
|
+
labels = question["labels"]
|
|
379
|
+
pos = labels.get("true")
|
|
380
|
+
neg = labels.get("false")
|
|
381
|
+
return (
|
|
382
|
+
str(pos) if pos is not None else "YES",
|
|
383
|
+
str(neg) if neg is not None else "NO",
|
|
384
|
+
)
|
|
385
|
+
|
|
386
|
+
|
|
387
|
+
def _typed_value(payload: dict, request: Optional[dict] = None) -> tuple[Any, Optional[float]]:
|
|
388
|
+
"""Pull the typed answer out of a Jev /v1/systemone response.
|
|
389
|
+
|
|
390
|
+
Prefers the question named ``answer``; otherwise the first question.
|
|
391
|
+
``choice``, ``noul``, ``yes``, then ``score``. A ``noul`` value is
|
|
392
|
+
P(true): >= 0.50 maps to the template's positive label, below that to
|
|
393
|
+
the negative. The raw probability is returned alongside the label.
|
|
394
|
+
Choice and score are returned as the server sent them.
|
|
395
|
+
"""
|
|
396
|
+
answers = payload.get("answers")
|
|
397
|
+
if not isinstance(answers, dict) or not answers:
|
|
398
|
+
raise ValueError("systemone response has no answers")
|
|
399
|
+
block = answers.get("answer")
|
|
400
|
+
if not isinstance(block, dict):
|
|
401
|
+
block = next(iter(answers.values()))
|
|
402
|
+
if not isinstance(block, dict):
|
|
403
|
+
raise ValueError("systemone answer is not an object")
|
|
404
|
+
for key in ("choice", "noul", "yes", "score"):
|
|
405
|
+
if key in block and block[key] is not None:
|
|
406
|
+
if key == "noul":
|
|
407
|
+
p_true = float(block[key])
|
|
408
|
+
pos, neg = _noul_labels(_noul_question(request or {}))
|
|
409
|
+
label = pos if p_true >= _NOUL_THRESHOLD else neg
|
|
410
|
+
return label, p_true
|
|
411
|
+
return block[key], None
|
|
412
|
+
raise ValueError("systemone answer has no choice, noul, yes, or score")
|
|
413
|
+
|
|
414
|
+
|
|
415
|
+
class RuleBackend:
|
|
416
|
+
"""In-process callable. ``model_id`` is ``module:callable``.
|
|
417
|
+
|
|
418
|
+
The callable receives ``(prompt, system)`` when it takes two arguments,
|
|
419
|
+
otherwise ``(prompt)``. A JSON prompt with ``state`` is unwrapped first:
|
|
420
|
+
the callable sees that state, not the template. Its return value is the
|
|
421
|
+
categorical label. No credentials. Latency is the call itself.
|
|
422
|
+
"""
|
|
423
|
+
|
|
424
|
+
def missing_creds(self) -> list[str]:
|
|
425
|
+
return []
|
|
426
|
+
|
|
427
|
+
def generate(self, model_id: str, prompt: str, system: str = "") -> BackendResult:
|
|
428
|
+
t0 = time.perf_counter()
|
|
429
|
+
try:
|
|
430
|
+
label = _call_rule(_load_rule(model_id), _rule_subject(prompt), system)
|
|
431
|
+
text = json.dumps({"answer": label})
|
|
432
|
+
except Exception as exc:
|
|
433
|
+
return BackendResult(
|
|
434
|
+
text="", tokens_in=0, tokens_thought=0, tokens_out=0,
|
|
435
|
+
latency_s=round(time.perf_counter() - t0, 6),
|
|
436
|
+
estimated=False, error=str(exc),
|
|
437
|
+
)
|
|
438
|
+
return BackendResult(
|
|
439
|
+
text=text,
|
|
440
|
+
tokens_in=0,
|
|
441
|
+
tokens_thought=0,
|
|
442
|
+
tokens_out=0,
|
|
443
|
+
latency_s=round(time.perf_counter() - t0, 6),
|
|
444
|
+
estimated=False,
|
|
445
|
+
)
|
|
446
|
+
|
|
447
|
+
|
|
448
|
+
class TypedHttpBackend:
|
|
449
|
+
"""POST a bench item to a Jev-compatible ``/v1/systemone`` server.
|
|
450
|
+
|
|
451
|
+
``model_id`` is the server base (``http://127.0.0.1:<port>``) or a full
|
|
452
|
+
``.../v1/systemone`` URL. A prompt that is a JSON object with ``state``
|
|
453
|
+
and ``questions`` is the POST body, unchanged — that is the pre-registered
|
|
454
|
+
template. No API key is read or sent. Latency is the round trip.
|
|
455
|
+
A ``noul`` answer is P(true): >= 0.50 becomes the template's positive
|
|
456
|
+
label and below 0.50 the negative. The raw P(true) stays in the result
|
|
457
|
+
text. Choice answers are the server's label, unthresholded.
|
|
458
|
+
"""
|
|
459
|
+
|
|
460
|
+
def missing_creds(self) -> list[str]:
|
|
461
|
+
return []
|
|
462
|
+
|
|
463
|
+
def generate(self, model_id: str, prompt: str, system: str = "") -> BackendResult:
|
|
464
|
+
t0 = time.perf_counter()
|
|
465
|
+
try:
|
|
466
|
+
endpoint = _systemone_url(model_id)
|
|
467
|
+
body = _request_body(prompt, system)
|
|
468
|
+
req = urllib.request.Request(
|
|
469
|
+
endpoint,
|
|
470
|
+
data=json.dumps(body).encode(),
|
|
471
|
+
headers={"Content-Type": "application/json"},
|
|
472
|
+
method="POST",
|
|
473
|
+
)
|
|
474
|
+
with urllib.request.urlopen(req, timeout=60) as resp:
|
|
475
|
+
raw = resp.read()
|
|
476
|
+
payload = json.loads(raw.decode() or "{}")
|
|
477
|
+
if not isinstance(payload, dict):
|
|
478
|
+
raise ValueError("systemone response is not an object")
|
|
479
|
+
label, p_true = _typed_value(payload, body)
|
|
480
|
+
rendered = {"answer": label}
|
|
481
|
+
if p_true is not None:
|
|
482
|
+
rendered["p_true"] = p_true
|
|
483
|
+
text = json.dumps(rendered)
|
|
484
|
+
usage = payload.get("usage") if isinstance(payload.get("usage"), dict) else {}
|
|
485
|
+
except Exception as exc:
|
|
486
|
+
return BackendResult(
|
|
487
|
+
text="", tokens_in=0, tokens_thought=0, tokens_out=0,
|
|
488
|
+
latency_s=round(time.perf_counter() - t0, 6),
|
|
489
|
+
estimated=False, error=str(exc),
|
|
490
|
+
)
|
|
491
|
+
return BackendResult(
|
|
492
|
+
text=text,
|
|
493
|
+
tokens_in=int(usage.get("input_tokens") or 0),
|
|
494
|
+
tokens_thought=0,
|
|
495
|
+
tokens_out=int(usage.get("output_tokens") or 0),
|
|
496
|
+
latency_s=round(time.perf_counter() - t0, 6),
|
|
497
|
+
estimated=False,
|
|
498
|
+
)
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
"""Thin adapters from the rules the mesh runs today to card #941's labels.
|
|
2
|
+
|
|
3
|
+
Frozen by lab-ovh (card #941, msg 48944). Each function calls the current
|
|
4
|
+
rule and adds no decision of its own. That message's closing line says the
|
|
5
|
+
rubric (science-claude, msg 48930) wins where the two vocabularies differ,
|
|
6
|
+
so claim/mention are returned as CLAIM/MENTION and act-now/routine as
|
|
7
|
+
ACT/ROUTINE. S1's YES/NO already matches the rubric.
|
|
8
|
+
"""
|
|
9
|
+
from __future__ import annotations
|
|
10
|
+
|
|
11
|
+
from swarph_cli.commands.codegraph_hook import prompt_has_coding_keywords
|
|
12
|
+
from swarph_cli.dreaming.verify import _is_dated_record, _is_superseded
|
|
13
|
+
from swarph_cli.scripts.dm_notify_filter import _format_dm
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def s1_code_question(state) -> str:
|
|
17
|
+
"""YES when the live codegraph gate would keep the prompt."""
|
|
18
|
+
text = state["text"] if isinstance(state, dict) else state
|
|
19
|
+
return "YES" if prompt_has_coding_keywords(text) else "NO"
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def s2_claim_vs_mention(state) -> str:
|
|
23
|
+
"""mention when the extractor found no value, or the line is superseded
|
|
24
|
+
or a dated record; otherwise claim. verify.py's current decision.
|
|
25
|
+
"""
|
|
26
|
+
text = state["text"]
|
|
27
|
+
asserted = state["asserted"]
|
|
28
|
+
mention = (
|
|
29
|
+
asserted is None
|
|
30
|
+
or _is_superseded(text)
|
|
31
|
+
or _is_dated_record(text, asserted)
|
|
32
|
+
)
|
|
33
|
+
return "MENTION" if mention else "CLAIM"
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def s3_dm_triage(state) -> str:
|
|
37
|
+
"""routine when today's notify filter would drop the DM; otherwise act-now."""
|
|
38
|
+
if _format_dm(state["dm"]) is None:
|
|
39
|
+
return "ROUTINE"
|
|
40
|
+
return "ACT"
|
|
@@ -40,11 +40,18 @@ def parse_models(arg: str) -> list[ModelSpec]:
|
|
|
40
40
|
tok = tok.strip()
|
|
41
41
|
if not tok:
|
|
42
42
|
continue
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
43
|
+
# rule:<module:callable> and typed-http:<url> carry colons in the
|
|
44
|
+
# payload, so they cannot go through the id:backend:label split.
|
|
45
|
+
for prefix, backend in (("typed-http:", "typed-http"), ("rule:", "rule")):
|
|
46
|
+
if tok.startswith(prefix):
|
|
47
|
+
specs.append(ModelSpec(id=tok[len(prefix):], backend=backend, label=tok))
|
|
48
|
+
break
|
|
49
|
+
else:
|
|
50
|
+
parts = tok.split(":")
|
|
51
|
+
mid = parts[0]
|
|
52
|
+
backend = parts[1] if len(parts) > 1 and parts[1] else "metered"
|
|
53
|
+
label = parts[2] if len(parts) > 2 and parts[2] else mid
|
|
54
|
+
specs.append(ModelSpec(id=mid, backend=backend, label=label))
|
|
48
55
|
return specs
|
|
49
56
|
|
|
50
57
|
|
|
@@ -26,7 +26,9 @@ from swarph_cli.bench.backends import (
|
|
|
26
26
|
Backend,
|
|
27
27
|
MeteredGeminiBackend,
|
|
28
28
|
MeteredMistralBackend,
|
|
29
|
+
RuleBackend,
|
|
29
30
|
SubscriptionBackend,
|
|
31
|
+
TypedHttpBackend,
|
|
30
32
|
)
|
|
31
33
|
from swarph_cli.bench.pack import PackError, load_pack, slugify_theme, validate_schema
|
|
32
34
|
from swarph_cli.bench.runner import ModelSpec, parse_models, preflight, run_pack
|
|
@@ -53,6 +55,8 @@ def _default_backends() -> dict[str, Backend]:
|
|
|
53
55
|
"metered": MeteredGeminiBackend(),
|
|
54
56
|
"mistral": MeteredMistralBackend(),
|
|
55
57
|
"subscription": SubscriptionBackend(),
|
|
58
|
+
"rule": RuleBackend(),
|
|
59
|
+
"typed-http": TypedHttpBackend(),
|
|
56
60
|
}
|
|
57
61
|
|
|
58
62
|
|
|
@@ -165,7 +165,9 @@ def _card_edit_payload(actor, title, body, *, due_at=_SENTINEL, project_id=None,
|
|
|
165
165
|
if body is not None:
|
|
166
166
|
patch["body"] = body
|
|
167
167
|
if due_at is not _SENTINEL:
|
|
168
|
-
|
|
168
|
+
# "" is the gateway's CLEAR sentinel; None means "not mentioned" and the
|
|
169
|
+
# write is skipped while the old date is echoed back (#901).
|
|
170
|
+
patch["due_at"] = _normalize_due_at(due_at) if due_at else ""
|
|
169
171
|
if project_id is not None:
|
|
170
172
|
patch["project_id"] = int(project_id) # #740: re-home; the gateway gates it (orchestrator + both owners)
|
|
171
173
|
if priority is not None:
|
|
@@ -233,7 +233,7 @@ def _synthesize(facade_url: str, facade_token: str, question: str, chunks: list)
|
|
|
233
233
|
body = {"model": os.environ.get("SWARPH_FACADE_MODEL", "claude"),
|
|
234
234
|
"messages": [{"role": "system", "content": sys_prompt},
|
|
235
235
|
{"role": "user", "content": user}],
|
|
236
|
-
|
|
236
|
+
}
|
|
237
237
|
raw = _http_post(facade_url, body, facade_token, accept="application/json")
|
|
238
238
|
doc = json.loads(raw)
|
|
239
239
|
return doc["choices"][0]["message"]["content"].strip()
|