agentwire-dev 1.59.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.59.0 → agentwire_dev-1.60.0}/PKG-INFO +1 -1
  2. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/__init__.py +1 -1
  3. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/doctor_cli.py +82 -0
  4. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/server.py +10 -8
  5. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/tts_cli.py +107 -14
  6. agentwire_dev-1.60.0/tests/unit/test_shim_selfheal.py +202 -0
  7. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/.agentwire.yml.example +0 -0
  8. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/.claude/commands/handoff.md +0 -0
  9. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/.claude/skills/wiki/SKILL.md +0 -0
  10. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/.github/FUNDING.yml +0 -0
  11. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
  12. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
  13. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/.github/ISSUE_TEMPLATE/question.md +0 -0
  14. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
  15. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/.github/workflows/pytest.yml +0 -0
  16. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/.github/workflows/ruff.yml +0 -0
  17. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/.github/workflows/security.yml +0 -0
  18. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/.github/workflows/tts-smoke.yml +0 -0
  19. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/.gitignore +0 -0
  20. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/AGENTS.md +0 -0
  21. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/CODE_OF_CONDUCT.md +0 -0
  22. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/CONTRIBUTING.md +0 -0
  23. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/Dockerfile.local +0 -0
  24. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/LICENSE +0 -0
  25. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/README.md +0 -0
  26. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/RELEASING.md +0 -0
  27. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/SECURITY.md +0 -0
  28. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/SPONSORS.md +0 -0
  29. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/__main__.py +0 -0
  30. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/agents/__init__.py +0 -0
  31. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/agents/base.py +0 -0
  32. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/agents/tmux.py +0 -0
  33. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/cached_status.py +0 -0
  34. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/channels/__init__.py +0 -0
  35. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/channels/base.py +0 -0
  36. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/channels/email.py +0 -0
  37. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/channels/push.py +0 -0
  38. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/channels/quo.py +0 -0
  39. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/channels_cli.py +0 -0
  40. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/chrome_tabs.py +0 -0
  41. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/completion.py +0 -0
  42. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/config.py +0 -0
  43. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/config_cli.py +0 -0
  44. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/core.py +0 -0
  45. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/council/__init__.py +0 -0
  46. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/council/cli.py +0 -0
  47. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/council/inbox.py +0 -0
  48. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/council/minutes.py +0 -0
  49. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/council/state.py +0 -0
  50. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/council/view.py +0 -0
  51. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/devices.py +0 -0
  52. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/diff_cli.py +0 -0
  53. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/doctor_voice.py +0 -0
  54. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/ensure_cli.py +0 -0
  55. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/fetch.py +0 -0
  56. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/handoff/__init__.py +0 -0
  57. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/handoff/git_state.py +0 -0
  58. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/handoff/instructions.py +0 -0
  59. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/handoff/parser.py +0 -0
  60. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/handoff/renderer.py +0 -0
  61. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/handoff/schema.py +0 -0
  62. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/handoff_cli.py +0 -0
  63. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/history.py +0 -0
  64. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/history_cli.py +0 -0
  65. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/hooks/__init__.py +0 -0
  66. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/hooks/agentwire-permission.sh +0 -0
  67. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/hooks/damage-control/__init__.py +0 -0
  68. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/hooks/damage-control/audit_logger.py +0 -0
  69. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/hooks/damage-control/bash-tool-damage-control.py +0 -0
  70. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/hooks/damage-control/edit-tool-damage-control.py +0 -0
  71. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/hooks/damage-control/mcp-tool-damage-control.py +0 -0
  72. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/hooks/damage-control/read-tool-damage-control.py +0 -0
  73. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/hooks/damage-control/rules/agentwire.yaml +0 -0
  74. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/hooks/damage-control/rules/aws.yaml +0 -0
  75. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/hooks/damage-control/rules/cloud-hosting.yaml +0 -0
  76. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/hooks/damage-control/rules/containers.yaml +0 -0
  77. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/hooks/damage-control/rules/control-plane.yaml +0 -0
  78. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/hooks/damage-control/rules/core.yaml +0 -0
  79. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/hooks/damage-control/rules/databases.yaml +0 -0
  80. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/hooks/damage-control/rules/firebase.yaml +0 -0
  81. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/hooks/damage-control/rules/gcp.yaml +0 -0
  82. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/hooks/damage-control/rules/git.yaml +0 -0
  83. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/hooks/damage-control/rules/gws.yaml +0 -0
  84. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/hooks/damage-control/rules/infrastructure.yaml +0 -0
  85. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/hooks/damage-control/rules/outbound.yaml +0 -0
  86. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/hooks/damage-control/rules/publish.yaml +0 -0
  87. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/hooks/damage-control/rules/remote.yaml +0 -0
  88. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/hooks/damage-control/write-tool-damage-control.py +0 -0
  89. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/hooks/idle-handler.sh +0 -0
  90. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/hooks/queue-processor.sh +0 -0
  91. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/hooks_cli.py +0 -0
  92. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/inbox.py +0 -0
  93. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/limits_cli.py +0 -0
  94. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/listen.py +0 -0
  95. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/locking.py +0 -0
  96. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/machine_cli.py +0 -0
  97. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/mcp_channels.py +0 -0
  98. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/mcp_chrome.py +0 -0
  99. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/mcp_cli.py +0 -0
  100. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/mcp_core.py +0 -0
  101. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/mcp_council.py +0 -0
  102. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/mcp_desktop.py +0 -0
  103. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/mcp_handoff.py +0 -0
  104. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/mcp_history.py +0 -0
  105. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/mcp_listen.py +0 -0
  106. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/mcp_lock.py +0 -0
  107. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/mcp_machine.py +0 -0
  108. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/mcp_msg.py +0 -0
  109. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/mcp_notify.py +0 -0
  110. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/mcp_pane.py +0 -0
  111. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/mcp_projects.py +0 -0
  112. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/mcp_scheduler.py +0 -0
  113. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/mcp_scratchpad.py +0 -0
  114. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/mcp_server.py +0 -0
  115. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/mcp_services.py +0 -0
  116. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/mcp_session.py +0 -0
  117. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/mcp_status.py +0 -0
  118. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/mcp_task.py +0 -0
  119. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/mcp_tunnels.py +0 -0
  120. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/mcp_voice.py +0 -0
  121. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/mcp_wiki.py +0 -0
  122. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/mcp_worktree.py +0 -0
  123. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/msg_cli.py +0 -0
  124. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/network.py +0 -0
  125. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/notify_cli.py +0 -0
  126. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/onboarding.py +0 -0
  127. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/palette_cli.py +0 -0
  128. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/pane_cli.py +0 -0
  129. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/pane_manager.py +0 -0
  130. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/portal_cli.py +0 -0
  131. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/project_config.py +0 -0
  132. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/projects.py +0 -0
  133. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/prompt_router.py +0 -0
  134. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/prompts_cli.py +0 -0
  135. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/push_cli.py +0 -0
  136. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/push_store.py +0 -0
  137. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/repo_cli.py +0 -0
  138. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/research.py +0 -0
  139. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/roles/__init__.py +0 -0
  140. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/roles/agentwire.md +0 -0
  141. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/roles/anchor.md +0 -0
  142. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/roles/chatbot.md +0 -0
  143. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/roles/contributor.md +0 -0
  144. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/roles/correspondent.md +0 -0
  145. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/roles/council-brain.md +0 -0
  146. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/roles/council-conscience.md +0 -0
  147. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/roles/council-critic.md +0 -0
  148. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/roles/council-devils-advocate.md +0 -0
  149. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/roles/council-gut.md +0 -0
  150. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/roles/council-historian.md +0 -0
  151. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/roles/council-member.md +0 -0
  152. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/roles/council-orchestrator.md +0 -0
  153. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/roles/init.md +0 -0
  154. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/roles/notifications.md +0 -0
  155. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/roles/orchestrator.md +0 -0
  156. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/roles/soul.md +0 -0
  157. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/roles/task-runner.md +0 -0
  158. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/roles/voice.md +0 -0
  159. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/roles/worker-worktree.md +0 -0
  160. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/roles/worker.md +0 -0
  161. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/roles_cli.py +0 -0
  162. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/routes/__init__.py +0 -0
  163. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/routes/artifacts.py +0 -0
  164. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/routes/config.py +0 -0
  165. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/routes/council.py +0 -0
  166. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/routes/desktop.py +0 -0
  167. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/routes/history.py +0 -0
  168. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/routes/machines.py +0 -0
  169. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/routes/notify.py +0 -0
  170. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/routes/palette.py +0 -0
  171. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/routes/permission.py +0 -0
  172. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/routes/projects.py +0 -0
  173. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/routes/push.py +0 -0
  174. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/routes/safety.py +0 -0
  175. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/routes/scheduler.py +0 -0
  176. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/routes/scratchpad.py +0 -0
  177. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/routes/sessions.py +0 -0
  178. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/routes/sessions_admin.py +0 -0
  179. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/routes/voice.py +0 -0
  180. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/safety/__init__.py +0 -0
  181. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/safety/_core.py +0 -0
  182. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/safety_cli.py +0 -0
  183. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/safety_commands.py +0 -0
  184. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/scheduler/__init__.py +0 -0
  185. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/scheduler/dispatch.py +0 -0
  186. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/scheduler/gates.py +0 -0
  187. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/scheduler/loop.py +0 -0
  188. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/scheduler/models.py +0 -0
  189. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/scheduler/report.py +0 -0
  190. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/scheduler/schedule.py +0 -0
  191. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/scheduler/state.py +0 -0
  192. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/scheduler_cli.py +0 -0
  193. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/scratchpad.py +0 -0
  194. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/security.py +0 -0
  195. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/send_cli.py +0 -0
  196. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/services.py +0 -0
  197. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/session_cli.py +0 -0
  198. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/session_context.py +0 -0
  199. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/session_ready.py +0 -0
  200. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/ssh.py +0 -0
  201. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/static/agentwire-splash-logo-layers--agentwire-text.png +0 -0
  202. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/static/agentwire-splash-logo-layers--echo-claw-fg.png +0 -0
  203. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/static/agentwire-splash-logo-layers--echo.png +0 -0
  204. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/static/agentwire-splash-logo-layers--telephone.png +0 -0
  205. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/static/agentwire-splash-logo-layers--tree.png +0 -0
  206. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/static/announcements.json +0 -0
  207. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/static/apple-touch-icon.png +0 -0
  208. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/static/css/desktop.css +0 -0
  209. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/static/css/mobile.css +0 -0
  210. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/static/favicon-32.png +0 -0
  211. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/static/favicon-64.png +0 -0
  212. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/static/icons/sessions/bear.webp +0 -0
  213. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/static/icons/sessions/cat.webp +0 -0
  214. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/static/icons/sessions/crown.webp +0 -0
  215. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/static/icons/sessions/custom/agentwire-portal.webp +0 -0
  216. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/static/icons/sessions/custom/agentwire-tts.webp +0 -0
  217. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/static/icons/sessions/custom/agentwire.webp +0 -0
  218. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/static/icons/sessions/deer.webp +0 -0
  219. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/static/icons/sessions/drone.webp +0 -0
  220. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/static/icons/sessions/eagle.webp +0 -0
  221. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/static/icons/sessions/fox.webp +0 -0
  222. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/static/icons/sessions/hawk.webp +0 -0
  223. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/static/icons/sessions/horse.webp +0 -0
  224. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/static/icons/sessions/lion.webp +0 -0
  225. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/static/icons/sessions/rabbit.webp +0 -0
  226. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/static/icons/sessions/robot.webp +0 -0
  227. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/static/icons/sessions/tiger.webp +0 -0
  228. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/static/icons/sessions/wolf.webp +0 -0
  229. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/static/img/icon-192.png +0 -0
  230. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/static/img/icon-512.png +0 -0
  231. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/static/js/.gitkeep +0 -0
  232. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/static/js/announcement-modal.js +0 -0
  233. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/static/js/api.js +0 -0
  234. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/static/js/artifact-window.js +0 -0
  235. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/static/js/collage.js +0 -0
  236. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/static/js/command-palette.js +0 -0
  237. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/static/js/council-window.js +0 -0
  238. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/static/js/dead-key-suppressor.js +0 -0
  239. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/static/js/desktop-manager.js +0 -0
  240. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/static/js/desktop.js +0 -0
  241. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/static/js/help-modal.js +0 -0
  242. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/static/js/icon-manager.js +0 -0
  243. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/static/js/mobile.js +0 -0
  244. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/static/js/notification-prefs.js +0 -0
  245. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/static/js/notifications-panel.js +0 -0
  246. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/static/js/ptt.js +0 -0
  247. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/static/js/push-client.js +0 -0
  248. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/static/js/review-window.js +0 -0
  249. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/static/js/safety-shared.js +0 -0
  250. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/static/js/safety-window.js +0 -0
  251. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/static/js/scratchpad.js +0 -0
  252. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/static/js/service-classification.js +0 -0
  253. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/static/js/session-id.js +0 -0
  254. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/static/js/session-window.js +0 -0
  255. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/static/js/shortcuts.js +0 -0
  256. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/static/js/sidebar/artifacts-section.js +0 -0
  257. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/static/js/sidebar/config-section.js +0 -0
  258. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/static/js/sidebar/council-section.js +0 -0
  259. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/static/js/sidebar/machines-section.js +0 -0
  260. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/static/js/sidebar/projects-section.js +0 -0
  261. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/static/js/sidebar/safety-section.js +0 -0
  262. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/static/js/sidebar/scheduler-section.js +0 -0
  263. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/static/js/sidebar/services-section.js +0 -0
  264. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/static/js/sidebar/sessions-section.js +0 -0
  265. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/static/js/sidebar.js +0 -0
  266. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/static/js/terminal-font-prefs.js +0 -0
  267. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/static/js/tile-manager.js +0 -0
  268. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/static/js/toast.js +0 -0
  269. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/static/js/token-modal.js +0 -0
  270. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/static/js/utils/ansi.js +0 -0
  271. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/static/js/utils/swipe.js +0 -0
  272. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/static/js/voice/autosend-prefs.js +0 -0
  273. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/static/js/voice/browser-stt.js +0 -0
  274. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/static/js/voice/browser-tts.js +0 -0
  275. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/static/js/voice/jargon.js +0 -0
  276. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/static/js/voice/prompt.js +0 -0
  277. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/static/js/winbox.bundle.min.js +0 -0
  278. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/static/manifest.webmanifest +0 -0
  279. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/static/service-worker.js +0 -0
  280. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/stt/__init__.py +0 -0
  281. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/stt/base.py +0 -0
  282. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/stt/cloud.py +0 -0
  283. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/stt/engine.py +0 -0
  284. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/stt/local.py +0 -0
  285. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/stt/server_backend.py +0 -0
  286. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/stt/stt_server.py +0 -0
  287. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/system_cli.py +0 -0
  288. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/tabs_cli.py +0 -0
  289. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/tasks.py +0 -0
  290. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/tasks_cli.py +0 -0
  291. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/templates/__init__.py +0 -0
  292. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/templates/base.html +0 -0
  293. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/templates/council/minutes.html.j2 +0 -0
  294. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/templates/desktop.html +0 -0
  295. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/templates/email_notification.html +0 -0
  296. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/templates/handoff/show-the-story.html.j2 +0 -0
  297. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/templates/handoff/theme.css.j2 +0 -0
  298. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/templates/mobile.html +0 -0
  299. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/templates/pair.html +0 -0
  300. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/templates/tmux.conf +0 -0
  301. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/templating.py +0 -0
  302. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/tooldefs/aws.yaml +0 -0
  303. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/tooldefs/docker.yaml +0 -0
  304. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/tooldefs/gcp.yaml +0 -0
  305. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/tooldefs/gh.yaml +0 -0
  306. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/tooldefs/git.yaml +0 -0
  307. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/tooldefs/gws.yaml +0 -0
  308. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/tooldefs/kubectl.yaml +0 -0
  309. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/tooldefs/npm.yaml +0 -0
  310. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/tooldefs/terraform.yaml +0 -0
  311. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/tooldefs/uv.yaml +0 -0
  312. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/tts/__init__.py +0 -0
  313. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/tts/audio.py +0 -0
  314. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/tts/base.py +0 -0
  315. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/tts/engines/__init__.py +0 -0
  316. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/tts/engines/chatterbox.py +0 -0
  317. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/tts/engines/kokoro.py +0 -0
  318. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/tts/engines/zonos.py +0 -0
  319. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/tts/kokoro_server.py +0 -0
  320. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/tts/local.py +0 -0
  321. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/tts/registry.py +0 -0
  322. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/tts_server.py +0 -0
  323. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/tunnels.py +0 -0
  324. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/tunnels_cli.py +0 -0
  325. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/usage_limit.py +0 -0
  326. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/utils/__init__.py +0 -0
  327. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/utils/chunker.py +0 -0
  328. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/utils/event_log.py +0 -0
  329. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/utils/file_io.py +0 -0
  330. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/utils/paths.py +0 -0
  331. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/utils/speech.py +0 -0
  332. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/utils/subprocess.py +0 -0
  333. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/validation.py +0 -0
  334. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/voice_status.py +0 -0
  335. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/wiki.py +0 -0
  336. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/wiki_audit.py +0 -0
  337. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/wiki_cli.py +0 -0
  338. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/worktree.py +0 -0
  339. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/agentwire/worktree_registry.py +0 -0
  340. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/docs/decisions/obsidian-second-brain.md +0 -0
  341. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/docs/logo.png +0 -0
  342. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/docs/wiki/INDEX.md +0 -0
  343. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/docs/wiki/architecture.md +0 -0
  344. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/docs/wiki/briefing-mode.md +0 -0
  345. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/docs/wiki/communication/channels.md +0 -0
  346. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/docs/wiki/communication/hammerspoon.md +0 -0
  347. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/docs/wiki/communication/handoff.md +0 -0
  348. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/docs/wiki/concepts.md +0 -0
  349. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/docs/wiki/council.md +0 -0
  350. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/docs/wiki/deployment/remote-access.md +0 -0
  351. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/docs/wiki/deployment/remote-machines.md +0 -0
  352. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/docs/wiki/glossary.md +0 -0
  353. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/docs/wiki/integrations/gws-google-workspace-cli.md +0 -0
  354. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/docs/wiki/internals/damage-control.md +0 -0
  355. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/docs/wiki/internals/parallel-refactor.md +0 -0
  356. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/docs/wiki/internals/portal.md +0 -0
  357. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/docs/wiki/internals/shell-escaping.md +0 -0
  358. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/docs/wiki/internals/troubleshooting.md +0 -0
  359. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/docs/wiki/internals/window-collage.md +0 -0
  360. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/docs/wiki/quickstart.md +0 -0
  361. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/docs/wiki/research/briefing-mode-feasibility.md +0 -0
  362. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/docs/wiki/research/orchestration-transport-alternatives.md +0 -0
  363. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/docs/wiki/scheduling/scheduled-workloads.md +0 -0
  364. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/docs/wiki/security/damage-control-hardening.md +0 -0
  365. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/docs/wiki/security/pip-audit.md +0 -0
  366. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/docs/wiki/security/remote-access-hardening.md +0 -0
  367. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/docs/wiki/security/secrets.md +0 -0
  368. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/docs/wiki/services.md +0 -0
  369. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/docs/wiki/sessions/claude-code-auto-mode.md +0 -0
  370. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/docs/wiki/sessions/messaging.md +0 -0
  371. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/docs/wiki/sessions/prompt-routing.md +0 -0
  372. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/docs/wiki/sessions/window-sizing.md +0 -0
  373. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/docs/wiki/sessions/worktree-sessions.md +0 -0
  374. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/docs/wiki/usage-limit-recovery.md +0 -0
  375. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/docs/wiki/voice/shim-contract.md +0 -0
  376. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/docs/wiki/voice/stt-cloud.md +0 -0
  377. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/docs/wiki/voice/stt-self-hosted.md +0 -0
  378. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/docs/wiki/voice/tts-self-hosted.md +0 -0
  379. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/pyproject.toml +0 -0
  380. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/tests/conftest.py +0 -0
  381. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/tests/e2e/test_portal_ui.py +0 -0
  382. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/tests/fixtures/sample_agentwire.yml +0 -0
  383. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/tests/fixtures/sample_config.yaml +0 -0
  384. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/tests/fixtures/sample_scheduler.yaml +0 -0
  385. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/tests/integration/test_council_portal.py +0 -0
  386. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/tests/integration/test_scheduler_board.py +0 -0
  387. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/tests/integration/test_send_verified_tmux.py +0 -0
  388. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/tests/integration/test_server_websockets.py +0 -0
  389. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/tests/integration/test_worktree_cmd.py +0 -0
  390. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/tests/unit/test_announcements.py +0 -0
  391. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/tests/unit/test_build_agent_command.py +0 -0
  392. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/tests/unit/test_channels.py +0 -0
  393. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/tests/unit/test_chrome_tabs.py +0 -0
  394. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/tests/unit/test_cli_commands.py +0 -0
  395. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/tests/unit/test_cli_output.py +0 -0
  396. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/tests/unit/test_cli_smoke.py +0 -0
  397. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/tests/unit/test_config.py +0 -0
  398. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/tests/unit/test_config_cli.py +0 -0
  399. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/tests/unit/test_control_plane_protection.py +0 -0
  400. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/tests/unit/test_core_created_by_rooting.py +0 -0
  401. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/tests/unit/test_council_cli.py +0 -0
  402. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/tests/unit/test_council_inbox.py +0 -0
  403. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/tests/unit/test_council_minutes.py +0 -0
  404. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/tests/unit/test_council_state.py +0 -0
  405. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/tests/unit/test_council_view.py +0 -0
  406. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/tests/unit/test_damage_control_bypass.py +0 -0
  407. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/tests/unit/test_damage_control_hooks.py +0 -0
  408. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/tests/unit/test_damage_control_sync.py +0 -0
  409. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/tests/unit/test_dangling_worktrees.py +0 -0
  410. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/tests/unit/test_devices.py +0 -0
  411. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/tests/unit/test_diff_cli.py +0 -0
  412. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/tests/unit/test_doctor_task_migration.py +0 -0
  413. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/tests/unit/test_doctor_voice.py +0 -0
  414. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/tests/unit/test_event_log.py +0 -0
  415. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/tests/unit/test_file_io.py +0 -0
  416. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/tests/unit/test_handoff_git_state.py +0 -0
  417. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/tests/unit/test_handoff_instructions.py +0 -0
  418. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/tests/unit/test_handoff_parser.py +0 -0
  419. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/tests/unit/test_handoff_renderer.py +0 -0
  420. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/tests/unit/test_history.py +0 -0
  421. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/tests/unit/test_hooks_install.py +0 -0
  422. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/tests/unit/test_idle_handler.py +0 -0
  423. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/tests/unit/test_idle_nag.py +0 -0
  424. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/tests/unit/test_inbox.py +0 -0
  425. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/tests/unit/test_init_command.py +0 -0
  426. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/tests/unit/test_install_parity.py +0 -0
  427. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/tests/unit/test_limits_tick_isolation.py +0 -0
  428. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/tests/unit/test_locking.py +0 -0
  429. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/tests/unit/test_mcp_server.py +0 -0
  430. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/tests/unit/test_mcp_tools_args.py +0 -0
  431. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/tests/unit/test_msg_cli.py +0 -0
  432. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/tests/unit/test_notify_cli.py +0 -0
  433. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/tests/unit/test_onboarding_reinit.py +0 -0
  434. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/tests/unit/test_palette_cli.py +0 -0
  435. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/tests/unit/test_pip_environment.py +0 -0
  436. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/tests/unit/test_portal_api.py +0 -0
  437. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/tests/unit/test_posture_default.py +0 -0
  438. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/tests/unit/test_project_config.py +0 -0
  439. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/tests/unit/test_prompt_router.py +0 -0
  440. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/tests/unit/test_push.py +0 -0
  441. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/tests/unit/test_rebuild_guard.py +0 -0
  442. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/tests/unit/test_repo_cli.py +0 -0
  443. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/tests/unit/test_roles.py +0 -0
  444. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/tests/unit/test_routes_snapshot.py +0 -0
  445. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/tests/unit/test_safety_commands.py +0 -0
  446. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/tests/unit/test_safety_disabled_rules.py +0 -0
  447. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/tests/unit/test_safety_escape_hatch.py +0 -0
  448. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/tests/unit/test_safety_heal.py +0 -0
  449. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/tests/unit/test_safety_kill_switch.py +0 -0
  450. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/tests/unit/test_scheduler.py +0 -0
  451. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/tests/unit/test_scheduler_parsing.py +0 -0
  452. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/tests/unit/test_scratchpad.py +0 -0
  453. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/tests/unit/test_security.py +0 -0
  454. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/tests/unit/test_server_async.py +0 -0
  455. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/tests/unit/test_server_pure.py +0 -0
  456. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/tests/unit/test_services.py +0 -0
  457. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/tests/unit/test_session_context.py +0 -0
  458. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/tests/unit/test_session_ready.py +0 -0
  459. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/tests/unit/test_shared_dir_guard.py +0 -0
  460. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/tests/unit/test_skill_install.py +0 -0
  461. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/tests/unit/test_speech_tags.py +0 -0
  462. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/tests/unit/test_ssh.py +0 -0
  463. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/tests/unit/test_stt_backend.py +0 -0
  464. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/tests/unit/test_stt_cloud.py +0 -0
  465. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/tests/unit/test_stt_engine.py +0 -0
  466. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/tests/unit/test_task_cli.py +0 -0
  467. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/tests/unit/test_tasks.py +0 -0
  468. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/tests/unit/test_tasks_cli.py +0 -0
  469. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/tests/unit/test_templating.py +0 -0
  470. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/tests/unit/test_terminal_resize.py +0 -0
  471. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/tests/unit/test_tmux_template.py +0 -0
  472. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/tests/unit/test_tts_engine_resolution.py +0 -0
  473. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/tests/unit/test_tts_local.py +0 -0
  474. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/tests/unit/test_tunnels_probe.py +0 -0
  475. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/tests/unit/test_unattended_env_isolation.py +0 -0
  476. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/tests/unit/test_usage_limit.py +0 -0
  477. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/tests/unit/test_validation.py +0 -0
  478. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/tests/unit/test_voice_status.py +0 -0
  479. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/tests/unit/test_wiki.py +0 -0
  480. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/tests/unit/test_wiki_audit.py +0 -0
  481. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/tests/unit/test_window_cycling_binding.py +0 -0
  482. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/tests/unit/test_worktree.py +0 -0
  483. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/tests/unit/test_worktree_branch_cleanup.py +0 -0
  484. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/tests/unit/test_worktree_layout.py +0 -0
  485. {agentwire_dev-1.59.0 → agentwire_dev-1.60.0}/tests/unit/test_worktree_registry.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: agentwire-dev
