agentwire-dev 1.58.0__tar.gz → 1.60.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.58.0 → agentwire_dev-1.60.0}/.gitignore +2 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/PKG-INFO +1 -1
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/__init__.py +1 -1
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/doctor_cli.py +140 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/server.py +10 -8
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/tasks_cli.py +88 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/tts_cli.py +107 -14
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/docs/wiki/scheduling/scheduled-workloads.md +2 -0
- agentwire_dev-1.60.0/tests/unit/test_doctor_task_migration.py +79 -0
- agentwire_dev-1.60.0/tests/unit/test_shim_selfheal.py +202 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/tests/unit/test_tasks_cli.py +81 -1
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/.agentwire.yml.example +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/.claude/commands/handoff.md +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/.claude/skills/wiki/SKILL.md +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/.github/FUNDING.yml +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/.github/ISSUE_TEMPLATE/question.md +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/.github/workflows/pytest.yml +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/.github/workflows/ruff.yml +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/.github/workflows/security.yml +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/.github/workflows/tts-smoke.yml +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/AGENTS.md +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/CODE_OF_CONDUCT.md +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/CONTRIBUTING.md +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/Dockerfile.local +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/LICENSE +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/README.md +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/RELEASING.md +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/SECURITY.md +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/SPONSORS.md +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/__main__.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/agents/__init__.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/agents/base.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/agents/tmux.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/cached_status.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/channels/__init__.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/channels/base.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/channels/email.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/channels/push.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/channels/quo.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/channels_cli.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/chrome_tabs.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/completion.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/config.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/config_cli.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/core.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/council/__init__.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/council/cli.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/council/inbox.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/council/minutes.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/council/state.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/council/view.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/devices.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/diff_cli.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/doctor_voice.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/ensure_cli.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/fetch.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/handoff/__init__.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/handoff/git_state.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/handoff/instructions.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/handoff/parser.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/handoff/renderer.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/handoff/schema.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/handoff_cli.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/history.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/history_cli.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/hooks/__init__.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/hooks/agentwire-permission.sh +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/hooks/damage-control/__init__.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/hooks/damage-control/audit_logger.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/hooks/damage-control/bash-tool-damage-control.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/hooks/damage-control/edit-tool-damage-control.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/hooks/damage-control/mcp-tool-damage-control.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/hooks/damage-control/read-tool-damage-control.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/hooks/damage-control/rules/agentwire.yaml +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/hooks/damage-control/rules/aws.yaml +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/hooks/damage-control/rules/cloud-hosting.yaml +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/hooks/damage-control/rules/containers.yaml +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/hooks/damage-control/rules/control-plane.yaml +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/hooks/damage-control/rules/core.yaml +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/hooks/damage-control/rules/databases.yaml +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/hooks/damage-control/rules/firebase.yaml +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/hooks/damage-control/rules/gcp.yaml +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/hooks/damage-control/rules/git.yaml +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/hooks/damage-control/rules/gws.yaml +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/hooks/damage-control/rules/infrastructure.yaml +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/hooks/damage-control/rules/outbound.yaml +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/hooks/damage-control/rules/publish.yaml +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/hooks/damage-control/rules/remote.yaml +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/hooks/damage-control/write-tool-damage-control.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/hooks/idle-handler.sh +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/hooks/queue-processor.sh +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/hooks_cli.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/inbox.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/limits_cli.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/listen.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/locking.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/machine_cli.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/mcp_channels.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/mcp_chrome.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/mcp_cli.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/mcp_core.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/mcp_council.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/mcp_desktop.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/mcp_handoff.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/mcp_history.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/mcp_listen.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/mcp_lock.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/mcp_machine.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/mcp_msg.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/mcp_notify.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/mcp_pane.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/mcp_projects.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/mcp_scheduler.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/mcp_scratchpad.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/mcp_server.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/mcp_services.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/mcp_session.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/mcp_status.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/mcp_task.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/mcp_tunnels.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/mcp_voice.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/mcp_wiki.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/mcp_worktree.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/msg_cli.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/network.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/notify_cli.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/onboarding.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/palette_cli.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/pane_cli.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/pane_manager.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/portal_cli.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/project_config.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/projects.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/prompt_router.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/prompts_cli.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/push_cli.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/push_store.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/repo_cli.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/research.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/roles/__init__.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/roles/agentwire.md +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/roles/anchor.md +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/roles/chatbot.md +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/roles/contributor.md +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/roles/correspondent.md +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/roles/council-brain.md +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/roles/council-conscience.md +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/roles/council-critic.md +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/roles/council-devils-advocate.md +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/roles/council-gut.md +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/roles/council-historian.md +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/roles/council-member.md +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/roles/council-orchestrator.md +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/roles/init.md +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/roles/notifications.md +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/roles/orchestrator.md +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/roles/soul.md +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/roles/task-runner.md +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/roles/voice.md +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/roles/worker-worktree.md +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/roles/worker.md +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/roles_cli.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/routes/__init__.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/routes/artifacts.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/routes/config.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/routes/council.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/routes/desktop.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/routes/history.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/routes/machines.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/routes/notify.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/routes/palette.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/routes/permission.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/routes/projects.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/routes/push.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/routes/safety.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/routes/scheduler.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/routes/scratchpad.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/routes/sessions.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/routes/sessions_admin.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/routes/voice.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/safety/__init__.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/safety/_core.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/safety_cli.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/safety_commands.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/scheduler/__init__.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/scheduler/dispatch.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/scheduler/gates.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/scheduler/loop.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/scheduler/models.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/scheduler/report.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/scheduler/schedule.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/scheduler/state.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/scheduler_cli.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/scratchpad.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/security.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/send_cli.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/services.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/session_cli.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/session_context.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/session_ready.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/ssh.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/static/agentwire-splash-logo-layers--agentwire-text.png +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/static/agentwire-splash-logo-layers--echo-claw-fg.png +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/static/agentwire-splash-logo-layers--echo.png +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/static/agentwire-splash-logo-layers--telephone.png +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/static/agentwire-splash-logo-layers--tree.png +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/static/announcements.json +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/static/apple-touch-icon.png +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/static/css/desktop.css +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/static/css/mobile.css +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/static/favicon-32.png +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/static/favicon-64.png +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/static/icons/sessions/bear.webp +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/static/icons/sessions/cat.webp +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/static/icons/sessions/crown.webp +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/static/icons/sessions/custom/agentwire-portal.webp +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/static/icons/sessions/custom/agentwire-tts.webp +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/static/icons/sessions/custom/agentwire.webp +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/static/icons/sessions/deer.webp +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/static/icons/sessions/drone.webp +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/static/icons/sessions/eagle.webp +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/static/icons/sessions/fox.webp +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/static/icons/sessions/hawk.webp +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/static/icons/sessions/horse.webp +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/static/icons/sessions/lion.webp +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/static/icons/sessions/rabbit.webp +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/static/icons/sessions/robot.webp +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/static/icons/sessions/tiger.webp +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/static/icons/sessions/wolf.webp +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/static/img/icon-192.png +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/static/img/icon-512.png +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/static/js/.gitkeep +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/static/js/announcement-modal.js +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/static/js/api.js +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/static/js/artifact-window.js +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/static/js/collage.js +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/static/js/command-palette.js +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/static/js/council-window.js +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/static/js/dead-key-suppressor.js +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/static/js/desktop-manager.js +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/static/js/desktop.js +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/static/js/help-modal.js +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/static/js/icon-manager.js +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/static/js/mobile.js +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/static/js/notification-prefs.js +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/static/js/notifications-panel.js +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/static/js/ptt.js +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/static/js/push-client.js +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/static/js/review-window.js +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/static/js/safety-shared.js +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/static/js/safety-window.js +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/static/js/scratchpad.js +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/static/js/service-classification.js +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/static/js/session-id.js +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/static/js/session-window.js +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/static/js/shortcuts.js +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/static/js/sidebar/artifacts-section.js +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/static/js/sidebar/config-section.js +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/static/js/sidebar/council-section.js +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/static/js/sidebar/machines-section.js +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/static/js/sidebar/projects-section.js +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/static/js/sidebar/safety-section.js +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/static/js/sidebar/scheduler-section.js +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/static/js/sidebar/services-section.js +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/static/js/sidebar/sessions-section.js +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/static/js/sidebar.js +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/static/js/terminal-font-prefs.js +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/static/js/tile-manager.js +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/static/js/toast.js +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/static/js/token-modal.js +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/static/js/utils/ansi.js +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/static/js/utils/swipe.js +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/static/js/voice/autosend-prefs.js +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/static/js/voice/browser-stt.js +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/static/js/voice/browser-tts.js +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/static/js/voice/jargon.js +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/static/js/voice/prompt.js +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/static/js/winbox.bundle.min.js +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/static/manifest.webmanifest +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/static/service-worker.js +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/stt/__init__.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/stt/base.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/stt/cloud.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/stt/engine.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/stt/local.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/stt/server_backend.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/stt/stt_server.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/system_cli.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/tabs_cli.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/tasks.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/templates/__init__.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/templates/base.html +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/templates/council/minutes.html.j2 +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/templates/desktop.html +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/templates/email_notification.html +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/templates/handoff/show-the-story.html.j2 +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/templates/handoff/theme.css.j2 +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/templates/mobile.html +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/templates/pair.html +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/templates/tmux.conf +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/templating.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/tooldefs/aws.yaml +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/tooldefs/docker.yaml +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/tooldefs/gcp.yaml +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/tooldefs/gh.yaml +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/tooldefs/git.yaml +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/tooldefs/gws.yaml +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/tooldefs/kubectl.yaml +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/tooldefs/npm.yaml +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/tooldefs/terraform.yaml +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/tooldefs/uv.yaml +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/tts/__init__.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/tts/audio.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/tts/base.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/tts/engines/__init__.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/tts/engines/chatterbox.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/tts/engines/kokoro.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/tts/engines/zonos.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/tts/kokoro_server.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/tts/local.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/tts/registry.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/tts_server.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/tunnels.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/tunnels_cli.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/usage_limit.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/utils/__init__.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/utils/chunker.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/utils/event_log.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/utils/file_io.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/utils/paths.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/utils/speech.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/utils/subprocess.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/validation.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/voice_status.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/wiki.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/wiki_audit.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/wiki_cli.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/worktree.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/worktree_registry.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/docs/decisions/obsidian-second-brain.md +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/docs/logo.png +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/docs/wiki/INDEX.md +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/docs/wiki/architecture.md +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/docs/wiki/briefing-mode.md +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/docs/wiki/communication/channels.md +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/docs/wiki/communication/hammerspoon.md +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/docs/wiki/communication/handoff.md +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/docs/wiki/concepts.md +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/docs/wiki/council.md +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/docs/wiki/deployment/remote-access.md +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/docs/wiki/deployment/remote-machines.md +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/docs/wiki/glossary.md +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/docs/wiki/integrations/gws-google-workspace-cli.md +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/docs/wiki/internals/damage-control.md +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/docs/wiki/internals/parallel-refactor.md +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/docs/wiki/internals/portal.md +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/docs/wiki/internals/shell-escaping.md +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/docs/wiki/internals/troubleshooting.md +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/docs/wiki/internals/window-collage.md +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/docs/wiki/quickstart.md +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/docs/wiki/research/briefing-mode-feasibility.md +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/docs/wiki/research/orchestration-transport-alternatives.md +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/docs/wiki/security/damage-control-hardening.md +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/docs/wiki/security/pip-audit.md +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/docs/wiki/security/remote-access-hardening.md +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/docs/wiki/security/secrets.md +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/docs/wiki/services.md +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/docs/wiki/sessions/claude-code-auto-mode.md +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/docs/wiki/sessions/messaging.md +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/docs/wiki/sessions/prompt-routing.md +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/docs/wiki/sessions/window-sizing.md +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/docs/wiki/sessions/worktree-sessions.md +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/docs/wiki/usage-limit-recovery.md +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/docs/wiki/voice/shim-contract.md +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/docs/wiki/voice/stt-cloud.md +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/docs/wiki/voice/stt-self-hosted.md +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/docs/wiki/voice/tts-self-hosted.md +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/pyproject.toml +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/tests/conftest.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/tests/e2e/test_portal_ui.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/tests/fixtures/sample_agentwire.yml +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/tests/fixtures/sample_config.yaml +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/tests/fixtures/sample_scheduler.yaml +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/tests/integration/test_council_portal.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/tests/integration/test_scheduler_board.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/tests/integration/test_send_verified_tmux.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/tests/integration/test_server_websockets.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/tests/integration/test_worktree_cmd.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/tests/unit/test_announcements.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/tests/unit/test_build_agent_command.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/tests/unit/test_channels.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/tests/unit/test_chrome_tabs.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/tests/unit/test_cli_commands.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/tests/unit/test_cli_output.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/tests/unit/test_cli_smoke.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/tests/unit/test_config.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/tests/unit/test_config_cli.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/tests/unit/test_control_plane_protection.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/tests/unit/test_core_created_by_rooting.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/tests/unit/test_council_cli.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/tests/unit/test_council_inbox.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/tests/unit/test_council_minutes.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/tests/unit/test_council_state.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/tests/unit/test_council_view.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/tests/unit/test_damage_control_bypass.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/tests/unit/test_damage_control_hooks.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/tests/unit/test_damage_control_sync.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/tests/unit/test_dangling_worktrees.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/tests/unit/test_devices.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/tests/unit/test_diff_cli.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/tests/unit/test_doctor_voice.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/tests/unit/test_event_log.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/tests/unit/test_file_io.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/tests/unit/test_handoff_git_state.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/tests/unit/test_handoff_instructions.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/tests/unit/test_handoff_parser.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/tests/unit/test_handoff_renderer.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/tests/unit/test_history.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/tests/unit/test_hooks_install.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/tests/unit/test_idle_handler.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/tests/unit/test_idle_nag.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/tests/unit/test_inbox.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/tests/unit/test_init_command.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/tests/unit/test_install_parity.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/tests/unit/test_limits_tick_isolation.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/tests/unit/test_locking.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/tests/unit/test_mcp_server.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/tests/unit/test_mcp_tools_args.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/tests/unit/test_msg_cli.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/tests/unit/test_notify_cli.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/tests/unit/test_onboarding_reinit.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/tests/unit/test_palette_cli.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/tests/unit/test_pip_environment.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/tests/unit/test_portal_api.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/tests/unit/test_posture_default.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/tests/unit/test_project_config.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/tests/unit/test_prompt_router.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/tests/unit/test_push.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/tests/unit/test_rebuild_guard.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/tests/unit/test_repo_cli.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/tests/unit/test_roles.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/tests/unit/test_routes_snapshot.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/tests/unit/test_safety_commands.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/tests/unit/test_safety_disabled_rules.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/tests/unit/test_safety_escape_hatch.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/tests/unit/test_safety_heal.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/tests/unit/test_safety_kill_switch.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/tests/unit/test_scheduler.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/tests/unit/test_scheduler_parsing.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/tests/unit/test_scratchpad.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/tests/unit/test_security.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/tests/unit/test_server_async.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/tests/unit/test_server_pure.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/tests/unit/test_services.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/tests/unit/test_session_context.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/tests/unit/test_session_ready.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/tests/unit/test_shared_dir_guard.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/tests/unit/test_skill_install.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/tests/unit/test_speech_tags.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/tests/unit/test_ssh.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/tests/unit/test_stt_backend.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/tests/unit/test_stt_cloud.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/tests/unit/test_stt_engine.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/tests/unit/test_task_cli.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/tests/unit/test_tasks.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/tests/unit/test_templating.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/tests/unit/test_terminal_resize.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/tests/unit/test_tmux_template.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/tests/unit/test_tts_engine_resolution.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/tests/unit/test_tts_local.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/tests/unit/test_tunnels_probe.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/tests/unit/test_unattended_env_isolation.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/tests/unit/test_usage_limit.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/tests/unit/test_validation.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/tests/unit/test_voice_status.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/tests/unit/test_wiki.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/tests/unit/test_wiki_audit.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/tests/unit/test_window_cycling_binding.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/tests/unit/test_worktree.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/tests/unit/test_worktree_branch_cleanup.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/tests/unit/test_worktree_layout.py +0 -0
- {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/tests/unit/test_worktree_registry.py +0 -0
|
@@ -357,6 +357,124 @@ def _render_voice_loop_section(config, ctx) -> int:
|
|
|
357
357
|
return failures
|
|
358
358
|
|
|
359
359
|
|
|
360
|
+
def _find_unmigrated_task_projects() -> list[str]:
|
|
361
|
+
"""Local projects with an inline ``.agentwire.yml`` ``tasks:`` block but no
|
|
362
|
+
promoted ``.agentwire.tasks.yml`` (#736).
|
|
363
|
+
|
|
364
|
+
This is the concrete #720/#721 regression: the task-split relocated where
|
|
365
|
+
tasks are READ from (``.agentwire.tasks.yml``) without migrating existing
|
|
366
|
+
task DATA, so these projects' scheduled/ensure tasks silently fail (exit 6)
|
|
367
|
+
while their config still *looks* task-bearing. Returns the affected project
|
|
368
|
+
names.
|
|
369
|
+
"""
|
|
370
|
+
import yaml
|
|
371
|
+
|
|
372
|
+
from . import projects as projects_mod
|
|
373
|
+
from .tasks import TASKS_FILENAME
|
|
374
|
+
|
|
375
|
+
unmigrated: list[str] = []
|
|
376
|
+
for proj in projects_mod.get_projects("local"):
|
|
377
|
+
proj_dir = Path(proj["path"])
|
|
378
|
+
cfg_file = proj_dir / ".agentwire.yml"
|
|
379
|
+
try:
|
|
380
|
+
cfg = yaml.safe_load(cfg_file.read_text()) or {}
|
|
381
|
+
except Exception:
|
|
382
|
+
continue
|
|
383
|
+
if cfg.get("tasks") and not (proj_dir / TASKS_FILENAME).exists():
|
|
384
|
+
unmigrated.append(proj["name"])
|
|
385
|
+
return unmigrated
|
|
386
|
+
|
|
387
|
+
|
|
388
|
+
def _render_task_migration_section() -> int:
|
|
389
|
+
"""Doctor section: flag projects whose inline tasks never migrated (#736)."""
|
|
390
|
+
unmigrated = _find_unmigrated_task_projects()
|
|
391
|
+
if not unmigrated:
|
|
392
|
+
print(" [ok] No projects with un-migrated inline tasks")
|
|
393
|
+
return 0
|
|
394
|
+
for name in unmigrated:
|
|
395
|
+
print(
|
|
396
|
+
f" [!!] Project {name}: tasks defined in .agentwire.yml but never "
|
|
397
|
+
"migrated to .agentwire.tasks.yml — they will NOT run under "
|
|
398
|
+
"ensure/scheduler."
|
|
399
|
+
)
|
|
400
|
+
print(
|
|
401
|
+
" Run `agentwire tasks migrate` then `agentwire tasks promote` "
|
|
402
|
+
"in each affected project."
|
|
403
|
+
)
|
|
404
|
+
return len(unmigrated)
|
|
405
|
+
|
|
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
|
+
|
|
360
478
|
def cmd_doctor(args) -> int:
|
|
361
479
|
"""Auto-diagnose and fix common issues."""
|
|
362
480
|
from .hooks_cli import _managed_file_state, _managed_hook_files, get_hooks_source
|
|
@@ -868,6 +986,28 @@ def cmd_doctor(args) -> int:
|
|
|
868
986
|
except Exception as e:
|
|
869
987
|
print(f" [..] Could not check for dangling worktree sessions: {e}")
|
|
870
988
|
|
|
989
|
+
# 12. Projects whose inline .agentwire.yml tasks were never migrated to the
|
|
990
|
+
# promoted .agentwire.tasks.yml (#736). The #720/#721 task-split moved where
|
|
991
|
+
# tasks are read from without migrating the data, so these tasks silently
|
|
992
|
+
# fail (exit 6) under ensure/scheduler — the exact regression that went
|
|
993
|
+
# undetected because nothing surfaced it. Loud here so it can't hide again.
|
|
994
|
+
print("\nChecking project task migration (#736)...")
|
|
995
|
+
try:
|
|
996
|
+
issues_found += _render_task_migration_section()
|
|
997
|
+
except Exception as e:
|
|
998
|
+
print(f" [..] Could not check project task migration: {e}")
|
|
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
|
+
|
|
871
1011
|
# Summary
|
|
872
1012
|
print()
|
|
873
1013
|
print("-" * 60)
|
|
@@ -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:
|
|
@@ -200,6 +200,80 @@ def cmd_tasks_review(args) -> int:
|
|
|
200
200
|
return 0
|
|
201
201
|
|
|
202
202
|
|
|
203
|
+
def cmd_tasks_migrate(args) -> int:
|
|
204
|
+
"""CLI command: agentwire tasks migrate [session]
|
|
205
|
+
|
|
206
|
+
One-shot data migration for the #720/#721 task-split (#736): reads the
|
|
207
|
+
inline ``tasks:`` block still living in a project's declarative
|
|
208
|
+
``.agentwire.yml`` — now dead weight, since the executor only reads
|
|
209
|
+
``.agentwire.tasks.yml`` — and STAGES it to the unprotected
|
|
210
|
+
``.agentwire.tasks.proposed.yml``. It deliberately never writes the
|
|
211
|
+
protected live ``.agentwire.tasks.yml``; that is ``promote``'s host-only
|
|
212
|
+
job. The human then runs ``agentwire tasks review`` and
|
|
213
|
+
``agentwire tasks promote``.
|
|
214
|
+
"""
|
|
215
|
+
json_mode = getattr(args, "json", False)
|
|
216
|
+
project_path = _resolve_project_path(getattr(args, "session", None))
|
|
217
|
+
|
|
218
|
+
config_path = project_path / ".agentwire.yml"
|
|
219
|
+
proposed_path = project_path / PROPOSED_TASKS_FILENAME
|
|
220
|
+
active_path = project_path / TASKS_FILENAME
|
|
221
|
+
|
|
222
|
+
if not config_path.exists():
|
|
223
|
+
return _output_result(
|
|
224
|
+
False, json_mode, f"No .agentwire.yml found in {project_path}"
|
|
225
|
+
)
|
|
226
|
+
|
|
227
|
+
data, err = _load_yaml(config_path)
|
|
228
|
+
if err:
|
|
229
|
+
return _output_result(False, json_mode, err)
|
|
230
|
+
|
|
231
|
+
tasks = data.get("tasks")
|
|
232
|
+
if not tasks:
|
|
233
|
+
return _output_result(
|
|
234
|
+
False, json_mode,
|
|
235
|
+
f"No inline 'tasks:' block in {config_path.name} — nothing to migrate.",
|
|
236
|
+
)
|
|
237
|
+
|
|
238
|
+
if active_path.exists():
|
|
239
|
+
return _output_result(
|
|
240
|
+
False, json_mode,
|
|
241
|
+
f"{active_path.name} already exists — tasks look already migrated. "
|
|
242
|
+
"Refusing to clobber the live task file; reconcile it by hand if you "
|
|
243
|
+
"really mean to re-migrate.",
|
|
244
|
+
)
|
|
245
|
+
|
|
246
|
+
overwrote = proposed_path.exists()
|
|
247
|
+
proposed_path.write_text(
|
|
248
|
+
yaml.safe_dump(
|
|
249
|
+
{"tasks": tasks}, sort_keys=False, allow_unicode=True, width=100
|
|
250
|
+
)
|
|
251
|
+
)
|
|
252
|
+
ensure_gitignored(project_path, TASKS_FILENAME, ".agentwire.tasks*.yml")
|
|
253
|
+
|
|
254
|
+
lines = [
|
|
255
|
+
f"Staged {len(tasks)} task(s) from {config_path.name} -> {proposed_path.name}"
|
|
256
|
+
]
|
|
257
|
+
if overwrote:
|
|
258
|
+
lines.append(f"(overwrote an existing {proposed_path.name})")
|
|
259
|
+
lines += [
|
|
260
|
+
"",
|
|
261
|
+
"Next:",
|
|
262
|
+
" 1. Review: agentwire tasks review",
|
|
263
|
+
" 2. Promote: agentwire tasks promote (host-only)",
|
|
264
|
+
"",
|
|
265
|
+
f"After promoting, delete the dead 'tasks:' block from {config_path.name} "
|
|
266
|
+
"— the executor ignores it.",
|
|
267
|
+
]
|
|
268
|
+
return _output_result(
|
|
269
|
+
True, json_mode, "\n".join(lines),
|
|
270
|
+
project=str(project_path),
|
|
271
|
+
proposed=str(proposed_path),
|
|
272
|
+
tasks=list(tasks),
|
|
273
|
+
overwrote=overwrote,
|
|
274
|
+
)
|
|
275
|
+
|
|
276
|
+
|
|
203
277
|
def cmd_tasks_promote(args) -> int:
|
|
204
278
|
"""CLI command: agentwire tasks promote [session] [--yes]
|
|
205
279
|
|
|
@@ -283,6 +357,20 @@ def register_tasks_parser(subparsers) -> None:
|
|
|
283
357
|
)
|
|
284
358
|
tasks_subparsers = tasks_parser.add_subparsers(dest="tasks_command")
|
|
285
359
|
|
|
360
|
+
migrate = tasks_subparsers.add_parser(
|
|
361
|
+
"migrate",
|
|
362
|
+
help="Stage a project's inline .agentwire.yml tasks: block as a draft (#736)",
|
|
363
|
+
description=(
|
|
364
|
+
"Read the inline 'tasks:' block from the project's .agentwire.yml "
|
|
365
|
+
"(dead weight since #720/#721 — the executor only reads "
|
|
366
|
+
".agentwire.tasks.yml) and stage it to .agentwire.tasks.proposed.yml. "
|
|
367
|
+
"Then run `agentwire tasks review` and `agentwire tasks promote`."
|
|
368
|
+
),
|
|
369
|
+
)
|
|
370
|
+
migrate.add_argument("session", nargs="?", help="Session name (default: current directory)")
|
|
371
|
+
migrate.add_argument("--json", action="store_true", help="Output JSON")
|
|
372
|
+
migrate.set_defaults(func=cmd_tasks_migrate)
|
|
373
|
+
|
|
286
374
|
review = tasks_subparsers.add_parser(
|
|
287
375
|
"review", help="Show the diff + every shell command in the staged draft"
|
|
288
376
|
)
|
|
@@ -459,19 +459,102 @@ def _resolve_shim_python() -> tuple[str | None, str | None, str | None]:
|
|
|
459
459
|
return sys.executable, None, None
|
|
460
460
|
|
|
461
461
|
|
|
462
|
+
# === Managed shim liveness (health-aware idempotency, #734) ===
|
|
463
|
+
#
|
|
464
|
+
# A managed voice shim (Kokoro TTS :8102, Moonshine STT :8101) runs uvicorn in
|
|
465
|
+
# a tmux session and warms its model in the background. The old start path was
|
|
466
|
+
# idempotent on *session existence* alone, so a dead/wedged process inside a
|
|
467
|
+
# live session was treated as healthy forever — say/transcribe then silently
|
|
468
|
+
# fell back to browser voice. These helpers make start/ensure health-aware:
|
|
469
|
+
# reuse a session only when it is actually serving (or too young to have bound
|
|
470
|
+
# its port yet); otherwise reap it and relaunch.
|
|
471
|
+
|
|
472
|
+
|
|
473
|
+
def _probe_shim_health(port: int, timeout: float = 2.0) -> tuple[bool, str | None]:
|
|
474
|
+
"""Probe a managed shim's ``/health`` on localhost.
|
|
475
|
+
|
|
476
|
+
Returns ``(responded, status)``: ``responded`` is True when the HTTP server
|
|
477
|
+
answered at all (even mid-warmup); ``status`` is the reported state string
|
|
478
|
+
(``ok``/``loading``/``downloading``/``absent``/``failed``/…) or None when
|
|
479
|
+
nothing answered (process dead, wedged, or the port not yet bound)."""
|
|
480
|
+
try:
|
|
481
|
+
req = urllib.request.Request(f"http://localhost:{port}/health")
|
|
482
|
+
with urllib.request.urlopen(req, timeout=timeout) as resp:
|
|
483
|
+
data = json.loads(resp.read().decode())
|
|
484
|
+
return True, data.get("status")
|
|
485
|
+
except Exception:
|
|
486
|
+
return False, None
|
|
487
|
+
|
|
488
|
+
|
|
489
|
+
def _tmux_session_age(session_name: str) -> float | None:
|
|
490
|
+
"""Seconds since the tmux session was created, or None if unknowable."""
|
|
491
|
+
import time
|
|
492
|
+
|
|
493
|
+
result = subprocess.run(
|
|
494
|
+
["tmux", "display-message", "-p", "-t", session_name, "#{session_created}"],
|
|
495
|
+
capture_output=True,
|
|
496
|
+
text=True,
|
|
497
|
+
)
|
|
498
|
+
if result.returncode != 0:
|
|
499
|
+
return None
|
|
500
|
+
try:
|
|
501
|
+
return time.time() - int(result.stdout.strip())
|
|
502
|
+
except (ValueError, TypeError):
|
|
503
|
+
return None
|
|
504
|
+
|
|
505
|
+
|
|
506
|
+
def _shim_session_state(
|
|
507
|
+
session_name: str, port: int, *, warmup_grace: float = 25.0
|
|
508
|
+
) -> tuple[bool, str | None]:
|
|
509
|
+
"""``(live, status)`` for an EXISTING managed-shim tmux session.
|
|
510
|
+
|
|
511
|
+
The single liveness predicate shared by ``start`` (reuse-vs-reap) and
|
|
512
|
+
``doctor`` (flag-a-dead-shim). A session is *live* when its ``/health``
|
|
513
|
+
answers a non-``failed`` status, OR it is younger than ``warmup_grace`` (the
|
|
514
|
+
port may not be bound yet). A process that never answers past the grace, or
|
|
515
|
+
reports a terminal ``failed``, is NOT live. ``status`` is the ``/health``
|
|
516
|
+
state, ``"starting"`` for a still-booting young session, or None for a dead
|
|
517
|
+
one — carried through for human-readable diagnostics."""
|
|
518
|
+
responded, status = _probe_shim_health(port)
|
|
519
|
+
if responded:
|
|
520
|
+
return (status != "failed", status)
|
|
521
|
+
age = _tmux_session_age(session_name)
|
|
522
|
+
if age is not None and age < warmup_grace:
|
|
523
|
+
return (True, "starting")
|
|
524
|
+
return (False, status)
|
|
525
|
+
|
|
526
|
+
|
|
527
|
+
def _reap_shim_session(session_name: str) -> None:
|
|
528
|
+
"""Kill a dead shim tmux session so a fresh one can bind the port."""
|
|
529
|
+
import time
|
|
530
|
+
|
|
531
|
+
subprocess.run(["tmux", "kill-session", "-t", session_name], capture_output=True)
|
|
532
|
+
time.sleep(0.5)
|
|
533
|
+
|
|
534
|
+
|
|
462
535
|
# === STT Commands ===
|
|
463
536
|
|
|
464
537
|
def cmd_stt_start(args) -> int:
|
|
465
538
|
"""Start the STT server in tmux."""
|
|
466
539
|
session_name = get_stt_session_name()
|
|
540
|
+
port = args.port or 8101
|
|
541
|
+
host = args.host or "0.0.0.0"
|
|
467
542
|
|
|
468
543
|
if tmux_session_exists(session_name):
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
544
|
+
live, status = _shim_session_state(session_name, port)
|
|
545
|
+
if live:
|
|
546
|
+
print(f"STT server already running in tmux session '{session_name}'")
|
|
547
|
+
print(f" Attach: tmux attach -t {session_name}")
|
|
548
|
+
return 0
|
|
549
|
+
# Session exists but :{port}/health isn't serving (dead/wedged) —
|
|
550
|
+
# self-heal by reaping and relaunching instead of masking a dead
|
|
551
|
+
# engine behind mere session existence (#734).
|
|
552
|
+
print(
|
|
553
|
+
f"STT server session '{session_name}' is present but not serving "
|
|
554
|
+
f"(state: {status or 'no response'}) — relaunching."
|
|
555
|
+
)
|
|
556
|
+
_reap_shim_session(session_name)
|
|
472
557
|
|
|
473
|
-
port = args.port or 8101
|
|
474
|
-
host = args.host or "0.0.0.0"
|
|
475
558
|
config = load_config()
|
|
476
559
|
stt_config = config.get("stt", {})
|
|
477
560
|
model = args.model or stt_config.get("model", "base")
|
|
@@ -576,21 +659,31 @@ def cmd_stt_status(args) -> int:
|
|
|
576
659
|
# === Kokoro (default-tier TTS shim) Commands ===
|
|
577
660
|
|
|
578
661
|
def cmd_kokoro_start(args) -> int:
|
|
579
|
-
"""Start the default-tier Kokoro TTS shim in tmux (idempotent).
|
|
662
|
+
"""Start the default-tier Kokoro TTS shim in tmux (idempotent, health-aware).
|
|
580
663
|
|
|
581
664
|
Mirrors ``agentwire stt start``: the portal's ``ensure_managed_tts`` calls
|
|
582
|
-
this on startup
|
|
583
|
-
|
|
665
|
+
this on startup. An existing session is reused only when it is actually
|
|
666
|
+
serving (``/health`` ok/warming); a dead-but-present session is reaped and
|
|
667
|
+
relaunched so a wedged shim self-heals instead of masking forever (#734)."""
|
|
584
668
|
session_name = get_kokoro_session_name()
|
|
585
|
-
|
|
586
|
-
if tmux_session_exists(session_name):
|
|
587
|
-
print(f"Kokoro TTS shim already running in tmux session '{session_name}'")
|
|
588
|
-
print(f" Attach: tmux attach -t {session_name}")
|
|
589
|
-
return 0
|
|
590
|
-
|
|
591
669
|
port = args.port or 8102
|
|
592
670
|
host = args.host or "0.0.0.0"
|
|
593
671
|
|
|
672
|
+
if tmux_session_exists(session_name):
|
|
673
|
+
live, status = _shim_session_state(session_name, port)
|
|
674
|
+
if live:
|
|
675
|
+
print(f"Kokoro TTS shim already running in tmux session '{session_name}'")
|
|
676
|
+
print(f" Attach: tmux attach -t {session_name}")
|
|
677
|
+
return 0
|
|
678
|
+
# Session exists but :{port}/health isn't serving (dead/wedged) —
|
|
679
|
+
# self-heal by reaping and relaunching instead of masking a dead
|
|
680
|
+
# engine behind mere session existence (#734).
|
|
681
|
+
print(
|
|
682
|
+
f"Kokoro TTS shim session '{session_name}' is present but not serving "
|
|
683
|
+
f"(state: {status or 'no response'}) — relaunching."
|
|
684
|
+
)
|
|
685
|
+
_reap_shim_session(session_name)
|
|
686
|
+
|
|
594
687
|
# Resolve an interpreter that can run the shim: dev-checkout venv when one
|
|
595
688
|
# exists, otherwise the installed package's interpreter.
|
|
596
689
|
python_path, cwd, error = _resolve_shim_python()
|
|
@@ -23,6 +23,8 @@ Define tasks in `.agentwire.tasks.yml` (a sibling of `.agentwire.yml`, split out
|
|
|
23
23
|
|
|
24
24
|
`.agentwire.tasks.yml` is **protected control-plane** — a policed agent can't write it directly. Authoring it is propose-and-promote: draft to `.agentwire.tasks.proposed.yml`, then a human runs `agentwire tasks review` and `agentwire tasks promote`. See [Damage control](../internals/damage-control.md#task-execution-config-split-agentwiretasksyml-720).
|
|
25
25
|
|
|
26
|
+
**Legacy inline tasks are dead weight (#736).** Tasks that predate the #720/#721 split still living under a `tasks:` key in `.agentwire.yml` do **not** run — the executor reads only `.agentwire.tasks.yml`, with no runtime fallback. Migrate once: `agentwire tasks migrate` stages the inline block to `.agentwire.tasks.proposed.yml`, then `agentwire tasks review` + `agentwire tasks promote` lands it; finally delete the dead `tasks:` block from `.agentwire.yml`. `agentwire doctor` flags any project still in the un-migrated state.
|
|
27
|
+
|
|
26
28
|
```yaml
|
|
27
29
|
# .agentwire.yml — declarative session config
|
|
28
30
|
posture: auto # Recommended for unattended work — see auto below
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
"""Tests for the doctor task-migration check (#736).
|
|
2
|
+
|
|
3
|
+
The #720/#721 task-split relocated where tasks are READ from
|
|
4
|
+
(.agentwire.tasks.yml) without migrating existing inline .agentwire.yml
|
|
5
|
+
`tasks:` data, so those projects' scheduled/ensure tasks silently failed
|
|
6
|
+
(exit 6). Doctor must surface exactly that state.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
import agentwire.projects as projects_mod
|
|
10
|
+
from agentwire.doctor_cli import (
|
|
11
|
+
_find_unmigrated_task_projects,
|
|
12
|
+
_render_task_migration_section,
|
|
13
|
+
)
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def _make_project(tmp_path, name, *, inline_tasks: bool, migrated: bool):
|
|
17
|
+
"""Create a fake local project dir and return its get_projects() dict."""
|
|
18
|
+
proj_dir = tmp_path / name
|
|
19
|
+
proj_dir.mkdir()
|
|
20
|
+
cfg = "posture: bypass\n"
|
|
21
|
+
if inline_tasks:
|
|
22
|
+
cfg += "tasks:\n daily:\n prompt: do the thing\n"
|
|
23
|
+
(proj_dir / ".agentwire.yml").write_text(cfg)
|
|
24
|
+
if migrated:
|
|
25
|
+
(proj_dir / ".agentwire.tasks.yml").write_text(
|
|
26
|
+
"tasks:\n daily:\n prompt: do the thing\n"
|
|
27
|
+
)
|
|
28
|
+
return {"name": name, "path": str(proj_dir), "machine": "local"}
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def _patch_projects(monkeypatch, project_dicts):
|
|
32
|
+
monkeypatch.setattr(projects_mod, "get_projects", lambda machine=None: project_dicts)
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def test_flags_unmigrated_project(tmp_path, monkeypatch):
|
|
36
|
+
p = _make_project(tmp_path, "daily-book-report", inline_tasks=True, migrated=False)
|
|
37
|
+
_patch_projects(monkeypatch, [p])
|
|
38
|
+
assert _find_unmigrated_task_projects() == ["daily-book-report"]
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def test_clean_once_migrated(tmp_path, monkeypatch):
|
|
42
|
+
p = _make_project(tmp_path, "daily-book-report", inline_tasks=True, migrated=True)
|
|
43
|
+
_patch_projects(monkeypatch, [p])
|
|
44
|
+
assert _find_unmigrated_task_projects() == []
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def test_project_without_inline_tasks_not_flagged(tmp_path, monkeypatch):
|
|
48
|
+
p = _make_project(tmp_path, "no-tasks", inline_tasks=False, migrated=False)
|
|
49
|
+
_patch_projects(monkeypatch, [p])
|
|
50
|
+
assert _find_unmigrated_task_projects() == []
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
def test_mixed_fleet_reports_only_unmigrated(tmp_path, monkeypatch):
|
|
54
|
+
projects = [
|
|
55
|
+
_make_project(tmp_path, "broken", inline_tasks=True, migrated=False),
|
|
56
|
+
_make_project(tmp_path, "fixed", inline_tasks=True, migrated=True),
|
|
57
|
+
_make_project(tmp_path, "plain", inline_tasks=False, migrated=False),
|
|
58
|
+
]
|
|
59
|
+
_patch_projects(monkeypatch, projects)
|
|
60
|
+
assert _find_unmigrated_task_projects() == ["broken"]
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
def test_render_section_flags_and_counts(tmp_path, monkeypatch, capsys):
|
|
64
|
+
p = _make_project(tmp_path, "daily-book-report", inline_tasks=True, migrated=False)
|
|
65
|
+
_patch_projects(monkeypatch, [p])
|
|
66
|
+
count = _render_task_migration_section()
|
|
67
|
+
out = capsys.readouterr().out
|
|
68
|
+
assert count == 1
|
|
69
|
+
assert "daily-book-report" in out
|
|
70
|
+
assert "will NOT run under ensure/scheduler" in out
|
|
71
|
+
assert "agentwire tasks migrate" in out
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
def test_render_section_ok_when_clean(tmp_path, monkeypatch, capsys):
|
|
75
|
+
p = _make_project(tmp_path, "fixed", inline_tasks=True, migrated=True)
|
|
76
|
+
_patch_projects(monkeypatch, [p])
|
|
77
|
+
count = _render_task_migration_section()
|
|
78
|
+
assert count == 0
|
|
79
|
+
assert "No projects with un-migrated inline tasks" in capsys.readouterr().out
|