agentwire-dev 1.59.0__tar.gz → 1.61.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.
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/PKG-INFO +1 -1
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/__init__.py +1 -1
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/core.py +69 -20
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/doctor_cli.py +106 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/limits_cli.py +16 -6
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/scheduler/__init__.py +4 -0
- agentwire_dev-1.61.0/agentwire/scheduler/zombie.py +160 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/server.py +10 -8
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/session_cli.py +92 -42
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/tts_cli.py +107 -14
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/tests/integration/test_worktree_cmd.py +72 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/tests/unit/test_cli_commands.py +77 -0
- agentwire_dev-1.61.0/tests/unit/test_guarded_launch_command.py +73 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/tests/unit/test_limits_tick_isolation.py +5 -2
- agentwire_dev-1.61.0/tests/unit/test_scheduler_zombie.py +269 -0
- agentwire_dev-1.61.0/tests/unit/test_session_created_by_env.py +56 -0
- agentwire_dev-1.61.0/tests/unit/test_shim_selfheal.py +202 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/.agentwire.yml.example +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/.claude/commands/handoff.md +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/.claude/skills/wiki/SKILL.md +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/.github/FUNDING.yml +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/.github/ISSUE_TEMPLATE/question.md +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/.github/workflows/pytest.yml +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/.github/workflows/ruff.yml +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/.github/workflows/security.yml +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/.github/workflows/tts-smoke.yml +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/.gitignore +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/AGENTS.md +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/CODE_OF_CONDUCT.md +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/CONTRIBUTING.md +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/Dockerfile.local +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/LICENSE +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/README.md +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/RELEASING.md +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/SECURITY.md +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/SPONSORS.md +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/__main__.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/agents/__init__.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/agents/base.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/agents/tmux.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/cached_status.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/channels/__init__.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/channels/base.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/channels/email.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/channels/push.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/channels/quo.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/channels_cli.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/chrome_tabs.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/completion.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/config.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/config_cli.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/council/__init__.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/council/cli.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/council/inbox.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/council/minutes.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/council/state.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/council/view.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/devices.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/diff_cli.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/doctor_voice.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/ensure_cli.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/fetch.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/handoff/__init__.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/handoff/git_state.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/handoff/instructions.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/handoff/parser.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/handoff/renderer.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/handoff/schema.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/handoff_cli.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/history.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/history_cli.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/hooks/__init__.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/hooks/agentwire-permission.sh +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/hooks/damage-control/__init__.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/hooks/damage-control/audit_logger.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/hooks/damage-control/bash-tool-damage-control.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/hooks/damage-control/edit-tool-damage-control.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/hooks/damage-control/mcp-tool-damage-control.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/hooks/damage-control/read-tool-damage-control.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/hooks/damage-control/rules/agentwire.yaml +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/hooks/damage-control/rules/aws.yaml +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/hooks/damage-control/rules/cloud-hosting.yaml +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/hooks/damage-control/rules/containers.yaml +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/hooks/damage-control/rules/control-plane.yaml +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/hooks/damage-control/rules/core.yaml +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/hooks/damage-control/rules/databases.yaml +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/hooks/damage-control/rules/firebase.yaml +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/hooks/damage-control/rules/gcp.yaml +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/hooks/damage-control/rules/git.yaml +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/hooks/damage-control/rules/gws.yaml +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/hooks/damage-control/rules/infrastructure.yaml +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/hooks/damage-control/rules/outbound.yaml +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/hooks/damage-control/rules/publish.yaml +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/hooks/damage-control/rules/remote.yaml +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/hooks/damage-control/write-tool-damage-control.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/hooks/idle-handler.sh +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/hooks/queue-processor.sh +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/hooks_cli.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/inbox.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/listen.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/locking.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/machine_cli.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/mcp_channels.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/mcp_chrome.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/mcp_cli.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/mcp_core.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/mcp_council.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/mcp_desktop.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/mcp_handoff.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/mcp_history.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/mcp_listen.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/mcp_lock.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/mcp_machine.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/mcp_msg.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/mcp_notify.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/mcp_pane.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/mcp_projects.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/mcp_scheduler.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/mcp_scratchpad.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/mcp_server.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/mcp_services.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/mcp_session.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/mcp_status.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/mcp_task.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/mcp_tunnels.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/mcp_voice.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/mcp_wiki.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/mcp_worktree.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/msg_cli.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/network.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/notify_cli.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/onboarding.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/palette_cli.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/pane_cli.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/pane_manager.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/portal_cli.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/project_config.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/projects.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/prompt_router.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/prompts_cli.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/push_cli.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/push_store.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/repo_cli.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/research.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/roles/__init__.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/roles/agentwire.md +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/roles/anchor.md +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/roles/chatbot.md +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/roles/contributor.md +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/roles/correspondent.md +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/roles/council-brain.md +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/roles/council-conscience.md +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/roles/council-critic.md +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/roles/council-devils-advocate.md +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/roles/council-gut.md +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/roles/council-historian.md +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/roles/council-member.md +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/roles/council-orchestrator.md +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/roles/init.md +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/roles/notifications.md +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/roles/orchestrator.md +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/roles/soul.md +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/roles/task-runner.md +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/roles/voice.md +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/roles/worker-worktree.md +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/roles/worker.md +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/roles_cli.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/routes/__init__.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/routes/artifacts.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/routes/config.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/routes/council.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/routes/desktop.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/routes/history.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/routes/machines.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/routes/notify.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/routes/palette.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/routes/permission.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/routes/projects.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/routes/push.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/routes/safety.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/routes/scheduler.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/routes/scratchpad.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/routes/sessions.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/routes/sessions_admin.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/routes/voice.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/safety/__init__.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/safety/_core.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/safety_cli.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/safety_commands.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/scheduler/dispatch.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/scheduler/gates.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/scheduler/loop.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/scheduler/models.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/scheduler/report.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/scheduler/schedule.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/scheduler/state.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/scheduler_cli.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/scratchpad.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/security.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/send_cli.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/services.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/session_context.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/session_ready.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/ssh.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/static/agentwire-splash-logo-layers--agentwire-text.png +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/static/agentwire-splash-logo-layers--echo-claw-fg.png +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/static/agentwire-splash-logo-layers--echo.png +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/static/agentwire-splash-logo-layers--telephone.png +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/static/agentwire-splash-logo-layers--tree.png +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/static/announcements.json +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/static/apple-touch-icon.png +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/static/css/desktop.css +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/static/css/mobile.css +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/static/favicon-32.png +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/static/favicon-64.png +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/static/icons/sessions/bear.webp +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/static/icons/sessions/cat.webp +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/static/icons/sessions/crown.webp +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/static/icons/sessions/custom/agentwire-portal.webp +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/static/icons/sessions/custom/agentwire-tts.webp +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/static/icons/sessions/custom/agentwire.webp +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/static/icons/sessions/deer.webp +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/static/icons/sessions/drone.webp +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/static/icons/sessions/eagle.webp +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/static/icons/sessions/fox.webp +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/static/icons/sessions/hawk.webp +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/static/icons/sessions/horse.webp +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/static/icons/sessions/lion.webp +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/static/icons/sessions/rabbit.webp +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/static/icons/sessions/robot.webp +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/static/icons/sessions/tiger.webp +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/static/icons/sessions/wolf.webp +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/static/img/icon-192.png +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/static/img/icon-512.png +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/static/js/.gitkeep +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/static/js/announcement-modal.js +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/static/js/api.js +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/static/js/artifact-window.js +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/static/js/collage.js +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/static/js/command-palette.js +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/static/js/council-window.js +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/static/js/dead-key-suppressor.js +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/static/js/desktop-manager.js +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/static/js/desktop.js +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/static/js/help-modal.js +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/static/js/icon-manager.js +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/static/js/mobile.js +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/static/js/notification-prefs.js +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/static/js/notifications-panel.js +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/static/js/ptt.js +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/static/js/push-client.js +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/static/js/review-window.js +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/static/js/safety-shared.js +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/static/js/safety-window.js +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/static/js/scratchpad.js +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/static/js/service-classification.js +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/static/js/session-id.js +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/static/js/session-window.js +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/static/js/shortcuts.js +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/static/js/sidebar/artifacts-section.js +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/static/js/sidebar/config-section.js +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/static/js/sidebar/council-section.js +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/static/js/sidebar/machines-section.js +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/static/js/sidebar/projects-section.js +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/static/js/sidebar/safety-section.js +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/static/js/sidebar/scheduler-section.js +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/static/js/sidebar/services-section.js +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/static/js/sidebar/sessions-section.js +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/static/js/sidebar.js +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/static/js/terminal-font-prefs.js +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/static/js/tile-manager.js +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/static/js/toast.js +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/static/js/token-modal.js +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/static/js/utils/ansi.js +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/static/js/utils/swipe.js +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/static/js/voice/autosend-prefs.js +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/static/js/voice/browser-stt.js +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/static/js/voice/browser-tts.js +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/static/js/voice/jargon.js +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/static/js/voice/prompt.js +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/static/js/winbox.bundle.min.js +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/static/manifest.webmanifest +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/static/service-worker.js +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/stt/__init__.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/stt/base.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/stt/cloud.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/stt/engine.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/stt/local.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/stt/server_backend.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/stt/stt_server.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/system_cli.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/tabs_cli.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/tasks.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/tasks_cli.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/templates/__init__.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/templates/base.html +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/templates/council/minutes.html.j2 +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/templates/desktop.html +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/templates/email_notification.html +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/templates/handoff/show-the-story.html.j2 +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/templates/handoff/theme.css.j2 +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/templates/mobile.html +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/templates/pair.html +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/templates/tmux.conf +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/templating.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/tooldefs/aws.yaml +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/tooldefs/docker.yaml +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/tooldefs/gcp.yaml +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/tooldefs/gh.yaml +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/tooldefs/git.yaml +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/tooldefs/gws.yaml +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/tooldefs/kubectl.yaml +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/tooldefs/npm.yaml +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/tooldefs/terraform.yaml +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/tooldefs/uv.yaml +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/tts/__init__.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/tts/audio.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/tts/base.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/tts/engines/__init__.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/tts/engines/chatterbox.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/tts/engines/kokoro.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/tts/engines/zonos.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/tts/kokoro_server.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/tts/local.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/tts/registry.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/tts_server.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/tunnels.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/tunnels_cli.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/usage_limit.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/utils/__init__.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/utils/chunker.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/utils/event_log.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/utils/file_io.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/utils/paths.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/utils/speech.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/utils/subprocess.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/validation.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/voice_status.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/wiki.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/wiki_audit.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/wiki_cli.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/worktree.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/agentwire/worktree_registry.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/docs/decisions/obsidian-second-brain.md +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/docs/logo.png +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/docs/wiki/INDEX.md +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/docs/wiki/architecture.md +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/docs/wiki/briefing-mode.md +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/docs/wiki/communication/channels.md +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/docs/wiki/communication/hammerspoon.md +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/docs/wiki/communication/handoff.md +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/docs/wiki/concepts.md +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/docs/wiki/council.md +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/docs/wiki/deployment/remote-access.md +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/docs/wiki/deployment/remote-machines.md +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/docs/wiki/glossary.md +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/docs/wiki/integrations/gws-google-workspace-cli.md +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/docs/wiki/internals/damage-control.md +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/docs/wiki/internals/parallel-refactor.md +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/docs/wiki/internals/portal.md +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/docs/wiki/internals/shell-escaping.md +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/docs/wiki/internals/troubleshooting.md +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/docs/wiki/internals/window-collage.md +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/docs/wiki/quickstart.md +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/docs/wiki/research/briefing-mode-feasibility.md +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/docs/wiki/research/orchestration-transport-alternatives.md +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/docs/wiki/scheduling/scheduled-workloads.md +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/docs/wiki/security/damage-control-hardening.md +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/docs/wiki/security/pip-audit.md +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/docs/wiki/security/remote-access-hardening.md +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/docs/wiki/security/secrets.md +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/docs/wiki/services.md +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/docs/wiki/sessions/claude-code-auto-mode.md +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/docs/wiki/sessions/messaging.md +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/docs/wiki/sessions/prompt-routing.md +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/docs/wiki/sessions/window-sizing.md +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/docs/wiki/sessions/worktree-sessions.md +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/docs/wiki/usage-limit-recovery.md +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/docs/wiki/voice/shim-contract.md +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/docs/wiki/voice/stt-cloud.md +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/docs/wiki/voice/stt-self-hosted.md +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/docs/wiki/voice/tts-self-hosted.md +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/pyproject.toml +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/tests/conftest.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/tests/e2e/test_portal_ui.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/tests/fixtures/sample_agentwire.yml +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/tests/fixtures/sample_config.yaml +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/tests/fixtures/sample_scheduler.yaml +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/tests/integration/test_council_portal.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/tests/integration/test_scheduler_board.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/tests/integration/test_send_verified_tmux.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/tests/integration/test_server_websockets.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/tests/unit/test_announcements.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/tests/unit/test_build_agent_command.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/tests/unit/test_channels.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/tests/unit/test_chrome_tabs.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/tests/unit/test_cli_output.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/tests/unit/test_cli_smoke.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/tests/unit/test_config.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/tests/unit/test_config_cli.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/tests/unit/test_control_plane_protection.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/tests/unit/test_core_created_by_rooting.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/tests/unit/test_council_cli.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/tests/unit/test_council_inbox.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/tests/unit/test_council_minutes.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/tests/unit/test_council_state.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/tests/unit/test_council_view.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/tests/unit/test_damage_control_bypass.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/tests/unit/test_damage_control_hooks.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/tests/unit/test_damage_control_sync.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/tests/unit/test_dangling_worktrees.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/tests/unit/test_devices.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/tests/unit/test_diff_cli.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/tests/unit/test_doctor_task_migration.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/tests/unit/test_doctor_voice.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/tests/unit/test_event_log.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/tests/unit/test_file_io.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/tests/unit/test_handoff_git_state.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/tests/unit/test_handoff_instructions.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/tests/unit/test_handoff_parser.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/tests/unit/test_handoff_renderer.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/tests/unit/test_history.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/tests/unit/test_hooks_install.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/tests/unit/test_idle_handler.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/tests/unit/test_idle_nag.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/tests/unit/test_inbox.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/tests/unit/test_init_command.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/tests/unit/test_install_parity.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/tests/unit/test_locking.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/tests/unit/test_mcp_server.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/tests/unit/test_mcp_tools_args.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/tests/unit/test_msg_cli.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/tests/unit/test_notify_cli.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/tests/unit/test_onboarding_reinit.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/tests/unit/test_palette_cli.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/tests/unit/test_pip_environment.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/tests/unit/test_portal_api.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/tests/unit/test_posture_default.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/tests/unit/test_project_config.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/tests/unit/test_prompt_router.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/tests/unit/test_push.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/tests/unit/test_rebuild_guard.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/tests/unit/test_repo_cli.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/tests/unit/test_roles.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/tests/unit/test_routes_snapshot.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/tests/unit/test_safety_commands.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/tests/unit/test_safety_disabled_rules.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/tests/unit/test_safety_escape_hatch.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/tests/unit/test_safety_heal.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/tests/unit/test_safety_kill_switch.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/tests/unit/test_scheduler.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/tests/unit/test_scheduler_parsing.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/tests/unit/test_scratchpad.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/tests/unit/test_security.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/tests/unit/test_server_async.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/tests/unit/test_server_pure.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/tests/unit/test_services.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/tests/unit/test_session_context.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/tests/unit/test_session_ready.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/tests/unit/test_shared_dir_guard.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/tests/unit/test_skill_install.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/tests/unit/test_speech_tags.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/tests/unit/test_ssh.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/tests/unit/test_stt_backend.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/tests/unit/test_stt_cloud.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/tests/unit/test_stt_engine.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/tests/unit/test_task_cli.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/tests/unit/test_tasks.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/tests/unit/test_tasks_cli.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/tests/unit/test_templating.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/tests/unit/test_terminal_resize.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/tests/unit/test_tmux_template.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/tests/unit/test_tts_engine_resolution.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/tests/unit/test_tts_local.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/tests/unit/test_tunnels_probe.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/tests/unit/test_unattended_env_isolation.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/tests/unit/test_usage_limit.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/tests/unit/test_validation.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/tests/unit/test_voice_status.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/tests/unit/test_wiki.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/tests/unit/test_wiki_audit.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/tests/unit/test_window_cycling_binding.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/tests/unit/test_worktree.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/tests/unit/test_worktree_branch_cleanup.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/tests/unit/test_worktree_layout.py +0 -0
- {agentwire_dev-1.59.0 → agentwire_dev-1.61.0}/tests/unit/test_worktree_registry.py +0 -0
|
@@ -148,15 +148,25 @@ def _build_tmux_env_flags_shell(env: dict[str, str]) -> str:
|
|
|
148
148
|
return " ".join(parts) + " "
|
|
149
149
|
|
|
150
150
|
|
|
151
|
-
def _set_session_name_env(agent: "AgentCommand", session_name: str) -> None:
|
|
152
|
-
"""Stamp ``AGENTWIRE_SESSION_NAME``
|
|
151
|
+
def _set_session_name_env(agent: "AgentCommand", session_name: str, created_by: str | None = None) -> None:
|
|
152
|
+
"""Stamp ``AGENTWIRE_SESSION_NAME`` (and, when there's a real parent,
|
|
153
|
+
``AGENTWIRE_CREATED_BY``) onto an ``AgentCommand.env``.
|
|
153
154
|
|
|
154
155
|
Every session created via ``cmd_new`` / ``cmd_spawn`` / ``cmd_recreate``
|
|
155
|
-
/ ``cmd_fork`` / scheduler-spawn paths gets
|
|
156
|
-
(notably the worker damage-control rules in
|
|
157
|
-
can identify which agentwire session the running
|
|
156
|
+
/ ``cmd_fork`` / scheduler-spawn paths gets ``AGENTWIRE_SESSION_NAME`` so
|
|
157
|
+
downstream tooling (notably the worker damage-control rules in
|
|
158
|
+
``safety/_core.py``) can identify which agentwire session the running
|
|
159
|
+
tool is part of.
|
|
160
|
+
|
|
161
|
+
``created_by`` of ``''`` (root/orchestrator) or ``None`` means no
|
|
162
|
+
parent — ``AGENTWIRE_CREATED_BY`` is deliberately left UNSET rather than
|
|
163
|
+
set to an empty string, so the bare pre-agent shell's launch-crash guard
|
|
164
|
+
(``_guarded_launch_command``) can tell "has a parent to escalate to"
|
|
165
|
+
apart from "root session, email the owner" with a plain ``-n`` test (#743).
|
|
158
166
|
"""
|
|
159
167
|
agent.env["AGENTWIRE_SESSION_NAME"] = session_name
|
|
168
|
+
if created_by:
|
|
169
|
+
agent.env["AGENTWIRE_CREATED_BY"] = created_by
|
|
160
170
|
|
|
161
171
|
|
|
162
172
|
def inject_session_env(session: str, env: dict[str, str], remote_host: str | None = None) -> None:
|
|
@@ -847,6 +857,52 @@ def _run_remote(machine_id: str, command: str) -> subprocess.CompletedProcess:
|
|
|
847
857
|
)
|
|
848
858
|
|
|
849
859
|
|
|
860
|
+
def _guarded_launch_command(path_str: str, agent_cmd: str | None) -> str:
|
|
861
|
+
"""Build the pane's ``cd <path> && <agent_cmd>`` line with a missing-dir guard (#739).
|
|
862
|
+
|
|
863
|
+
A crashed worktree create can leave ``path_str`` absent by the time the
|
|
864
|
+
pane actually runs its ``cd`` (race between ``agentwire new`` reporting
|
|
865
|
+
success and the async pane launch, or an external actor removing the
|
|
866
|
+
dir). Without a guard, ``cd`` fails, the shell prints an error and
|
|
867
|
+
carries on, and ``agent_cmd`` (e.g. ``claude``) then launches from the
|
|
868
|
+
WRONG cwd and crashes — dropping the pane to a bare shell that the
|
|
869
|
+
idle-reaper never touches (it only reaps a *running* agent going idle),
|
|
870
|
+
so it lingers forever.
|
|
871
|
+
|
|
872
|
+
On a missing dir this instead alerts and exits the shell, which tears the
|
|
873
|
+
tmux session down instead of leaving a zombie. ``agent_cmd`` never runs.
|
|
874
|
+
|
|
875
|
+
Two alert routes, both shell-runtime-gated on env vars stamped at launch
|
|
876
|
+
(``_set_session_name_env``), so this function stays a pure string builder
|
|
877
|
+
with no Python-level knowledge of the session's parent (#743):
|
|
878
|
+
- A real recorded parent (``$AGENTWIRE_CREATED_BY`` set) gets the crash
|
|
879
|
+
escalated to its msg inbox — in-band, not just an email the human has
|
|
880
|
+
to forward.
|
|
881
|
+
- No parent (root/orchestrator sessions, the genuine scheduler-dispatch
|
|
882
|
+
case) falls back to the original owner email, still gated on
|
|
883
|
+
``$AGENTWIRE_UNATTENDED=1`` (see ``_with_unattended_env``).
|
|
884
|
+
"""
|
|
885
|
+
quoted_path = shlex.quote(path_str)
|
|
886
|
+
session_ref = "${AGENTWIRE_SESSION_NAME:-unknown session}"
|
|
887
|
+
missing_body = f"cd failed at launch: {path_str}"
|
|
888
|
+
notify_parent = (
|
|
889
|
+
'[ -n "$AGENTWIRE_CREATED_BY" ] && agentwire msg send --to "$AGENTWIRE_CREATED_BY" '
|
|
890
|
+
f'--kind escalation --subject "agentwire: worktree missing at launch — {session_ref}" '
|
|
891
|
+
f'--body "{missing_body}" >/dev/null 2>&1'
|
|
892
|
+
)
|
|
893
|
+
notify_owner = (
|
|
894
|
+
'[ -z "$AGENTWIRE_CREATED_BY" ] && [ "$AGENTWIRE_UNATTENDED" = "1" ] && agentwire email '
|
|
895
|
+
f'--subject "agentwire: worktree missing — {session_ref}" '
|
|
896
|
+
f'--body "{missing_body}" >/dev/null 2>&1'
|
|
897
|
+
)
|
|
898
|
+
alert = (
|
|
899
|
+
f"echo \"agentwire: worktree missing at launch, aborting: {path_str}\" >&2; "
|
|
900
|
+
f"{notify_parent}; {notify_owner}"
|
|
901
|
+
)
|
|
902
|
+
guard = f"cd {quoted_path} || {{ {alert}; exit 1; }}"
|
|
903
|
+
return f"{guard} && {agent_cmd}" if agent_cmd else guard
|
|
904
|
+
|
|
905
|
+
|
|
850
906
|
def _launch_tmux_session(
|
|
851
907
|
session_name: str,
|
|
852
908
|
session_path,
|
|
@@ -859,8 +915,9 @@ def _launch_tmux_session(
|
|
|
859
915
|
The one launch sequence shared by ``new`` / ``recreate`` / ``fork`` (#630):
|
|
860
916
|
`tmux new-session -e K=V` injects *env* into the session environment
|
|
861
917
|
BEFORE the initial shell starts (post-hoc `set-environment` never reaches
|
|
862
|
-
it), then `send-keys` cd's into place
|
|
863
|
-
|
|
918
|
+
it), then `send-keys` cd's into place (guarded — see
|
|
919
|
+
``_guarded_launch_command``) and, if *agent_cmd* is non-empty, starts the
|
|
920
|
+
agent after a short settle.
|
|
864
921
|
|
|
865
922
|
Local (machine_id None): runs subprocess calls with check=True (raises on
|
|
866
923
|
tmux failure) and returns None. Remote: runs one composite shell command
|
|
@@ -869,17 +926,14 @@ def _launch_tmux_session(
|
|
|
869
926
|
import time
|
|
870
927
|
|
|
871
928
|
path_str = str(session_path)
|
|
929
|
+
launch_cmd = _guarded_launch_command(path_str, agent_cmd)
|
|
872
930
|
if machine_id:
|
|
873
931
|
env_flags = _build_tmux_env_flags_shell(env)
|
|
874
932
|
create_cmd = (
|
|
875
933
|
f"tmux new-session -d -s {shlex.quote(session_name)} -c {shlex.quote(path_str)} {env_flags}&& "
|
|
876
|
-
f"
|
|
934
|
+
f"sleep 0.1 && "
|
|
935
|
+
f"tmux send-keys -t {shlex.quote(session_name)} {shlex.quote(launch_cmd)} Enter"
|
|
877
936
|
)
|
|
878
|
-
if agent_cmd:
|
|
879
|
-
create_cmd += (
|
|
880
|
-
f" && sleep 0.1 && "
|
|
881
|
-
f"tmux send-keys -t {shlex.quote(session_name)} {shlex.quote(agent_cmd)} Enter"
|
|
882
|
-
)
|
|
883
937
|
return _run_remote(machine_id, create_cmd)
|
|
884
938
|
|
|
885
939
|
subprocess.run(
|
|
@@ -887,16 +941,11 @@ def _launch_tmux_session(
|
|
|
887
941
|
*_build_tmux_env_flags(env)],
|
|
888
942
|
check=True,
|
|
889
943
|
)
|
|
944
|
+
time.sleep(0.1)
|
|
890
945
|
subprocess.run(
|
|
891
|
-
["tmux", "send-keys", "-t", session_name,
|
|
946
|
+
["tmux", "send-keys", "-t", session_name, launch_cmd, "Enter"],
|
|
892
947
|
check=True,
|
|
893
948
|
)
|
|
894
|
-
time.sleep(0.1)
|
|
895
|
-
if agent_cmd:
|
|
896
|
-
subprocess.run(
|
|
897
|
-
["tmux", "send-keys", "-t", session_name, agent_cmd, "Enter"],
|
|
898
|
-
check=True,
|
|
899
|
-
)
|
|
900
949
|
return None
|
|
901
950
|
|
|
902
951
|
|
|
@@ -404,6 +404,77 @@ def _render_task_migration_section() -> int:
|
|
|
404
404
|
return len(unmigrated)
|
|
405
405
|
|
|
406
406
|
|
|
407
|
+
def _find_dead_managed_shims() -> list[dict]:
|
|
408
|
+
"""Managed voice shims whose tmux session is alive but ``/health`` is dead.
|
|
409
|
+
|
|
410
|
+
The #734 failure mode: a wedged Kokoro (:8102) or Moonshine STT (:8101) shim
|
|
411
|
+
inside a live ``agentwire-kokoro``/``agentwire-stt`` session — say/transcribe
|
|
412
|
+
then silently fall back to browser voice/recognition with no error, and the
|
|
413
|
+
old session-existence-only ``ensure`` never relaunches it. Only the default
|
|
414
|
+
tier runs a managed shim, so we check that tier only, and reuse the same
|
|
415
|
+
``_shim_session_state`` liveness predicate as ``start`` (SSOT).
|
|
416
|
+
"""
|
|
417
|
+
from .config import load_config as load_config_typed
|
|
418
|
+
from .core import (
|
|
419
|
+
get_kokoro_session_name,
|
|
420
|
+
get_stt_session_name,
|
|
421
|
+
tmux_session_exists,
|
|
422
|
+
)
|
|
423
|
+
from .tts_cli import _shim_session_state
|
|
424
|
+
|
|
425
|
+
cfg = load_config_typed()
|
|
426
|
+
checks: list[tuple[str, str, int, str, str]] = []
|
|
427
|
+
|
|
428
|
+
if getattr(getattr(cfg, "tts", None), "backend", "default") == "default":
|
|
429
|
+
checks.append((
|
|
430
|
+
"Kokoro TTS", get_kokoro_session_name(), 8102,
|
|
431
|
+
"agentwire kokoro start", "say falls back to browser voice",
|
|
432
|
+
))
|
|
433
|
+
|
|
434
|
+
if getattr(getattr(cfg, "stt", None), "backend", "default") == "default":
|
|
435
|
+
# Only the Moonshine path runs a shim; without it the default tier
|
|
436
|
+
# transcribes in the browser and there is nothing to probe.
|
|
437
|
+
from .stt import moonshine_importable
|
|
438
|
+
|
|
439
|
+
if moonshine_importable():
|
|
440
|
+
checks.append((
|
|
441
|
+
"Moonshine STT", get_stt_session_name(), 8101,
|
|
442
|
+
"agentwire stt start",
|
|
443
|
+
"transcription falls back to browser recognition",
|
|
444
|
+
))
|
|
445
|
+
|
|
446
|
+
dead: list[dict] = []
|
|
447
|
+
for label, session, port, fix, impact in checks:
|
|
448
|
+
if not tmux_session_exists(session):
|
|
449
|
+
continue
|
|
450
|
+
live, status = _shim_session_state(session, port)
|
|
451
|
+
if not live:
|
|
452
|
+
dead.append({
|
|
453
|
+
"label": label, "session": session, "port": port,
|
|
454
|
+
"status": status, "fix": fix, "impact": impact,
|
|
455
|
+
})
|
|
456
|
+
return dead
|
|
457
|
+
|
|
458
|
+
|
|
459
|
+
def _render_shim_liveness_section() -> int:
|
|
460
|
+
"""Doctor section: managed shim session alive but ``/health`` dead (#734)."""
|
|
461
|
+
dead = _find_dead_managed_shims()
|
|
462
|
+
if not dead:
|
|
463
|
+
print(" [ok] No dead-but-present voice shims")
|
|
464
|
+
return 0
|
|
465
|
+
for d in dead:
|
|
466
|
+
print(
|
|
467
|
+
f" [!!] {d['label']} shim session '{d['session']}' is alive but "
|
|
468
|
+
f":{d['port']}/health is not serving (state: "
|
|
469
|
+
f"{d['status'] or 'no response'}) — {d['impact']}."
|
|
470
|
+
)
|
|
471
|
+
print(
|
|
472
|
+
f" Self-heal: re-run `{dead[0]['fix']}` — it is now health-aware and "
|
|
473
|
+
"reaps a dead session before relaunching."
|
|
474
|
+
)
|
|
475
|
+
return len(dead)
|
|
476
|
+
|
|
477
|
+
|
|
407
478
|
def cmd_doctor(args) -> int:
|
|
408
479
|
"""Auto-diagnose and fix common issues."""
|
|
409
480
|
from .hooks_cli import _managed_file_state, _managed_hook_files, get_hooks_source
|
|
@@ -926,6 +997,41 @@ def cmd_doctor(args) -> int:
|
|
|
926
997
|
except Exception as e:
|
|
927
998
|
print(f" [..] Could not check project task migration: {e}")
|
|
928
999
|
|
|
1000
|
+
# 13. Managed voice shims (Kokoro :8102, Moonshine STT :8101) whose tmux
|
|
1001
|
+
# session is alive but whose /health is dead (#734). The old
|
|
1002
|
+
# session-existence-only idempotency masked a wedged engine forever, so
|
|
1003
|
+
# say/transcribe silently fell back to browser voice. Surfaced distinctly
|
|
1004
|
+
# here with the now-health-aware self-heal command.
|
|
1005
|
+
print("\nChecking managed voice shim liveness (#734)...")
|
|
1006
|
+
try:
|
|
1007
|
+
issues_found += _render_shim_liveness_section()
|
|
1008
|
+
except Exception as e:
|
|
1009
|
+
print(f" [..] Could not check managed voice shim liveness: {e}")
|
|
1010
|
+
|
|
1011
|
+
# 14. Zombie scheduler sessions (#739): a worktree dispatch whose launch
|
|
1012
|
+
# crashed before the agent started (e.g. the worktree dir went missing
|
|
1013
|
+
# between `agentwire new` reporting success and the pane's `cd`) drops to
|
|
1014
|
+
# a bare shell the idle-reaper never touches. `agentwire limits tick`
|
|
1015
|
+
# self-heals these every minute, so a live one here means the watchdog
|
|
1016
|
+
# isn't installed/running, not that reaping is broken.
|
|
1017
|
+
print("\nChecking for zombie scheduler sessions (#739)...")
|
|
1018
|
+
try:
|
|
1019
|
+
from .scheduler import scan_zombie_sessions
|
|
1020
|
+
|
|
1021
|
+
zombie_sessions = scan_zombie_sessions()
|
|
1022
|
+
if not zombie_sessions:
|
|
1023
|
+
print(" [ok] No zombie scheduler sessions found")
|
|
1024
|
+
else:
|
|
1025
|
+
issues_found += 1
|
|
1026
|
+
print(f" [!!] {len(zombie_sessions)} scheduler session(s) stuck at a bare shell:")
|
|
1027
|
+
for z in zombie_sessions:
|
|
1028
|
+
print(f" - {z['session']} ({z['command']}, {z['age_seconds']}s old)")
|
|
1029
|
+
print(" `agentwire limits tick` reaps these automatically — "
|
|
1030
|
+
"run it now, or check the usage-limit watchdog is installed "
|
|
1031
|
+
"(`agentwire limits install`).")
|
|
1032
|
+
except Exception as e:
|
|
1033
|
+
print(f" [..] Could not check for zombie scheduler sessions: {e}")
|
|
1034
|
+
|
|
929
1035
|
# Summary
|
|
930
1036
|
print()
|
|
931
1037
|
print("-" * 60)
|
|
@@ -177,16 +177,20 @@ def cmd_limits_tick(args) -> int:
|
|
|
177
177
|
"""One watchdog pass (called by launchd every minute).
|
|
178
178
|
|
|
179
179
|
Runs the usage-limit sweep FIRST, then prompt routing (#276), then the
|
|
180
|
-
polite-message inbox drain (#296), then context auto-management (#442)
|
|
181
|
-
the
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
180
|
+
polite-message inbox drain (#296), then context auto-management (#442),
|
|
181
|
+
then the zombie-scheduler-session reap (#739) — the ordering guarantees a
|
|
182
|
+
usage-limit dialog is parked before any sweep looks at the pane, that the
|
|
183
|
+
inbox only ever delivers to panes the prompt sweep already cleared, that
|
|
184
|
+
auto-``/clear`` runs before the reap so it never fights a pending
|
|
185
|
+
paste/prompt for the same idle, empty box, and that the reap runs LAST
|
|
186
|
+
since it kills sessions outright (nothing later should still be acting on
|
|
187
|
+
one).
|
|
185
188
|
|
|
186
189
|
Each stage runs inside :func:`_run_stage` so an exception in one subsystem
|
|
187
190
|
is logged and skipped rather than aborting the whole cycle (#490).
|
|
188
191
|
"""
|
|
189
192
|
from agentwire import inbox, prompt_router, session_context
|
|
193
|
+
from agentwire.scheduler import zombie as scheduler_zombie
|
|
190
194
|
|
|
191
195
|
result = _run_stage(
|
|
192
196
|
"usage_limit", usage_limit.tick,
|
|
@@ -197,9 +201,12 @@ def cmd_limits_tick(args) -> int:
|
|
|
197
201
|
"inbox", inbox.tick, {"flushed": [], "deferred": []})
|
|
198
202
|
context = _run_stage(
|
|
199
203
|
"session_context", session_context.tick, {"acted": [], "deferred": []})
|
|
204
|
+
zombies = _run_stage(
|
|
205
|
+
"scheduler_zombie", scheduler_zombie.tick, {"killed": []})
|
|
200
206
|
if getattr(args, "json", False):
|
|
201
207
|
print(json.dumps({
|
|
202
|
-
**result, "prompts": prompts, "messages": messages,
|
|
208
|
+
**result, "prompts": prompts, "messages": messages,
|
|
209
|
+
"context": context, "zombies": zombies,
|
|
203
210
|
}))
|
|
204
211
|
return 0
|
|
205
212
|
if result.get("skipped"):
|
|
@@ -237,6 +244,9 @@ def cmd_limits_tick(args) -> int:
|
|
|
237
244
|
if ctx_deferred:
|
|
238
245
|
print("context deferred: " + ", ".join(
|
|
239
246
|
f"{e['session']}({e['deferred']})" for e in ctx_deferred))
|
|
247
|
+
killed = zombies.get("killed") or []
|
|
248
|
+
if killed:
|
|
249
|
+
print("zombie scheduler sessions reaped: " + ", ".join(killed))
|
|
240
250
|
return 0
|
|
241
251
|
|
|
242
252
|
|
|
@@ -24,6 +24,7 @@ from datetime import datetime, timezone
|
|
|
24
24
|
import yaml
|
|
25
25
|
|
|
26
26
|
from ..core import _atomic_write
|
|
27
|
+
from . import zombie
|
|
27
28
|
from .dispatch import (
|
|
28
29
|
_WORKFLOW_STATUS_TO_SCHED,
|
|
29
30
|
_apply_max_runs,
|
|
@@ -110,3 +111,6 @@ from .state import (
|
|
|
110
111
|
load_board,
|
|
111
112
|
save_board,
|
|
112
113
|
)
|
|
114
|
+
from .zombie import reap as reap_zombie_sessions
|
|
115
|
+
from .zombie import scan as scan_zombie_sessions
|
|
116
|
+
from .zombie import tick as zombie_tick
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
"""Reap bare-shell scheduler sessions (#739).
|
|
2
|
+
|
|
3
|
+
``_dispatch_worktree_task`` names every worktree branch
|
|
4
|
+
``scheduler-<task>-<ts>``. If the session's launch crashes before the agent
|
|
5
|
+
starts (e.g. the worktree directory went missing between ``agentwire new``
|
|
6
|
+
reporting success and the pane's ``cd``), the tmux session drops to a bare
|
|
7
|
+
shell — which the idle-reaper correctly never touches, since it only reaps a
|
|
8
|
+
*running* agent that goes idle. Nothing else would ever clean that up, so it
|
|
9
|
+
lingers indefinitely. This module finds and kills those sessions.
|
|
10
|
+
|
|
11
|
+
Detected by branch naming rather than ``worktree_registry`` — scheduler
|
|
12
|
+
dispatch goes through ``agentwire new``, which (unlike ``agentwire
|
|
13
|
+
worktree``) never registers there.
|
|
14
|
+
"""
|
|
15
|
+
|
|
16
|
+
import subprocess
|
|
17
|
+
import time
|
|
18
|
+
|
|
19
|
+
from ..worktree import parse_session_name
|
|
20
|
+
|
|
21
|
+
BRANCH_PREFIX = "scheduler-"
|
|
22
|
+
|
|
23
|
+
# tmux `session_created` is whole seconds. A healthy launch's pre-agent shell
|
|
24
|
+
# moment lasts well under a second (see `_launch_tmux_session`'s 0.1s
|
|
25
|
+
# settle), but this gives a slow `claude` cold start real headroom before a
|
|
26
|
+
# session still mid-launch could be mistaken for a zombie.
|
|
27
|
+
MIN_AGE_SECONDS = 60
|
|
28
|
+
|
|
29
|
+
_SHELL_COMMANDS = frozenset({"zsh", "bash", "sh", "fish", "tcsh", "csh", "dash"})
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def _is_bare_shell(command: str) -> bool:
|
|
33
|
+
"""True if *command* (a ``pane_current_command`` value) is a login shell."""
|
|
34
|
+
return command.strip().lstrip("-") in _SHELL_COMMANDS
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def scan() -> list[dict]:
|
|
38
|
+
"""Live scheduler-dispatched worktree sessions stuck at a bare shell.
|
|
39
|
+
|
|
40
|
+
Each entry: ``session``, ``branch``, ``command``, ``age_seconds``.
|
|
41
|
+
"""
|
|
42
|
+
result = subprocess.run(
|
|
43
|
+
["tmux", "list-sessions", "-F", "#{session_name}\t#{session_created}"],
|
|
44
|
+
capture_output=True, text=True,
|
|
45
|
+
)
|
|
46
|
+
if result.returncode != 0:
|
|
47
|
+
return []
|
|
48
|
+
|
|
49
|
+
now = time.time()
|
|
50
|
+
zombies = []
|
|
51
|
+
for line in result.stdout.strip().splitlines():
|
|
52
|
+
if "\t" not in line:
|
|
53
|
+
continue
|
|
54
|
+
session, created = line.split("\t", 1)
|
|
55
|
+
_, branch, machine = parse_session_name(session)
|
|
56
|
+
if machine or not branch or not branch.startswith(BRANCH_PREFIX):
|
|
57
|
+
continue
|
|
58
|
+
try:
|
|
59
|
+
age = now - float(created)
|
|
60
|
+
except ValueError:
|
|
61
|
+
continue
|
|
62
|
+
if age < MIN_AGE_SECONDS:
|
|
63
|
+
continue
|
|
64
|
+
|
|
65
|
+
panes = subprocess.run(
|
|
66
|
+
["tmux", "list-panes", "-t", f"={session}", "-F", "#{pane_current_command}"],
|
|
67
|
+
capture_output=True, text=True,
|
|
68
|
+
)
|
|
69
|
+
if panes.returncode != 0:
|
|
70
|
+
continue
|
|
71
|
+
commands = [p for p in panes.stdout.strip().splitlines() if p]
|
|
72
|
+
if len(commands) == 1 and _is_bare_shell(commands[0]):
|
|
73
|
+
zombies.append({
|
|
74
|
+
"session": session, "branch": branch,
|
|
75
|
+
"command": commands[0], "age_seconds": int(age),
|
|
76
|
+
})
|
|
77
|
+
return zombies
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
def _notify(session: str, branch: str, command: str) -> None:
|
|
81
|
+
"""Alert on a reaped zombie session (#739 + #743).
|
|
82
|
+
|
|
83
|
+
Always posts a portal toast, so the reap is visible in-band rather than
|
|
84
|
+
only in an email the human has to notice and forward. When the session
|
|
85
|
+
has a recorded parent (``created_by`` in its metadata — set at
|
|
86
|
+
``agentwire new`` time, see ``_record_session_creator``), the crash is
|
|
87
|
+
ALSO escalated there via the msg inbox (drained by the same watchdog that
|
|
88
|
+
runs this reap) — a worktree worker's crash reaches its orchestrator, not
|
|
89
|
+
just the owner's inbox. Owner email — the reused Resend wiring, mirrors
|
|
90
|
+
``dispatch._notify_dispatch_timeout`` — is strictly the fallback for a
|
|
91
|
+
session with no recorded parent (the genuine root/scheduler-dispatch
|
|
92
|
+
case #739 originally covered). Each channel is independently
|
|
93
|
+
best-effort; this must never raise into the caller.
|
|
94
|
+
"""
|
|
95
|
+
text = (
|
|
96
|
+
f"agentwire: reaped zombie scheduler session `{session}` (branch "
|
|
97
|
+
f"`{branch}`) — launch crashed at a bare shell (`{command}`) before "
|
|
98
|
+
"the agent started."
|
|
99
|
+
)
|
|
100
|
+
|
|
101
|
+
try:
|
|
102
|
+
from ..core import _post_desktop_notification
|
|
103
|
+
_post_desktop_notification(text, session=session, priority="high")
|
|
104
|
+
except Exception:
|
|
105
|
+
pass
|
|
106
|
+
|
|
107
|
+
parent = None
|
|
108
|
+
try:
|
|
109
|
+
from ..core import load_session_metadata
|
|
110
|
+
parent = load_session_metadata(session).get("created_by") or None
|
|
111
|
+
except Exception:
|
|
112
|
+
parent = None
|
|
113
|
+
|
|
114
|
+
if parent:
|
|
115
|
+
try:
|
|
116
|
+
from ..inbox import enqueue
|
|
117
|
+
enqueue(parent, text, kind="escalation", sender="agentwire")
|
|
118
|
+
except Exception:
|
|
119
|
+
pass
|
|
120
|
+
return
|
|
121
|
+
|
|
122
|
+
try:
|
|
123
|
+
import socket
|
|
124
|
+
|
|
125
|
+
from ..channels.email import send_email
|
|
126
|
+
send_email(
|
|
127
|
+
subject=f"[agentwire] reaped zombie scheduler session: {session}",
|
|
128
|
+
body=(
|
|
129
|
+
f"Scheduler dispatch session `{session}` (branch `{branch}`) "
|
|
130
|
+
f"on `{socket.gethostname()}` never reached its agent — the "
|
|
131
|
+
f"pane was stuck at a bare shell (`{command}`), the #739 "
|
|
132
|
+
"failure mode where the worktree launch crashes before "
|
|
133
|
+
"`claude` starts (e.g. a missing worktree directory). The "
|
|
134
|
+
"watchdog killed the session so it can't linger.\n\n"
|
|
135
|
+
"Check the scheduler events log for the originating "
|
|
136
|
+
"dispatch failure."
|
|
137
|
+
),
|
|
138
|
+
)
|
|
139
|
+
except Exception:
|
|
140
|
+
pass
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
def reap() -> dict:
|
|
144
|
+
"""Kill every detected zombie session, logging + emailing each one."""
|
|
145
|
+
from agentwire import scheduler as _sched
|
|
146
|
+
|
|
147
|
+
killed = []
|
|
148
|
+
for z in scan():
|
|
149
|
+
_sched._kill_session(z["session"])
|
|
150
|
+
_sched._log_event("zombie_session_reaped", session=z["session"],
|
|
151
|
+
branch=z["branch"], command=z["command"],
|
|
152
|
+
age_seconds=z["age_seconds"])
|
|
153
|
+
_notify(z["session"], z["branch"], z["command"])
|
|
154
|
+
killed.append(z["session"])
|
|
155
|
+
return {"killed": killed}
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
def tick() -> dict:
|
|
159
|
+
"""Watchdog stage entry point — same ``{"killed": [...]}`` shape as ``reap()``."""
|
|
160
|
+
return reap()
|
|
@@ -387,10 +387,11 @@ class AgentWireServer(
|
|
|
387
387
|
"""Ensure the default-tier Moonshine shim subprocess is running.
|
|
388
388
|
|
|
389
389
|
Delegates to the CLI (single source of truth): ``agentwire stt start``
|
|
390
|
-
is idempotent — ``cmd_stt_start``
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
390
|
+
is idempotent and health-aware — ``cmd_stt_start`` reuses the
|
|
391
|
+
``agentwire-stt`` session only when it is actually serving, and reaps +
|
|
392
|
+
relaunches a dead-but-present one (#734), so a wedged shim self-heals on
|
|
393
|
+
the next ensure. The ~19s ONNX warm-up happens in that child process,
|
|
394
|
+
never on the portal's event loop. Mirrors ``autostart_custom_services``."""
|
|
394
395
|
await asyncio.sleep(5) # let the portal finish binding first
|
|
395
396
|
try:
|
|
396
397
|
success, result = await self.run_agentwire_cmd(["stt", "start"], json_output=False)
|
|
@@ -438,10 +439,11 @@ class AgentWireServer(
|
|
|
438
439
|
"""Ensure the default-tier Kokoro TTS shim subprocess is running.
|
|
439
440
|
|
|
440
441
|
Delegates to the CLI (single source of truth): ``agentwire kokoro start``
|
|
441
|
-
is idempotent — ``cmd_kokoro_start``
|
|
442
|
-
``agentwire-kokoro``
|
|
443
|
-
|
|
444
|
-
|
|
442
|
+
is idempotent and health-aware — ``cmd_kokoro_start`` reuses the
|
|
443
|
+
``agentwire-kokoro`` session only when it is actually serving, and reaps
|
|
444
|
+
+ relaunches a dead-but-present one (#734), so a wedged shim self-heals
|
|
445
|
+
on the next ensure. The ~200 MB download + ONNX warm-up happens in that
|
|
446
|
+
child process, never on the portal's event loop. Mirrors
|
|
445
447
|
``ensure_managed_stt``."""
|
|
446
448
|
await asyncio.sleep(5) # let the portal finish binding first
|
|
447
449
|
try:
|