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.
Files changed (485) hide show
  1. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/.gitignore +2 -0
  2. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/PKG-INFO +1 -1
  3. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/__init__.py +1 -1
  4. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/doctor_cli.py +140 -0
  5. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/server.py +10 -8
  6. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/tasks_cli.py +88 -0
  7. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/tts_cli.py +107 -14
  8. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/docs/wiki/scheduling/scheduled-workloads.md +2 -0
  9. agentwire_dev-1.60.0/tests/unit/test_doctor_task_migration.py +79 -0
  10. agentwire_dev-1.60.0/tests/unit/test_shim_selfheal.py +202 -0
  11. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/tests/unit/test_tasks_cli.py +81 -1
  12. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/.agentwire.yml.example +0 -0
  13. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/.claude/commands/handoff.md +0 -0
  14. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/.claude/skills/wiki/SKILL.md +0 -0
  15. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/.github/FUNDING.yml +0 -0
  16. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
  17. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
  18. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/.github/ISSUE_TEMPLATE/question.md +0 -0
  19. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
  20. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/.github/workflows/pytest.yml +0 -0
  21. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/.github/workflows/ruff.yml +0 -0
  22. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/.github/workflows/security.yml +0 -0
  23. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/.github/workflows/tts-smoke.yml +0 -0
  24. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/AGENTS.md +0 -0
  25. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/CODE_OF_CONDUCT.md +0 -0
  26. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/CONTRIBUTING.md +0 -0
  27. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/Dockerfile.local +0 -0
  28. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/LICENSE +0 -0
  29. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/README.md +0 -0
  30. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/RELEASING.md +0 -0
  31. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/SECURITY.md +0 -0
  32. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/SPONSORS.md +0 -0
  33. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/__main__.py +0 -0
  34. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/agents/__init__.py +0 -0
  35. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/agents/base.py +0 -0
  36. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/agents/tmux.py +0 -0
  37. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/cached_status.py +0 -0
  38. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/channels/__init__.py +0 -0
  39. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/channels/base.py +0 -0
  40. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/channels/email.py +0 -0
  41. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/channels/push.py +0 -0
  42. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/channels/quo.py +0 -0
  43. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/channels_cli.py +0 -0
  44. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/chrome_tabs.py +0 -0
  45. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/completion.py +0 -0
  46. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/config.py +0 -0
  47. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/config_cli.py +0 -0
  48. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/core.py +0 -0
  49. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/council/__init__.py +0 -0
  50. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/council/cli.py +0 -0
  51. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/council/inbox.py +0 -0
  52. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/council/minutes.py +0 -0
  53. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/council/state.py +0 -0
  54. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/council/view.py +0 -0
  55. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/devices.py +0 -0
  56. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/diff_cli.py +0 -0
  57. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/doctor_voice.py +0 -0
  58. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/ensure_cli.py +0 -0
  59. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/fetch.py +0 -0
  60. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/handoff/__init__.py +0 -0
  61. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/handoff/git_state.py +0 -0
  62. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/handoff/instructions.py +0 -0
  63. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/handoff/parser.py +0 -0
  64. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/handoff/renderer.py +0 -0
  65. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/handoff/schema.py +0 -0
  66. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/handoff_cli.py +0 -0
  67. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/history.py +0 -0
  68. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/history_cli.py +0 -0
  69. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/hooks/__init__.py +0 -0
  70. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/hooks/agentwire-permission.sh +0 -0
  71. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/hooks/damage-control/__init__.py +0 -0
  72. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/hooks/damage-control/audit_logger.py +0 -0
  73. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/hooks/damage-control/bash-tool-damage-control.py +0 -0
  74. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/hooks/damage-control/edit-tool-damage-control.py +0 -0
  75. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/hooks/damage-control/mcp-tool-damage-control.py +0 -0
  76. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/hooks/damage-control/read-tool-damage-control.py +0 -0
  77. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/hooks/damage-control/rules/agentwire.yaml +0 -0
  78. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/hooks/damage-control/rules/aws.yaml +0 -0
  79. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/hooks/damage-control/rules/cloud-hosting.yaml +0 -0
  80. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/hooks/damage-control/rules/containers.yaml +0 -0
  81. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/hooks/damage-control/rules/control-plane.yaml +0 -0
  82. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/hooks/damage-control/rules/core.yaml +0 -0
  83. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/hooks/damage-control/rules/databases.yaml +0 -0
  84. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/hooks/damage-control/rules/firebase.yaml +0 -0
  85. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/hooks/damage-control/rules/gcp.yaml +0 -0
  86. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/hooks/damage-control/rules/git.yaml +0 -0
  87. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/hooks/damage-control/rules/gws.yaml +0 -0
  88. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/hooks/damage-control/rules/infrastructure.yaml +0 -0
  89. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/hooks/damage-control/rules/outbound.yaml +0 -0
  90. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/hooks/damage-control/rules/publish.yaml +0 -0
  91. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/hooks/damage-control/rules/remote.yaml +0 -0
  92. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/hooks/damage-control/write-tool-damage-control.py +0 -0
  93. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/hooks/idle-handler.sh +0 -0
  94. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/hooks/queue-processor.sh +0 -0
  95. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/hooks_cli.py +0 -0
  96. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/inbox.py +0 -0
  97. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/limits_cli.py +0 -0
  98. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/listen.py +0 -0
  99. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/locking.py +0 -0
  100. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/machine_cli.py +0 -0
  101. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/mcp_channels.py +0 -0
  102. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/mcp_chrome.py +0 -0
  103. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/mcp_cli.py +0 -0
  104. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/mcp_core.py +0 -0
  105. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/mcp_council.py +0 -0
  106. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/mcp_desktop.py +0 -0
  107. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/mcp_handoff.py +0 -0
  108. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/mcp_history.py +0 -0
  109. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/mcp_listen.py +0 -0
  110. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/mcp_lock.py +0 -0
  111. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/mcp_machine.py +0 -0
  112. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/mcp_msg.py +0 -0
  113. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/mcp_notify.py +0 -0
  114. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/mcp_pane.py +0 -0
  115. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/mcp_projects.py +0 -0
  116. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/mcp_scheduler.py +0 -0
  117. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/mcp_scratchpad.py +0 -0
  118. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/mcp_server.py +0 -0
  119. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/mcp_services.py +0 -0
  120. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/mcp_session.py +0 -0
  121. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/mcp_status.py +0 -0
  122. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/mcp_task.py +0 -0
  123. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/mcp_tunnels.py +0 -0
  124. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/mcp_voice.py +0 -0
  125. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/mcp_wiki.py +0 -0
  126. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/mcp_worktree.py +0 -0
  127. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/msg_cli.py +0 -0
  128. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/network.py +0 -0
  129. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/notify_cli.py +0 -0
  130. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/onboarding.py +0 -0
  131. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/palette_cli.py +0 -0
  132. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/pane_cli.py +0 -0
  133. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/pane_manager.py +0 -0
  134. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/portal_cli.py +0 -0
  135. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/project_config.py +0 -0
  136. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/projects.py +0 -0
  137. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/prompt_router.py +0 -0
  138. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/prompts_cli.py +0 -0
  139. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/push_cli.py +0 -0
  140. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/push_store.py +0 -0
  141. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/repo_cli.py +0 -0
  142. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/research.py +0 -0
  143. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/roles/__init__.py +0 -0
  144. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/roles/agentwire.md +0 -0
  145. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/roles/anchor.md +0 -0
  146. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/roles/chatbot.md +0 -0
  147. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/roles/contributor.md +0 -0
  148. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/roles/correspondent.md +0 -0
  149. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/roles/council-brain.md +0 -0
  150. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/roles/council-conscience.md +0 -0
  151. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/roles/council-critic.md +0 -0
  152. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/roles/council-devils-advocate.md +0 -0
  153. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/roles/council-gut.md +0 -0
  154. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/roles/council-historian.md +0 -0
  155. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/roles/council-member.md +0 -0
  156. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/roles/council-orchestrator.md +0 -0
  157. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/roles/init.md +0 -0
  158. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/roles/notifications.md +0 -0
  159. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/roles/orchestrator.md +0 -0
  160. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/roles/soul.md +0 -0
  161. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/roles/task-runner.md +0 -0
  162. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/roles/voice.md +0 -0
  163. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/roles/worker-worktree.md +0 -0
  164. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/roles/worker.md +0 -0
  165. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/roles_cli.py +0 -0
  166. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/routes/__init__.py +0 -0
  167. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/routes/artifacts.py +0 -0
  168. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/routes/config.py +0 -0
  169. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/routes/council.py +0 -0
  170. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/routes/desktop.py +0 -0
  171. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/routes/history.py +0 -0
  172. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/routes/machines.py +0 -0
  173. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/routes/notify.py +0 -0
  174. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/routes/palette.py +0 -0
  175. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/routes/permission.py +0 -0
  176. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/routes/projects.py +0 -0
  177. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/routes/push.py +0 -0
  178. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/routes/safety.py +0 -0
  179. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/routes/scheduler.py +0 -0
  180. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/routes/scratchpad.py +0 -0
  181. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/routes/sessions.py +0 -0
  182. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/routes/sessions_admin.py +0 -0
  183. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/routes/voice.py +0 -0
  184. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/safety/__init__.py +0 -0
  185. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/safety/_core.py +0 -0
  186. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/safety_cli.py +0 -0
  187. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/safety_commands.py +0 -0
  188. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/scheduler/__init__.py +0 -0
  189. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/scheduler/dispatch.py +0 -0
  190. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/scheduler/gates.py +0 -0
  191. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/scheduler/loop.py +0 -0
  192. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/scheduler/models.py +0 -0
  193. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/scheduler/report.py +0 -0
  194. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/scheduler/schedule.py +0 -0
  195. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/scheduler/state.py +0 -0
  196. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/scheduler_cli.py +0 -0
  197. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/scratchpad.py +0 -0
  198. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/security.py +0 -0
  199. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/send_cli.py +0 -0
  200. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/services.py +0 -0
  201. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/session_cli.py +0 -0
  202. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/session_context.py +0 -0
  203. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/session_ready.py +0 -0
  204. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/ssh.py +0 -0
  205. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/static/agentwire-splash-logo-layers--agentwire-text.png +0 -0
  206. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/static/agentwire-splash-logo-layers--echo-claw-fg.png +0 -0
  207. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/static/agentwire-splash-logo-layers--echo.png +0 -0
  208. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/static/agentwire-splash-logo-layers--telephone.png +0 -0
  209. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/static/agentwire-splash-logo-layers--tree.png +0 -0
  210. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/static/announcements.json +0 -0
  211. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/static/apple-touch-icon.png +0 -0
  212. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/static/css/desktop.css +0 -0
  213. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/static/css/mobile.css +0 -0
  214. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/static/favicon-32.png +0 -0
  215. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/static/favicon-64.png +0 -0
  216. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/static/icons/sessions/bear.webp +0 -0
  217. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/static/icons/sessions/cat.webp +0 -0
  218. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/static/icons/sessions/crown.webp +0 -0
  219. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/static/icons/sessions/custom/agentwire-portal.webp +0 -0
  220. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/static/icons/sessions/custom/agentwire-tts.webp +0 -0
  221. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/static/icons/sessions/custom/agentwire.webp +0 -0
  222. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/static/icons/sessions/deer.webp +0 -0
  223. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/static/icons/sessions/drone.webp +0 -0
  224. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/static/icons/sessions/eagle.webp +0 -0
  225. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/static/icons/sessions/fox.webp +0 -0
  226. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/static/icons/sessions/hawk.webp +0 -0
  227. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/static/icons/sessions/horse.webp +0 -0
  228. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/static/icons/sessions/lion.webp +0 -0
  229. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/static/icons/sessions/rabbit.webp +0 -0
  230. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/static/icons/sessions/robot.webp +0 -0
  231. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/static/icons/sessions/tiger.webp +0 -0
  232. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/static/icons/sessions/wolf.webp +0 -0
  233. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/static/img/icon-192.png +0 -0
  234. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/static/img/icon-512.png +0 -0
  235. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/static/js/.gitkeep +0 -0
  236. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/static/js/announcement-modal.js +0 -0
  237. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/static/js/api.js +0 -0
  238. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/static/js/artifact-window.js +0 -0
  239. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/static/js/collage.js +0 -0
  240. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/static/js/command-palette.js +0 -0
  241. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/static/js/council-window.js +0 -0
  242. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/static/js/dead-key-suppressor.js +0 -0
  243. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/static/js/desktop-manager.js +0 -0
  244. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/static/js/desktop.js +0 -0
  245. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/static/js/help-modal.js +0 -0
  246. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/static/js/icon-manager.js +0 -0
  247. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/static/js/mobile.js +0 -0
  248. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/static/js/notification-prefs.js +0 -0
  249. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/static/js/notifications-panel.js +0 -0
  250. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/static/js/ptt.js +0 -0
  251. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/static/js/push-client.js +0 -0
  252. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/static/js/review-window.js +0 -0
  253. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/static/js/safety-shared.js +0 -0
  254. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/static/js/safety-window.js +0 -0
  255. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/static/js/scratchpad.js +0 -0
  256. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/static/js/service-classification.js +0 -0
  257. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/static/js/session-id.js +0 -0
  258. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/static/js/session-window.js +0 -0
  259. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/static/js/shortcuts.js +0 -0
  260. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/static/js/sidebar/artifacts-section.js +0 -0
  261. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/static/js/sidebar/config-section.js +0 -0
  262. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/static/js/sidebar/council-section.js +0 -0
  263. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/static/js/sidebar/machines-section.js +0 -0
  264. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/static/js/sidebar/projects-section.js +0 -0
  265. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/static/js/sidebar/safety-section.js +0 -0
  266. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/static/js/sidebar/scheduler-section.js +0 -0
  267. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/static/js/sidebar/services-section.js +0 -0
  268. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/static/js/sidebar/sessions-section.js +0 -0
  269. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/static/js/sidebar.js +0 -0
  270. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/static/js/terminal-font-prefs.js +0 -0
  271. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/static/js/tile-manager.js +0 -0
  272. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/static/js/toast.js +0 -0
  273. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/static/js/token-modal.js +0 -0
  274. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/static/js/utils/ansi.js +0 -0
  275. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/static/js/utils/swipe.js +0 -0
  276. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/static/js/voice/autosend-prefs.js +0 -0
  277. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/static/js/voice/browser-stt.js +0 -0
  278. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/static/js/voice/browser-tts.js +0 -0
  279. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/static/js/voice/jargon.js +0 -0
  280. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/static/js/voice/prompt.js +0 -0
  281. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/static/js/winbox.bundle.min.js +0 -0
  282. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/static/manifest.webmanifest +0 -0
  283. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/static/service-worker.js +0 -0
  284. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/stt/__init__.py +0 -0
  285. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/stt/base.py +0 -0
  286. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/stt/cloud.py +0 -0
  287. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/stt/engine.py +0 -0
  288. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/stt/local.py +0 -0
  289. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/stt/server_backend.py +0 -0
  290. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/stt/stt_server.py +0 -0
  291. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/system_cli.py +0 -0
  292. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/tabs_cli.py +0 -0
  293. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/tasks.py +0 -0
  294. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/templates/__init__.py +0 -0
  295. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/templates/base.html +0 -0
  296. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/templates/council/minutes.html.j2 +0 -0
  297. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/templates/desktop.html +0 -0
  298. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/templates/email_notification.html +0 -0
  299. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/templates/handoff/show-the-story.html.j2 +0 -0
  300. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/templates/handoff/theme.css.j2 +0 -0
  301. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/templates/mobile.html +0 -0
  302. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/templates/pair.html +0 -0
  303. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/templates/tmux.conf +0 -0
  304. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/templating.py +0 -0
  305. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/tooldefs/aws.yaml +0 -0
  306. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/tooldefs/docker.yaml +0 -0
  307. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/tooldefs/gcp.yaml +0 -0
  308. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/tooldefs/gh.yaml +0 -0
  309. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/tooldefs/git.yaml +0 -0
  310. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/tooldefs/gws.yaml +0 -0
  311. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/tooldefs/kubectl.yaml +0 -0
  312. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/tooldefs/npm.yaml +0 -0
  313. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/tooldefs/terraform.yaml +0 -0
  314. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/tooldefs/uv.yaml +0 -0
  315. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/tts/__init__.py +0 -0
  316. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/tts/audio.py +0 -0
  317. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/tts/base.py +0 -0
  318. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/tts/engines/__init__.py +0 -0
  319. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/tts/engines/chatterbox.py +0 -0
  320. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/tts/engines/kokoro.py +0 -0
  321. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/tts/engines/zonos.py +0 -0
  322. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/tts/kokoro_server.py +0 -0
  323. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/tts/local.py +0 -0
  324. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/tts/registry.py +0 -0
  325. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/tts_server.py +0 -0
  326. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/tunnels.py +0 -0
  327. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/tunnels_cli.py +0 -0
  328. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/usage_limit.py +0 -0
  329. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/utils/__init__.py +0 -0
  330. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/utils/chunker.py +0 -0
  331. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/utils/event_log.py +0 -0
  332. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/utils/file_io.py +0 -0
  333. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/utils/paths.py +0 -0
  334. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/utils/speech.py +0 -0
  335. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/utils/subprocess.py +0 -0
  336. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/validation.py +0 -0
  337. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/voice_status.py +0 -0
  338. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/wiki.py +0 -0
  339. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/wiki_audit.py +0 -0
  340. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/wiki_cli.py +0 -0
  341. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/worktree.py +0 -0
  342. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/agentwire/worktree_registry.py +0 -0
  343. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/docs/decisions/obsidian-second-brain.md +0 -0
  344. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/docs/logo.png +0 -0
  345. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/docs/wiki/INDEX.md +0 -0
  346. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/docs/wiki/architecture.md +0 -0
  347. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/docs/wiki/briefing-mode.md +0 -0
  348. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/docs/wiki/communication/channels.md +0 -0
  349. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/docs/wiki/communication/hammerspoon.md +0 -0
  350. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/docs/wiki/communication/handoff.md +0 -0
  351. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/docs/wiki/concepts.md +0 -0
  352. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/docs/wiki/council.md +0 -0
  353. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/docs/wiki/deployment/remote-access.md +0 -0
  354. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/docs/wiki/deployment/remote-machines.md +0 -0
  355. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/docs/wiki/glossary.md +0 -0
  356. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/docs/wiki/integrations/gws-google-workspace-cli.md +0 -0
  357. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/docs/wiki/internals/damage-control.md +0 -0
  358. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/docs/wiki/internals/parallel-refactor.md +0 -0
  359. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/docs/wiki/internals/portal.md +0 -0
  360. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/docs/wiki/internals/shell-escaping.md +0 -0
  361. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/docs/wiki/internals/troubleshooting.md +0 -0
  362. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/docs/wiki/internals/window-collage.md +0 -0
  363. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/docs/wiki/quickstart.md +0 -0
  364. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/docs/wiki/research/briefing-mode-feasibility.md +0 -0
  365. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/docs/wiki/research/orchestration-transport-alternatives.md +0 -0
  366. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/docs/wiki/security/damage-control-hardening.md +0 -0
  367. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/docs/wiki/security/pip-audit.md +0 -0
  368. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/docs/wiki/security/remote-access-hardening.md +0 -0
  369. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/docs/wiki/security/secrets.md +0 -0
  370. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/docs/wiki/services.md +0 -0
  371. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/docs/wiki/sessions/claude-code-auto-mode.md +0 -0
  372. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/docs/wiki/sessions/messaging.md +0 -0
  373. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/docs/wiki/sessions/prompt-routing.md +0 -0
  374. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/docs/wiki/sessions/window-sizing.md +0 -0
  375. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/docs/wiki/sessions/worktree-sessions.md +0 -0
  376. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/docs/wiki/usage-limit-recovery.md +0 -0
  377. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/docs/wiki/voice/shim-contract.md +0 -0
  378. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/docs/wiki/voice/stt-cloud.md +0 -0
  379. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/docs/wiki/voice/stt-self-hosted.md +0 -0
  380. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/docs/wiki/voice/tts-self-hosted.md +0 -0
  381. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/pyproject.toml +0 -0
  382. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/tests/conftest.py +0 -0
  383. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/tests/e2e/test_portal_ui.py +0 -0
  384. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/tests/fixtures/sample_agentwire.yml +0 -0
  385. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/tests/fixtures/sample_config.yaml +0 -0
  386. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/tests/fixtures/sample_scheduler.yaml +0 -0
  387. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/tests/integration/test_council_portal.py +0 -0
  388. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/tests/integration/test_scheduler_board.py +0 -0
  389. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/tests/integration/test_send_verified_tmux.py +0 -0
  390. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/tests/integration/test_server_websockets.py +0 -0
  391. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/tests/integration/test_worktree_cmd.py +0 -0
  392. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/tests/unit/test_announcements.py +0 -0
  393. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/tests/unit/test_build_agent_command.py +0 -0
  394. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/tests/unit/test_channels.py +0 -0
  395. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/tests/unit/test_chrome_tabs.py +0 -0
  396. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/tests/unit/test_cli_commands.py +0 -0
  397. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/tests/unit/test_cli_output.py +0 -0
  398. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/tests/unit/test_cli_smoke.py +0 -0
  399. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/tests/unit/test_config.py +0 -0
  400. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/tests/unit/test_config_cli.py +0 -0
  401. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/tests/unit/test_control_plane_protection.py +0 -0
  402. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/tests/unit/test_core_created_by_rooting.py +0 -0
  403. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/tests/unit/test_council_cli.py +0 -0
  404. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/tests/unit/test_council_inbox.py +0 -0
  405. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/tests/unit/test_council_minutes.py +0 -0
  406. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/tests/unit/test_council_state.py +0 -0
  407. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/tests/unit/test_council_view.py +0 -0
  408. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/tests/unit/test_damage_control_bypass.py +0 -0
  409. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/tests/unit/test_damage_control_hooks.py +0 -0
  410. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/tests/unit/test_damage_control_sync.py +0 -0
  411. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/tests/unit/test_dangling_worktrees.py +0 -0
  412. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/tests/unit/test_devices.py +0 -0
  413. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/tests/unit/test_diff_cli.py +0 -0
  414. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/tests/unit/test_doctor_voice.py +0 -0
  415. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/tests/unit/test_event_log.py +0 -0
  416. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/tests/unit/test_file_io.py +0 -0
  417. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/tests/unit/test_handoff_git_state.py +0 -0
  418. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/tests/unit/test_handoff_instructions.py +0 -0
  419. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/tests/unit/test_handoff_parser.py +0 -0
  420. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/tests/unit/test_handoff_renderer.py +0 -0
  421. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/tests/unit/test_history.py +0 -0
  422. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/tests/unit/test_hooks_install.py +0 -0
  423. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/tests/unit/test_idle_handler.py +0 -0
  424. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/tests/unit/test_idle_nag.py +0 -0
  425. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/tests/unit/test_inbox.py +0 -0
  426. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/tests/unit/test_init_command.py +0 -0
  427. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/tests/unit/test_install_parity.py +0 -0
  428. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/tests/unit/test_limits_tick_isolation.py +0 -0
  429. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/tests/unit/test_locking.py +0 -0
  430. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/tests/unit/test_mcp_server.py +0 -0
  431. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/tests/unit/test_mcp_tools_args.py +0 -0
  432. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/tests/unit/test_msg_cli.py +0 -0
  433. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/tests/unit/test_notify_cli.py +0 -0
  434. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/tests/unit/test_onboarding_reinit.py +0 -0
  435. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/tests/unit/test_palette_cli.py +0 -0
  436. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/tests/unit/test_pip_environment.py +0 -0
  437. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/tests/unit/test_portal_api.py +0 -0
  438. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/tests/unit/test_posture_default.py +0 -0
  439. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/tests/unit/test_project_config.py +0 -0
  440. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/tests/unit/test_prompt_router.py +0 -0
  441. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/tests/unit/test_push.py +0 -0
  442. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/tests/unit/test_rebuild_guard.py +0 -0
  443. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/tests/unit/test_repo_cli.py +0 -0
  444. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/tests/unit/test_roles.py +0 -0
  445. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/tests/unit/test_routes_snapshot.py +0 -0
  446. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/tests/unit/test_safety_commands.py +0 -0
  447. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/tests/unit/test_safety_disabled_rules.py +0 -0
  448. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/tests/unit/test_safety_escape_hatch.py +0 -0
  449. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/tests/unit/test_safety_heal.py +0 -0
  450. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/tests/unit/test_safety_kill_switch.py +0 -0
  451. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/tests/unit/test_scheduler.py +0 -0
  452. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/tests/unit/test_scheduler_parsing.py +0 -0
  453. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/tests/unit/test_scratchpad.py +0 -0
  454. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/tests/unit/test_security.py +0 -0
  455. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/tests/unit/test_server_async.py +0 -0
  456. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/tests/unit/test_server_pure.py +0 -0
  457. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/tests/unit/test_services.py +0 -0
  458. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/tests/unit/test_session_context.py +0 -0
  459. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/tests/unit/test_session_ready.py +0 -0
  460. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/tests/unit/test_shared_dir_guard.py +0 -0
  461. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/tests/unit/test_skill_install.py +0 -0
  462. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/tests/unit/test_speech_tags.py +0 -0
  463. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/tests/unit/test_ssh.py +0 -0
  464. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/tests/unit/test_stt_backend.py +0 -0
  465. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/tests/unit/test_stt_cloud.py +0 -0
  466. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/tests/unit/test_stt_engine.py +0 -0
  467. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/tests/unit/test_task_cli.py +0 -0
  468. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/tests/unit/test_tasks.py +0 -0
  469. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/tests/unit/test_templating.py +0 -0
  470. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/tests/unit/test_terminal_resize.py +0 -0
  471. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/tests/unit/test_tmux_template.py +0 -0
  472. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/tests/unit/test_tts_engine_resolution.py +0 -0
  473. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/tests/unit/test_tts_local.py +0 -0
  474. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/tests/unit/test_tunnels_probe.py +0 -0
  475. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/tests/unit/test_unattended_env_isolation.py +0 -0
  476. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/tests/unit/test_usage_limit.py +0 -0
  477. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/tests/unit/test_validation.py +0 -0
  478. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/tests/unit/test_voice_status.py +0 -0
  479. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/tests/unit/test_wiki.py +0 -0
  480. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/tests/unit/test_wiki_audit.py +0 -0
  481. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/tests/unit/test_window_cycling_binding.py +0 -0
  482. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/tests/unit/test_worktree.py +0 -0
  483. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/tests/unit/test_worktree_branch_cleanup.py +0 -0
  484. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/tests/unit/test_worktree_layout.py +0 -0
  485. {agentwire_dev-1.58.0 → agentwire_dev-1.60.0}/tests/unit/test_worktree_registry.py +0 -0