3
- Version: 1.59.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.59.0"
3
+ __version__ = "1.60.0"
@@ -404,6 +404,77 @@ def _render_task_migration_section() -> int:
404
404
  return len(unmigrated)
405
405
 
406
406
 
407
+ def _find_dead_managed_shims() -> list[dict]:
408
+ """Managed voice shims whose tmux session is alive but ``/health`` is dead.
409
+
410
+ The #734 failure mode: a wedged Kokoro (:8102) or Moonshine STT (:8101) shim
411
+ inside a live ``agentwire-kokoro``/``agentwire-stt`` session — say/transcribe
412
+ then silently fall back to browser voice/recognition with no error, and the
413
+ old session-existence-only ``ensure`` never relaunches it. Only the default
414
+ tier runs a managed shim, so we check that tier only, and reuse the same
415
+ ``_shim_session_state`` liveness predicate as ``start`` (SSOT).
416
+ """
417
+ from .config import load_config as load_config_typed
418
+ from .core import (
419
+ get_kokoro_session_name,
420
+ get_stt_session_name,
421
+ tmux_session_exists,
422
+ )
423
+ from .tts_cli import _shim_session_state
424
+
425
+ cfg = load_config_typed()
426
+ checks: list[tuple[str, str, int, str, str]] = []
427
+
428
+ if getattr(getattr(cfg, "tts", None), "backend", "default") == "default":
429
+ checks.append((
430
+ "Kokoro TTS", get_kokoro_session_name(), 8102,
431
+ "agentwire kokoro start", "say falls back to browser voice",
432
+ ))
433
+
434
+ if getattr(getattr(cfg, "stt", None), "backend", "default") == "default":
435
+ # Only the Moonshine path runs a shim; without it the default tier
436
+ # transcribes in the browser and there is nothing to probe.
437
+ from .stt import moonshine_importable
438
+
439
+ if moonshine_importable():
440
+ checks.append((
441
+ "Moonshine STT", get_stt_session_name(), 8101,
442
+ "agentwire stt start",
443
+ "transcription falls back to browser recognition",
444
+ ))
445
+
446
+ dead: list[dict] = []
447
+ for label, session, port, fix, impact in checks:
448
+ if not tmux_session_exists(session):
449
+ continue
450
+ live, status = _shim_session_state(session, port)
451
+ if not live:
452
+ dead.append({
453
+ "label": label, "session": session, "port": port,
454
+ "status": status, "fix": fix, "impact": impact,
455
+ })
456
+ return dead
457
+
458
+
459
+ def _render_shim_liveness_section() -> int:
460
+ """Doctor section: managed shim session alive but ``/health`` dead (#734)."""
461
+ dead = _find_dead_managed_shims()
462
+ if not dead:
463
+ print(" [ok] No dead-but-present voice shims")
464
+ return 0
465
+ for d in dead:
466
+ print(
467
+ f" [!!] {d['label']} shim session '{d['session']}' is alive but "
468
+ f":{d['port']}/health is not serving (state: "
469
+ f"{d['status'] or 'no response'}) — {d['impact']}."
470
+ )
471
+ print(
472
+ f" Self-heal: re-run `{dead[0]['fix']}` — it is now health-aware and "
473
+ "reaps a dead session before relaunching."
474
+ )
475
+ return len(dead)
476
+
477
+
407
478
  def cmd_doctor(args) -> int:
408
479
  """Auto-diagnose and fix common issues."""
409
480
  from .hooks_cli import _managed_file_state, _managed_hook_files, get_hooks_source
@@ -926,6 +997,17 @@ def cmd_doctor(args) -> int:
926
997
  except Exception as e:
927
998
  print(f" [..] Could not check project task migration: {e}")
928
999
 
1000
+ # 13. Managed voice shims (Kokoro :8102, Moonshine STT :8101) whose tmux
1001
+ # session is alive but whose /health is dead (#734). The old
1002
+ # session-existence-only idempotency masked a wedged engine forever, so
1003
+ # say/transcribe silently fell back to browser voice. Surfaced distinctly
1004
+ # here with the now-health-aware self-heal command.
1005
+ print("\nChecking managed voice shim liveness (#734)...")
1006
+ try:
1007
+ issues_found += _render_shim_liveness_section()
1008
+ except Exception as e:
1009
+ print(f" [..] Could not check managed voice shim liveness: {e}")
1010
+
929
1011
  # Summary
930
1012
  print()
931
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:
@@ -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()
@@ -0,0 +1,202 @@
1
+ """Health-aware managed-shim self-heal (#734).
2
+
3
+ A dead/wedged Kokoro (:8102) or Moonshine STT (:8101) shim inside a live tmux
4
+ session used to be treated as healthy forever (idempotency keyed on session
5
+ existence alone), so say/transcribe silently fell back to browser voice. These
6
+ tests pin the liveness predicate, the reuse-vs-reap decision in ``start``, and
7
+ the doctor surfacing — without touching any real tmux session or port.
8
+ """
9
+
10
+ from types import SimpleNamespace
11
+
12
+ import pytest
13
+
14
+ from agentwire import tts_cli
15
+
16
+ # === _shim_session_state: the shared liveness predicate ====================
17
+
18
+
19
+ def _patch_probe(monkeypatch, *, responded, status):
20
+ monkeypatch.setattr(
21
+ tts_cli, "_probe_shim_health", lambda port, timeout=2.0: (responded, status)
22
+ )
23
+
24
+
25
+ def test_state_ok_is_live(monkeypatch):
26
+ _patch_probe(monkeypatch, responded=True, status="ok")
27
+ assert tts_cli._shim_session_state("s", 8102) == (True, "ok")
28
+
29
+
30
+ @pytest.mark.parametrize("warming", ["loading", "downloading", "absent"])
31
+ def test_state_warming_is_live(monkeypatch, warming):
32
+ # A shim mid-warmup still answers /health — reuse it, never reap it.
33
+ _patch_probe(monkeypatch, responded=True, status=warming)
34
+ live, status = tts_cli._shim_session_state("s", 8102)
35
+ assert live is True
36
+ assert status == warming
37
+
38
+
39
+ def test_state_failed_is_not_live(monkeypatch):
40
+ # Terminal engine failure: the process answers but will never be ready.
41
+ _patch_probe(monkeypatch, responded=True, status="failed")
42
+ assert tts_cli._shim_session_state("s", 8102) == (False, "failed")
43
+
44
+
45
+ def test_state_no_response_young_is_live(monkeypatch):
46
+ # Just launched: the port may not be bound yet — give it the grace window.
47
+ _patch_probe(monkeypatch, responded=False, status=None)
48
+ monkeypatch.setattr(tts_cli, "_tmux_session_age", lambda s: 3.0)
49
+ assert tts_cli._shim_session_state("s", 8102, warmup_grace=25.0) == (True, "starting")
50
+
51
+
52
+ def test_state_no_response_old_is_dead(monkeypatch):
53
+ # Session has existed for hours but nothing answers — dead/wedged.
54
+ _patch_probe(monkeypatch, responded=False, status=None)
55
+ monkeypatch.setattr(tts_cli, "_tmux_session_age", lambda s: 9000.0)
56
+ assert tts_cli._shim_session_state("s", 8102, warmup_grace=25.0) == (False, None)
57
+
58
+
59
+ def test_state_no_response_unknown_age_is_dead(monkeypatch):
60
+ # Age unknowable (session vanished mid-probe) → not live.
61
+ _patch_probe(monkeypatch, responded=False, status=None)
62
+ monkeypatch.setattr(tts_cli, "_tmux_session_age", lambda s: None)
63
+ assert tts_cli._shim_session_state("s", 8102) == (False, None)
64
+
65
+
66
+ # === start commands: reuse when live, reap+relaunch when dead ==============
67
+
68
+
69
+ class _StartHarness:
70
+ """Records whether start reaped the session / launched a fresh one."""
71
+
72
+ def __init__(self, monkeypatch, module=tts_cli):
73
+ self.reaped = False
74
+ self.launched = False
75
+ monkeypatch.setattr(module, "tmux_session_exists", lambda s: True)
76
+ monkeypatch.setattr(module, "_reap_shim_session", self._reap)
77
+ monkeypatch.setattr(
78
+ module, "_resolve_shim_python", lambda: ("/usr/bin/python3", None, None)
79
+ )
80
+ monkeypatch.setattr(module, "load_config", lambda: {"stt": {}})
81
+ monkeypatch.setattr(module.subprocess, "run", self._run)
82
+
83
+ def _reap(self, session):
84
+ self.reaped = True
85
+
86
+ def _run(self, cmd, *a, **k):
87
+ # `tmux new-session` is the launch of a fresh shim.
88
+ if isinstance(cmd, list) and "new-session" in cmd:
89
+ self.launched = True
90
+ return SimpleNamespace(returncode=0, stdout="", stderr="")
91
+
92
+
93
+ def _kokoro_args():
94
+ return SimpleNamespace(port=None, host=None)
95
+
96
+
97
+ def _stt_args():
98
+ return SimpleNamespace(port=None, host=None, model=None, backend=None)
99
+
100
+
101
+ def test_kokoro_start_reuses_live_session(monkeypatch, capsys):
102
+ h = _StartHarness(monkeypatch)
103
+ monkeypatch.setattr(tts_cli, "_shim_session_state", lambda s, p: (True, "ok"))
104
+ rc = tts_cli.cmd_kokoro_start(_kokoro_args())
105
+ assert rc == 0
106
+ assert h.reaped is False and h.launched is False
107
+ assert "already running" in capsys.readouterr().out
108
+
109
+
110
+ def test_kokoro_start_reaps_and_relaunches_dead_session(monkeypatch, capsys):
111
+ h = _StartHarness(monkeypatch)
112
+ monkeypatch.setattr(tts_cli, "_shim_session_state", lambda s, p: (False, None))
113
+ rc = tts_cli.cmd_kokoro_start(_kokoro_args())
114
+ assert rc == 0
115
+ assert h.reaped is True and h.launched is True
116
+ out = capsys.readouterr().out
117
+ assert "not serving" in out and "already running" not in out
118
+
119
+
120
+ def test_stt_start_reuses_live_session(monkeypatch, capsys):
121
+ h = _StartHarness(monkeypatch)
122
+ monkeypatch.setattr(tts_cli, "_shim_session_state", lambda s, p: (True, "ok"))
123
+ rc = tts_cli.cmd_stt_start(_stt_args())
124
+ assert rc == 0
125
+ assert h.reaped is False and h.launched is False
126
+ assert "already running" in capsys.readouterr().out
127
+
128
+
129
+ def test_stt_start_reaps_and_relaunches_dead_session(monkeypatch, capsys):
130
+ h = _StartHarness(monkeypatch)
131
+ monkeypatch.setattr(tts_cli, "_shim_session_state", lambda s, p: (False, "failed"))
132
+ rc = tts_cli.cmd_stt_start(_stt_args())
133
+ assert rc == 0
134
+ assert h.reaped is True and h.launched is True
135
+ out = capsys.readouterr().out
136
+ assert "not serving" in out and "already running" not in out
137
+
138
+
139
+ # === doctor: flag a present-but-dead shim, ignore warming / absent =========
140
+
141
+
142
+ def _patch_doctor(monkeypatch, *, tts="default", stt="default", moonshine=True):
143
+ from agentwire import doctor_cli
144
+
145
+ cfg = SimpleNamespace(
146
+ tts=SimpleNamespace(backend=tts),
147
+ stt=SimpleNamespace(backend=stt),
148
+ )
149
+ # _find_dead_managed_shims imports these lazily from their home modules.
150
+ import agentwire.config as cfg_mod
151
+ import agentwire.core as core_mod
152
+ import agentwire.stt as stt_mod
153
+
154
+ monkeypatch.setattr(cfg_mod, "load_config", lambda: cfg)
155
+ monkeypatch.setattr(core_mod, "get_kokoro_session_name", lambda: "agentwire-kokoro")
156
+ monkeypatch.setattr(core_mod, "get_stt_session_name", lambda: "agentwire-stt")
157
+ monkeypatch.setattr(stt_mod, "moonshine_importable", lambda: moonshine)
158
+ return doctor_cli
159
+
160
+
161
+ def test_doctor_flags_dead_kokoro_shim(monkeypatch):
162
+ doctor_cli = _patch_doctor(monkeypatch, stt="none")
163
+ from agentwire import core as core_mod
164
+
165
+ monkeypatch.setattr(core_mod, "tmux_session_exists", lambda s: True)
166
+ monkeypatch.setattr(tts_cli, "_shim_session_state", lambda s, p: (False, None))
167
+
168
+ dead = doctor_cli._find_dead_managed_shims()
169
+ assert len(dead) == 1
170
+ assert dead[0]["label"] == "Kokoro TTS" and dead[0]["port"] == 8102
171
+
172
+
173
+ def test_doctor_ignores_warming_shim(monkeypatch):
174
+ doctor_cli = _patch_doctor(monkeypatch, stt="none")
175
+ from agentwire import core as core_mod
176
+
177
+ monkeypatch.setattr(core_mod, "tmux_session_exists", lambda s: True)
178
+ monkeypatch.setattr(tts_cli, "_shim_session_state", lambda s, p: (True, "loading"))
179
+
180
+ assert doctor_cli._find_dead_managed_shims() == []
181
+
182
+
183
+ def test_doctor_ignores_absent_session(monkeypatch):
184
+ doctor_cli = _patch_doctor(monkeypatch)
185
+ from agentwire import core as core_mod
186
+
187
+ # No tmux session → nothing to self-heal, not a dead shim.
188
+ monkeypatch.setattr(core_mod, "tmux_session_exists", lambda s: False)
189
+ monkeypatch.setattr(tts_cli, "_shim_session_state", lambda s, p: (False, None))
190
+
191
+ assert doctor_cli._find_dead_managed_shims() == []
192
+
193
+
194
+ def test_doctor_skips_stt_when_moonshine_absent(monkeypatch):
195
+ # STT default tier without Moonshine transcribes in-browser: no shim to flag.
196
+ doctor_cli = _patch_doctor(monkeypatch, tts="custom", moonshine=False)
197
+ from agentwire import core as core_mod
198
+
199
+ monkeypatch.setattr(core_mod, "tmux_session_exists", lambda s: True)
200
+ monkeypatch.setattr(tts_cli, "_shim_session_state", lambda s, p: (False, None))
201
+
202
+ assert doctor_cli._find_dead_managed_shims() == []
File without changes
File without changes
File without changes