@@ -45,6 +45,8 @@ Thumbs.db
45
45
  /voices/
46
46
 
47
47
  .agentwire.yml
48
+ .agentwire.tasks.yml
49
+ .agentwire.tasks.proposed.yml
48
50
 
49
51
 
50
52
  # Test outputs
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: agentwire-dev
3
- Version: 1.58.0
3
+ Version: 1.60.0
4
4
  Summary: Multi-session voice web interface for AI coding agents
5
5
  Project-URL: Homepage, https://agentwire.dev
6
6
  Project-URL: Repository, https://github.com/dotdevdotdev/agentwire-dev
@@ -1,3 +1,3 @@
1
1
  """AgentWire - Multi-session voice web interface for AI coding agents."""
2
2
 
3
- __version__ = "1.58.0"
3
+ __version__ = "1.60.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`` early-returns if the ``agentwire-stt``
391
- tmux session already exists, so a user-started shim is reused with no
392
- port clash. The ~19s ONNX warm-up happens in that child process, never
393
- on the portal's event loop. Mirrors ``autostart_custom_services``."""
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`` early-returns if the
442
- ``agentwire-kokoro`` tmux session already exists, so a user-started shim
443
- is reused with no port clash. The ~200 MB download + ONNX warm-up
444
- happens in that child process, never on the portal's event loop. Mirrors
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
- print(f"STT server already running in tmux session '{session_name}'")
470
- print(f" Attach: tmux attach -t {session_name}")
471
- return 0
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, and the early-return on an existing session means a
583
- user-started shim is reused with no port clash."""
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