agentwire-dev 1.65.2__tar.gz → 1.65.3__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 (509) hide show
  1. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/PKG-INFO +1 -1
  2. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/__init__.py +1 -1
  3. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/mcp_core.py +23 -0
  4. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/mcp_session.py +5 -0
  5. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/send_cli.py +87 -5
  6. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/server.py +14 -3
  7. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/session_ready.py +15 -0
  8. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/tests/unit/test_cli_commands.py +161 -8
  9. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/tests/unit/test_mcp_server.py +51 -0
  10. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/tests/unit/test_mcp_tools_args.py +4 -0
  11. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/tests/unit/test_portal_api.py +64 -0
  12. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/tests/unit/test_session_ready.py +22 -1
  13. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/.agentwire.yml.example +0 -0
  14. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/.claude/commands/handoff.md +0 -0
  15. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/.claude/skills/wiki/SKILL.md +0 -0
  16. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/.github/FUNDING.yml +0 -0
  17. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
  18. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
  19. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/.github/ISSUE_TEMPLATE/question.md +0 -0
  20. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
  21. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/.github/workflows/pytest.yml +0 -0
  22. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/.github/workflows/ruff.yml +0 -0
  23. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/.github/workflows/security.yml +0 -0
  24. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/.github/workflows/tts-smoke.yml +0 -0
  25. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/.gitignore +0 -0
  26. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/AGENTS.md +0 -0
  27. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/CODE_OF_CONDUCT.md +0 -0
  28. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/CONTRIBUTING.md +0 -0
  29. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/Dockerfile.local +0 -0
  30. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/LICENSE +0 -0
  31. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/README.md +0 -0
  32. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/RELEASING.md +0 -0
  33. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/SECURITY.md +0 -0
  34. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/SPONSORS.md +0 -0
  35. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/__main__.py +0 -0
  36. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/agents/__init__.py +0 -0
  37. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/agents/base.py +0 -0
  38. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/agents/tmux.py +0 -0
  39. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/cached_status.py +0 -0
  40. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/channels/__init__.py +0 -0
  41. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/channels/base.py +0 -0
  42. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/channels/email.py +0 -0
  43. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/channels/push.py +0 -0
  44. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/channels/quo.py +0 -0
  45. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/channels_cli.py +0 -0
  46. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/chrome_tabs.py +0 -0
  47. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/completion.py +0 -0
  48. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/config.py +0 -0
  49. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/config_cli.py +0 -0
  50. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/core.py +0 -0
  51. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/council/__init__.py +0 -0
  52. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/council/cli.py +0 -0
  53. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/council/inbox.py +0 -0
  54. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/council/minutes.py +0 -0
  55. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/council/state.py +0 -0
  56. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/council/view.py +0 -0
  57. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/devices.py +0 -0
  58. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/diff_cli.py +0 -0
  59. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/doctor_cli.py +0 -0
  60. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/doctor_voice.py +0 -0
  61. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/ensure_cli.py +0 -0
  62. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/fetch.py +0 -0
  63. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/handoff/__init__.py +0 -0
  64. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/handoff/git_state.py +0 -0
  65. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/handoff/instructions.py +0 -0
  66. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/handoff/parser.py +0 -0
  67. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/handoff/renderer.py +0 -0
  68. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/handoff/schema.py +0 -0
  69. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/handoff_cli.py +0 -0
  70. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/history.py +0 -0
  71. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/history_cli.py +0 -0
  72. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/hooks/__init__.py +0 -0
  73. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/hooks/agentwire-permission.sh +0 -0
  74. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/hooks/damage-control/__init__.py +0 -0
  75. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/hooks/damage-control/audit_logger.py +0 -0
  76. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/hooks/damage-control/bash-tool-damage-control.py +0 -0
  77. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/hooks/damage-control/edit-tool-damage-control.py +0 -0
  78. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/hooks/damage-control/mcp-tool-damage-control.py +0 -0
  79. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/hooks/damage-control/read-tool-damage-control.py +0 -0
  80. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/hooks/damage-control/rules/agentwire.yaml +0 -0
  81. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/hooks/damage-control/rules/aws.yaml +0 -0
  82. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/hooks/damage-control/rules/cloud-hosting.yaml +0 -0
  83. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/hooks/damage-control/rules/containers.yaml +0 -0
  84. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/hooks/damage-control/rules/control-plane.yaml +0 -0
  85. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/hooks/damage-control/rules/core.yaml +0 -0
  86. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/hooks/damage-control/rules/databases.yaml +0 -0
  87. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/hooks/damage-control/rules/firebase.yaml +0 -0
  88. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/hooks/damage-control/rules/gcp.yaml +0 -0
  89. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/hooks/damage-control/rules/git.yaml +0 -0
  90. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/hooks/damage-control/rules/gws.yaml +0 -0
  91. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/hooks/damage-control/rules/infrastructure.yaml +0 -0
  92. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/hooks/damage-control/rules/outbound.yaml +0 -0
  93. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/hooks/damage-control/rules/publish.yaml +0 -0
  94. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/hooks/damage-control/rules/remote.yaml +0 -0
  95. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/hooks/damage-control/write-tool-damage-control.py +0 -0
  96. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/hooks/idle-handler.sh +0 -0
  97. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/hooks/queue-processor.sh +0 -0
  98. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/hooks_cli.py +0 -0
  99. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/inbox.py +0 -0
  100. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/limits_cli.py +0 -0
  101. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/listen.py +0 -0
  102. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/locking.py +0 -0
  103. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/machine_cli.py +0 -0
  104. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/mcp_channels.py +0 -0
  105. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/mcp_chrome.py +0 -0
  106. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/mcp_cli.py +0 -0
  107. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/mcp_council.py +0 -0
  108. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/mcp_desktop.py +0 -0
  109. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/mcp_handoff.py +0 -0
  110. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/mcp_history.py +0 -0
  111. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/mcp_listen.py +0 -0
  112. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/mcp_lock.py +0 -0
  113. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/mcp_machine.py +0 -0
  114. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/mcp_msg.py +0 -0
  115. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/mcp_notify.py +0 -0
  116. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/mcp_pane.py +0 -0
  117. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/mcp_projects.py +0 -0
  118. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/mcp_scheduler.py +0 -0
  119. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/mcp_scratchpad.py +0 -0
  120. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/mcp_server.py +0 -0
  121. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/mcp_services.py +0 -0
  122. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/mcp_status.py +0 -0
  123. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/mcp_task.py +0 -0
  124. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/mcp_tunnels.py +0 -0
  125. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/mcp_voice.py +0 -0
  126. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/mcp_wiki.py +0 -0
  127. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/mcp_worktree.py +0 -0
  128. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/msg_cli.py +0 -0
  129. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/network.py +0 -0
  130. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/notify_cli.py +0 -0
  131. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/onboarding.py +0 -0
  132. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/palette_cli.py +0 -0
  133. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/pane_cli.py +0 -0
  134. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/pane_manager.py +0 -0
  135. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/portal_cli.py +0 -0
  136. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/project_config.py +0 -0
  137. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/projects.py +0 -0
  138. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/prompt_router.py +0 -0
  139. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/prompts_cli.py +0 -0
  140. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/push_cli.py +0 -0
  141. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/push_store.py +0 -0
  142. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/repo_cli.py +0 -0
  143. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/research.py +0 -0
  144. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/roles/__init__.py +0 -0
  145. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/roles/agentwire.md +0 -0
  146. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/roles/anchor.md +0 -0
  147. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/roles/chatbot.md +0 -0
  148. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/roles/contributor.md +0 -0
  149. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/roles/correspondent.md +0 -0
  150. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/roles/council-brain.md +0 -0
  151. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/roles/council-conscience.md +0 -0
  152. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/roles/council-critic.md +0 -0
  153. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/roles/council-devils-advocate.md +0 -0
  154. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/roles/council-gut.md +0 -0
  155. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/roles/council-historian.md +0 -0
  156. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/roles/council-member.md +0 -0
  157. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/roles/council-orchestrator.md +0 -0
  158. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/roles/init.md +0 -0
  159. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/roles/notifications.md +0 -0
  160. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/roles/orchestrator.md +0 -0
  161. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/roles/reviewer-worktree.md +0 -0
  162. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/roles/reviewer.md +0 -0
  163. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/roles/soul.md +0 -0
  164. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/roles/task-runner.md +0 -0
  165. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/roles/voice.md +0 -0
  166. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/roles/worker-worktree.md +0 -0
  167. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/roles/worker.md +0 -0
  168. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/roles_cli.py +0 -0
  169. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/routes/__init__.py +0 -0
  170. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/routes/artifacts.py +0 -0
  171. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/routes/config.py +0 -0
  172. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/routes/council.py +0 -0
  173. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/routes/desktop.py +0 -0
  174. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/routes/history.py +0 -0
  175. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/routes/machines.py +0 -0
  176. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/routes/notify.py +0 -0
  177. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/routes/palette.py +0 -0
  178. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/routes/permission.py +0 -0
  179. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/routes/projects.py +0 -0
  180. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/routes/push.py +0 -0
  181. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/routes/safety.py +0 -0
  182. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/routes/scheduler.py +0 -0
  183. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/routes/scratchpad.py +0 -0
  184. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/routes/sessions.py +0 -0
  185. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/routes/sessions_admin.py +0 -0
  186. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/routes/voice.py +0 -0
  187. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/safety/__init__.py +0 -0
  188. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/safety/_core.py +0 -0
  189. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/safety_cli.py +0 -0
  190. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/safety_commands.py +0 -0
  191. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/scheduler/__init__.py +0 -0
  192. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/scheduler/dispatch.py +0 -0
  193. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/scheduler/gates.py +0 -0
  194. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/scheduler/loop.py +0 -0
  195. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/scheduler/models.py +0 -0
  196. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/scheduler/report.py +0 -0
  197. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/scheduler/schedule.py +0 -0
  198. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/scheduler/state.py +0 -0
  199. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/scheduler/zombie.py +0 -0
  200. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/scheduler_cli.py +0 -0
  201. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/scratchpad.py +0 -0
  202. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/security.py +0 -0
  203. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/services.py +0 -0
  204. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/session_cli.py +0 -0
  205. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/session_context.py +0 -0
  206. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/ssh.py +0 -0
  207. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/static/agentwire-splash-logo-layers--agentwire-text.png +0 -0
  208. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/static/agentwire-splash-logo-layers--echo-claw-fg.png +0 -0
  209. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/static/agentwire-splash-logo-layers--echo.png +0 -0
  210. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/static/agentwire-splash-logo-layers--telephone.png +0 -0
  211. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/static/agentwire-splash-logo-layers--tree.png +0 -0
  212. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/static/announcements.json +0 -0
  213. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/static/apple-touch-icon.png +0 -0
  214. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/static/css/desktop.css +0 -0
  215. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/static/css/mobile.css +0 -0
  216. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/static/favicon-32.png +0 -0
  217. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/static/favicon-64.png +0 -0
  218. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/static/icons/sessions/bear.webp +0 -0
  219. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/static/icons/sessions/cat.webp +0 -0
  220. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/static/icons/sessions/crown.webp +0 -0
  221. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/static/icons/sessions/custom/agentwire-portal.webp +0 -0
  222. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/static/icons/sessions/custom/agentwire-tts.webp +0 -0
  223. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/static/icons/sessions/custom/agentwire.webp +0 -0
  224. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/static/icons/sessions/deer.webp +0 -0
  225. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/static/icons/sessions/drone.webp +0 -0
  226. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/static/icons/sessions/eagle.webp +0 -0
  227. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/static/icons/sessions/fox.webp +0 -0
  228. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/static/icons/sessions/hawk.webp +0 -0
  229. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/static/icons/sessions/horse.webp +0 -0
  230. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/static/icons/sessions/lion.webp +0 -0
  231. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/static/icons/sessions/rabbit.webp +0 -0
  232. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/static/icons/sessions/robot.webp +0 -0
  233. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/static/icons/sessions/tiger.webp +0 -0
  234. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/static/icons/sessions/wolf.webp +0 -0
  235. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/static/img/icon-192.png +0 -0
  236. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/static/img/icon-512.png +0 -0
  237. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/static/js/.gitkeep +0 -0
  238. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/static/js/announcement-modal.js +0 -0
  239. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/static/js/api.js +0 -0
  240. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/static/js/artifact-window.js +0 -0
  241. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/static/js/card-terminal.js +0 -0
  242. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/static/js/collage.js +0 -0
  243. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/static/js/command-palette.js +0 -0
  244. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/static/js/council-window.js +0 -0
  245. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/static/js/dead-key-suppressor.js +0 -0
  246. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/static/js/desktop-manager.js +0 -0
  247. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/static/js/desktop.js +0 -0
  248. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/static/js/help-modal.js +0 -0
  249. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/static/js/icon-manager.js +0 -0
  250. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/static/js/lineage.js +0 -0
  251. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/static/js/mobile.js +0 -0
  252. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/static/js/notification-prefs.js +0 -0
  253. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/static/js/notifications-panel.js +0 -0
  254. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/static/js/ptt.js +0 -0
  255. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/static/js/push-client.js +0 -0
  256. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/static/js/review-window.js +0 -0
  257. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/static/js/safety-shared.js +0 -0
  258. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/static/js/safety-window.js +0 -0
  259. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/static/js/scratchpad.js +0 -0
  260. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/static/js/service-classification.js +0 -0
  261. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/static/js/session-hud-controller.js +0 -0
  262. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/static/js/session-hud-notices.js +0 -0
  263. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/static/js/session-hud-spawn.js +0 -0
  264. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/static/js/session-hud.js +0 -0
  265. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/static/js/session-id.js +0 -0
  266. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/static/js/session-window.js +0 -0
  267. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/static/js/shortcuts.js +0 -0
  268. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/static/js/sidebar/artifacts-section.js +0 -0
  269. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/static/js/sidebar/config-section.js +0 -0
  270. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/static/js/sidebar/council-section.js +0 -0
  271. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/static/js/sidebar/machines-section.js +0 -0
  272. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/static/js/sidebar/projects-section.js +0 -0
  273. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/static/js/sidebar/safety-section.js +0 -0
  274. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/static/js/sidebar/scheduler-section.js +0 -0
  275. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/static/js/sidebar/services-section.js +0 -0
  276. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/static/js/sidebar/sessions-section.js +0 -0
  277. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/static/js/sidebar.js +0 -0
  278. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/static/js/spawn-ghost.js +0 -0
  279. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/static/js/terminal-font-prefs.js +0 -0
  280. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/static/js/terminal-pane.js +0 -0
  281. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/static/js/tile-manager.js +0 -0
  282. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/static/js/toast.js +0 -0
  283. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/static/js/token-modal.js +0 -0
  284. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/static/js/topology-render.js +0 -0
  285. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/static/js/utils/ansi.js +0 -0
  286. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/static/js/utils/rich-text.js +0 -0
  287. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/static/js/utils/swipe.js +0 -0
  288. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/static/js/voice/autosend-prefs.js +0 -0
  289. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/static/js/voice/browser-stt.js +0 -0
  290. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/static/js/voice/browser-tts.js +0 -0
  291. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/static/js/voice/jargon.js +0 -0
  292. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/static/js/voice/prompt.js +0 -0
  293. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/static/js/winbox.bundle.min.js +0 -0
  294. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/static/js/workspace-window.js +0 -0
  295. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/static/manifest.webmanifest +0 -0
  296. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/static/service-worker.js +0 -0
  297. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/static/topology-harness.html +0 -0
  298. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/stt/__init__.py +0 -0
  299. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/stt/base.py +0 -0
  300. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/stt/cloud.py +0 -0
  301. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/stt/engine.py +0 -0
  302. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/stt/local.py +0 -0
  303. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/stt/server_backend.py +0 -0
  304. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/stt/stt_server.py +0 -0
  305. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/system_cli.py +0 -0
  306. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/tabs_cli.py +0 -0
  307. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/tasks.py +0 -0
  308. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/tasks_cli.py +0 -0
  309. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/templates/__init__.py +0 -0
  310. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/templates/base.html +0 -0
  311. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/templates/council/minutes.html.j2 +0 -0
  312. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/templates/desktop.html +0 -0
  313. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/templates/email_notification.html +0 -0
  314. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/templates/handoff/show-the-story.html.j2 +0 -0
  315. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/templates/handoff/theme.css.j2 +0 -0
  316. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/templates/mobile.html +0 -0
  317. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/templates/pair.html +0 -0
  318. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/templates/tmux.conf +0 -0
  319. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/templating.py +0 -0
  320. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/tooldefs/aws.yaml +0 -0
  321. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/tooldefs/docker.yaml +0 -0
  322. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/tooldefs/gcp.yaml +0 -0
  323. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/tooldefs/gh.yaml +0 -0
  324. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/tooldefs/git.yaml +0 -0
  325. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/tooldefs/gws.yaml +0 -0
  326. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/tooldefs/kubectl.yaml +0 -0
  327. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/tooldefs/npm.yaml +0 -0
  328. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/tooldefs/terraform.yaml +0 -0
  329. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/tooldefs/uv.yaml +0 -0
  330. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/tts/__init__.py +0 -0
  331. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/tts/audio.py +0 -0
  332. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/tts/base.py +0 -0
  333. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/tts/engines/__init__.py +0 -0
  334. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/tts/engines/chatterbox.py +0 -0
  335. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/tts/engines/kokoro.py +0 -0
  336. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/tts/engines/zonos.py +0 -0
  337. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/tts/kokoro_server.py +0 -0
  338. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/tts/local.py +0 -0
  339. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/tts/registry.py +0 -0
  340. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/tts_cli.py +0 -0
  341. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/tts_server.py +0 -0
  342. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/tunnels.py +0 -0
  343. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/tunnels_cli.py +0 -0
  344. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/usage_limit.py +0 -0
  345. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/utils/__init__.py +0 -0
  346. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/utils/chunker.py +0 -0
  347. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/utils/event_log.py +0 -0
  348. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/utils/file_io.py +0 -0
  349. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/utils/paths.py +0 -0
  350. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/utils/speech.py +0 -0
  351. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/utils/subprocess.py +0 -0
  352. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/validation.py +0 -0
  353. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/voice_status.py +0 -0
  354. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/wiki.py +0 -0
  355. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/wiki_audit.py +0 -0
  356. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/wiki_cli.py +0 -0
  357. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/worktree.py +0 -0
  358. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/agentwire/worktree_registry.py +0 -0
  359. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/docs/decisions/obsidian-second-brain.md +0 -0
  360. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/docs/design/session-card-fields.md +0 -0
  361. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/docs/design/session-card-recommendation.md +0 -0
  362. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/docs/logo.png +0 -0
  363. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/docs/wiki/INDEX.md +0 -0
  364. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/docs/wiki/architecture.md +0 -0
  365. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/docs/wiki/briefing-mode.md +0 -0
  366. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/docs/wiki/communication/channels.md +0 -0
  367. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/docs/wiki/communication/hammerspoon.md +0 -0
  368. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/docs/wiki/communication/handoff.md +0 -0
  369. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/docs/wiki/concepts.md +0 -0
  370. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/docs/wiki/council.md +0 -0
  371. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/docs/wiki/deployment/remote-access.md +0 -0
  372. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/docs/wiki/deployment/remote-machines.md +0 -0
  373. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/docs/wiki/glossary.md +0 -0
  374. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/docs/wiki/integrations/gws-google-workspace-cli.md +0 -0
  375. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/docs/wiki/internals/damage-control.md +0 -0
  376. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/docs/wiki/internals/parallel-refactor.md +0 -0
  377. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/docs/wiki/internals/portal.md +0 -0
  378. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/docs/wiki/internals/session-topology.md +0 -0
  379. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/docs/wiki/internals/shell-escaping.md +0 -0
  380. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/docs/wiki/internals/troubleshooting.md +0 -0
  381. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/docs/wiki/internals/window-collage.md +0 -0
  382. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/docs/wiki/quickstart.md +0 -0
  383. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/docs/wiki/research/briefing-mode-feasibility.md +0 -0
  384. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/docs/wiki/research/orchestration-transport-alternatives.md +0 -0
  385. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/docs/wiki/scheduling/scheduled-workloads.md +0 -0
  386. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/docs/wiki/security/damage-control-hardening.md +0 -0
  387. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/docs/wiki/security/pip-audit.md +0 -0
  388. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/docs/wiki/security/remote-access-hardening.md +0 -0
  389. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/docs/wiki/security/secrets.md +0 -0
  390. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/docs/wiki/services.md +0 -0
  391. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/docs/wiki/sessions/claude-code-auto-mode.md +0 -0
  392. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/docs/wiki/sessions/messaging.md +0 -0
  393. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/docs/wiki/sessions/prompt-routing.md +0 -0
  394. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/docs/wiki/sessions/window-sizing.md +0 -0
  395. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/docs/wiki/sessions/worktree-sessions.md +0 -0
  396. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/docs/wiki/usage-limit-recovery.md +0 -0
  397. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/docs/wiki/voice/shim-contract.md +0 -0
  398. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/docs/wiki/voice/stt-cloud.md +0 -0
  399. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/docs/wiki/voice/stt-self-hosted.md +0 -0
  400. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/docs/wiki/voice/tts-self-hosted.md +0 -0
  401. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/pyproject.toml +0 -0
  402. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/tests/conftest.py +0 -0
  403. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/tests/e2e/test_portal_ui.py +0 -0
  404. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/tests/fixtures/sample_agentwire.yml +0 -0
  405. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/tests/fixtures/sample_config.yaml +0 -0
  406. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/tests/fixtures/sample_scheduler.yaml +0 -0
  407. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/tests/integration/test_council_portal.py +0 -0
  408. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/tests/integration/test_scheduler_board.py +0 -0
  409. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/tests/integration/test_send_verified_tmux.py +0 -0
  410. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/tests/integration/test_server_websockets.py +0 -0
  411. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/tests/integration/test_worktree_cmd.py +0 -0
  412. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/tests/unit/test_announcements.py +0 -0
  413. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/tests/unit/test_build_agent_command.py +0 -0
  414. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/tests/unit/test_channels.py +0 -0
  415. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/tests/unit/test_chrome_tabs.py +0 -0
  416. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/tests/unit/test_cli_output.py +0 -0
  417. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/tests/unit/test_cli_smoke.py +0 -0
  418. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/tests/unit/test_config.py +0 -0
  419. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/tests/unit/test_config_cli.py +0 -0
  420. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/tests/unit/test_control_plane_protection.py +0 -0
  421. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/tests/unit/test_core_created_by_rooting.py +0 -0
  422. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/tests/unit/test_council_cli.py +0 -0
  423. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/tests/unit/test_council_inbox.py +0 -0
  424. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/tests/unit/test_council_minutes.py +0 -0
  425. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/tests/unit/test_council_state.py +0 -0
  426. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/tests/unit/test_council_view.py +0 -0
  427. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/tests/unit/test_damage_control_bypass.py +0 -0
  428. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/tests/unit/test_damage_control_hooks.py +0 -0
  429. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/tests/unit/test_damage_control_sync.py +0 -0
  430. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/tests/unit/test_dangling_worktrees.py +0 -0
  431. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/tests/unit/test_devices.py +0 -0
  432. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/tests/unit/test_diff_cli.py +0 -0
  433. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/tests/unit/test_doctor_scheduler_staleness.py +0 -0
  434. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/tests/unit/test_doctor_task_migration.py +0 -0
  435. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/tests/unit/test_doctor_voice.py +0 -0
  436. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/tests/unit/test_event_log.py +0 -0
  437. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/tests/unit/test_file_io.py +0 -0
  438. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/tests/unit/test_guarded_launch_command.py +0 -0
  439. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/tests/unit/test_handoff_git_state.py +0 -0
  440. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/tests/unit/test_handoff_instructions.py +0 -0
  441. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/tests/unit/test_handoff_parser.py +0 -0
  442. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/tests/unit/test_handoff_renderer.py +0 -0
  443. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/tests/unit/test_history.py +0 -0
  444. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/tests/unit/test_hooks_install.py +0 -0
  445. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/tests/unit/test_idle_handler.py +0 -0
  446. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/tests/unit/test_idle_nag.py +0 -0
  447. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/tests/unit/test_inbox.py +0 -0
  448. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/tests/unit/test_init_command.py +0 -0
  449. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/tests/unit/test_install_parity.py +0 -0
  450. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/tests/unit/test_limits_tick_isolation.py +0 -0
  451. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/tests/unit/test_locking.py +0 -0
  452. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/tests/unit/test_msg_cli.py +0 -0
  453. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/tests/unit/test_notify_cli.py +0 -0
  454. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/tests/unit/test_onboarding_reinit.py +0 -0
  455. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/tests/unit/test_palette_cli.py +0 -0
  456. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/tests/unit/test_pip_environment.py +0 -0
  457. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/tests/unit/test_posture_default.py +0 -0
  458. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/tests/unit/test_project_config.py +0 -0
  459. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/tests/unit/test_projects_registry.py +0 -0
  460. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/tests/unit/test_prompt_router.py +0 -0
  461. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/tests/unit/test_push.py +0 -0
  462. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/tests/unit/test_rebuild_guard.py +0 -0
  463. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/tests/unit/test_repo_cli.py +0 -0
  464. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/tests/unit/test_rich_text_js.py +0 -0
  465. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/tests/unit/test_roles.py +0 -0
  466. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/tests/unit/test_routes_snapshot.py +0 -0
  467. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/tests/unit/test_safety_commands.py +0 -0
  468. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/tests/unit/test_safety_disabled_rules.py +0 -0
  469. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/tests/unit/test_safety_escape_hatch.py +0 -0
  470. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/tests/unit/test_safety_heal.py +0 -0
  471. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/tests/unit/test_safety_kill_switch.py +0 -0
  472. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/tests/unit/test_scheduler.py +0 -0
  473. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/tests/unit/test_scheduler_parsing.py +0 -0
  474. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/tests/unit/test_scheduler_zombie.py +0 -0
  475. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/tests/unit/test_scratchpad.py +0 -0
  476. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/tests/unit/test_security.py +0 -0
  477. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/tests/unit/test_server_async.py +0 -0
  478. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/tests/unit/test_server_pure.py +0 -0
  479. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/tests/unit/test_services.py +0 -0
  480. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/tests/unit/test_session_context.py +0 -0
  481. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/tests/unit/test_session_created_by_env.py +0 -0
  482. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/tests/unit/test_shared_dir_guard.py +0 -0
  483. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/tests/unit/test_shim_selfheal.py +0 -0
  484. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/tests/unit/test_skill_install.py +0 -0
  485. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/tests/unit/test_speech_tags.py +0 -0
  486. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/tests/unit/test_ssh.py +0 -0
  487. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/tests/unit/test_stt_backend.py +0 -0
  488. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/tests/unit/test_stt_cloud.py +0 -0
  489. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/tests/unit/test_stt_engine.py +0 -0
  490. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/tests/unit/test_task_cli.py +0 -0
  491. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/tests/unit/test_tasks.py +0 -0
  492. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/tests/unit/test_tasks_cli.py +0 -0
  493. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/tests/unit/test_templating.py +0 -0
  494. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/tests/unit/test_terminal_resize.py +0 -0
  495. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/tests/unit/test_tmux_template.py +0 -0
  496. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/tests/unit/test_tts_engine_resolution.py +0 -0
  497. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/tests/unit/test_tts_local.py +0 -0
  498. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/tests/unit/test_tunnels_probe.py +0 -0
  499. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/tests/unit/test_unattended_env_isolation.py +0 -0
  500. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/tests/unit/test_usage_limit.py +0 -0
  501. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/tests/unit/test_validation.py +0 -0
  502. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/tests/unit/test_voice_status.py +0 -0
  503. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/tests/unit/test_wiki.py +0 -0
  504. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/tests/unit/test_wiki_audit.py +0 -0
  505. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/tests/unit/test_window_cycling_binding.py +0 -0
  506. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/tests/unit/test_worktree.py +0 -0
  507. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/tests/unit/test_worktree_branch_cleanup.py +0 -0
  508. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/tests/unit/test_worktree_layout.py +0 -0
  509. {agentwire_dev-1.65.2 → agentwire_dev-1.65.3}/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.65.2
3
+ Version: 1.65.3
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.65.2"
3
+ __version__ = "1.65.3"
@@ -162,11 +162,34 @@ def _delivery_result(data: dict, where: str) -> str:
162
162
  returns ``verified``: True (landed), False (sent but not seen — likely a
163
163
  busy/booting pane that dropped it), or None (remote — unverifiable across
164
164
  SSH). Surface that instead of a blind "sent".
165
+
166
+ A ``False`` verify from a *session*-level send no longer just hands the
167
+ problem back to whichever caller reads this string (#834) — the CLI
168
+ falls back to the durable msg inbox (retried across ticks, dead-lettered
169
+ + emailed on true exhaustion) when the direct paste can't be confirmed,
170
+ so report THAT outcome rather than telling the caller to notice and
171
+ resend by hand. A worker *pane* send has no such fallback (the msg inbox
172
+ only addresses sessions, not individual panes) — ``data`` won't carry a
173
+ ``fallback`` key at all in that case, distinguishing "not attempted"
174
+ from "attempted and failed" so this never claims a fallback that never
175
+ ran.
165
176
  """
166
177
  verified = data.get("verified")
167
178
  if verified is True:
168
179
  return f"Message delivered {where} (verified in pane)."
169
180
  if verified is False:
181
+ if "fallback" in data:
182
+ if data.get("fallback") == "already_delivered":
183
+ return (f"Message sent {where} — the pane confirmation was ambiguous, but the "
184
+ f"message is already visible on scrollback, so it was in fact delivered. "
185
+ f"No action needed.")
186
+ if data.get("fallback") == "inbox":
187
+ return (f"Message sent {where} but delivery could NOT be verified in the pane — "
188
+ f"queued to its msg inbox instead, which guarantees delivery (retried "
189
+ f"automatically, dead-lettered + emailed to the owner only if it truly "
190
+ f"can't land). No action needed.")
191
+ return (f"Message sent {where} but delivery could NOT be verified, AND the msg-inbox "
192
+ f"fallback also failed — this message may be lost. Check the pane or resend.")
170
193
  return (f"Message sent {where} but delivery could NOT be verified — it may "
171
194
  f"have been dropped (busy/booting pane). Check the pane or resend.")
172
195
  if verified is None and "verified" in data:
@@ -227,6 +227,11 @@ def session_send(session: str, message: str) -> str:
227
227
  f"{message}"
228
228
  )
229
229
  args = ["send", "-s", session, "--verify", message]
230
+ if caller:
231
+ # Attributes a msg-inbox delivery fallback to the real caller instead
232
+ # of the generic "agentwire" (#835 review) — the CLI subprocess can't
233
+ # auto-detect the caller across the MCP boundary itself.
234
+ args.extend(["--caller-session", caller])
230
235
  data = run_agentwire_cmd(args)
231
236
  if not data.get("success"):
232
237
  return f"Failed to send message: {data.get('error', 'Unknown error')}"
@@ -24,6 +24,60 @@ from .core import (
24
24
  )
25
25
 
26
26
 
27
+ def _recover_unverified_send(session: str, prompt: str, sender: str) -> "str | None":
28
+ """Fallback when `send_verified` can't confirm delivery (#834, #835 review).
29
+
30
+ First checks whether the bare message is already on scrollback outside
31
+ the input box. A `send_verified` failure can mean the paste genuinely
32
+ never landed/submitted, OR that it fully submitted and only the
33
+ *confirm* read was ambiguous (an unparseable box frame, or a laggy host
34
+ blowing the submit budget). The msg-inbox drain's own dedup can't catch
35
+ the latter case on its own: it matches the WRAPPED ``[MSG from ... ]
36
+ ... <id>`` render (see ``inbox.Message.render``), never the bare text
37
+ this path pasted directly — enqueuing unconditionally would risk a real
38
+ duplicate delivery rather than the safe no-op the drain's dedup gives
39
+ its own messages. Checking here first avoids that duplicate in the
40
+ common case.
41
+
42
+ A message that lands only *after* this check runs (queued invisibly
43
+ mid-generation, per ``submit_confirmed``'s own docstring) can still
44
+ duplicate — accepted per this codebase's existing bias that a
45
+ recoverable duplicate beats a silently dropped message.
46
+
47
+ Known residual risk (#835 second-pass review): this is the same bare
48
+ whitespace-normalized substring match ``_deliver_once`` already uses for
49
+ its own internal idempotent-paste guard — not a new invention — but
50
+ reused here it trades in the *opposite* direction from most of this
51
+ file's checks. A false match reports "already delivered" and SKIPS the
52
+ inbox enqueue entirely: for a short or generic message (a bare "yes",
53
+ "continue", "approved") that happens to already sit in the last
54
+ ``VERIFY_SCROLLBACK_LINES`` for an unrelated reason, a send that
55
+ genuinely never landed could be silently dropped instead of queued —
56
+ the one outcome this whole fallback exists to prevent. Tracked as a
57
+ follow-up (a lightweight per-attempt marker, mirroring
58
+ ``send_verified``'s own ``marker`` param, would close this precisely);
59
+ not fixed here because it's strictly narrower than the bug this
60
+ function was written to close (needs a coincidental/repeated-text
61
+ match, not just any unverified send).
62
+
63
+ Returns ``"already_delivered"``, ``"inbox"``, or ``None`` (the inbox
64
+ fallback itself failed).
65
+ """
66
+ from agentwire.session_ready import message_on_scrollback, recover_failed_seed, scrollback
67
+
68
+ if message_on_scrollback(scrollback(session), prompt):
69
+ return "already_delivered"
70
+ return recover_failed_seed(session, prompt, sender=sender)
71
+
72
+
73
+ def _fallback_suffix(fallback: "str | None") -> str:
74
+ if fallback == "already_delivered":
75
+ return " — already delivered directly (the confirmation read was just ambiguous); no action needed"
76
+ if fallback == "inbox":
77
+ return " — queued to its msg inbox for guaranteed delivery"
78
+ return " and could not be queued — resend manually"
79
+
80
+
27
81
  def cmd_send(args) -> int:
28
82
  """Send a prompt to a tmux session or pane (adds Enter automatically).
29
83
 
@@ -36,6 +90,13 @@ def cmd_send(args) -> int:
36
90
  json_mode = getattr(args, 'json', False)
37
91
  wait_ready = getattr(args, 'wait_ready', False)
38
92
  verify = getattr(args, 'verify', False)
93
+ # Candidate sender for a msg-inbox fallback's attribution (#835 review):
94
+ # prefer the real calling session over the generic "agentwire" so
95
+ # dead-letter emails and the rendered [MSG from ...] header stay
96
+ # meaningful. MCP forwards --caller-session explicitly (can't reliably
97
+ # auto-detect the caller across that boundary); a bare CLI invocation
98
+ # falls back to auto-detecting its own tmux session.
99
+ fallback_sender = getattr(args, 'caller_session', None) or pane_manager.get_current_session() or "agentwire"
39
100
 
40
101
  if wait_ready and pane_index is not None:
41
102
  return _output_result(False, json_mode, "--wait-ready targets a session's pane 0; it can't be combined with --pane")
@@ -173,13 +234,22 @@ def cmd_send(args) -> int:
173
234
  if not wait_for_session_ready(session, timeout=timeout):
174
235
  return _output_result(False, json_mode, f"Agent in '{session}' not ready after {timeout:.0f}s")
175
236
  if not send_verified(session, prompt):
237
+ # A caller acting on "not verified" text is optional, not
238
+ # guaranteed — under load this is exactly the class of message
239
+ # that must never depend on an LLM noticing and manually
240
+ # resending. Fall back to the durable msg inbox (retried across
241
+ # ticks, dead-lettered + emailed on true exhaustion) instead of
242
+ # returning inert advisory text (#834).
243
+ fallback = _recover_unverified_send(session, prompt, fallback_sender)
176
244
  if json_mode:
177
- print(json.dumps({"success": False, "session": session_full, "verified": False, "error": "Delivery not verified"}))
245
+ print(json.dumps({"success": False, "session": session_full, "verified": False,
246
+ "fallback": fallback, "error": "Delivery not verified"}))
178
247
  else:
179
- print(f"Sent to {session} but delivery could not be verified", file=sys.stderr)
248
+ print(f"Sent to {session} but delivery could not be verified{_fallback_suffix(fallback)}", file=sys.stderr)
180
249
  return 1
181
250
  if json_mode:
182
- print(json.dumps({"success": True, "session": session_full, "machine": None, "verified": True, "message": "Prompt sent"}))
251
+ print(json.dumps({"success": True, "session": session_full, "machine": None,
252
+ "verified": True, "fallback": None, "message": "Prompt sent"}))
183
253
  else:
184
254
  print(f"Sent to {session} (verified)")
185
255
  return 0
@@ -197,12 +267,19 @@ def cmd_send(args) -> int:
197
267
  from agentwire.session_ready import send_verified
198
268
 
199
269
  ok = send_verified(session, prompt, retries=1)
270
+ fallback = None
271
+ if not ok:
272
+ # Same durable fallback as --wait-ready (#834).
273
+ fallback = _recover_unverified_send(session, prompt, fallback_sender)
200
274
  if json_mode:
201
275
  print(json.dumps({"success": True, "session": session_full, "machine": None,
202
- "verified": ok,
276
+ "verified": ok, "fallback": fallback,
203
277
  "message": "Prompt sent" if ok else "Prompt sent but delivery could not be verified"}))
204
278
  else:
205
- print(f"Sent to {session}" + (" (verified)" if ok else " (delivery NOT verified)"))
279
+ if ok:
280
+ print(f"Sent to {session} (verified)")
281
+ else:
282
+ print(f"Sent to {session} (delivery NOT verified){_fallback_suffix(fallback)}")
206
283
  return 0
207
284
 
208
285
  # Delegate paste + Enter handling to the shared pane_manager helper so
@@ -313,6 +390,11 @@ def register_send_parser(subparsers) -> None:
313
390
  "report verified vs unconfirmed instead of blind success")
314
391
  send_parser.add_argument("--timeout", type=float, default=30.0,
315
392
  help="Readiness wait timeout in seconds (with --wait-ready, default: 30)")
393
+ send_parser.add_argument("--caller-session", dest="caller_session",
394
+ help="Internal: attribute a msg-inbox delivery fallback to this sender "
395
+ "instead of auto-detecting the calling tmux session. MCP forwards "
396
+ "this explicitly, since the CLI subprocess can't reliably "
397
+ "auto-detect the caller across that boundary.")
316
398
  send_parser.add_argument("--json", action="store_true", help="Output as JSON")
317
399
  send_parser.set_defaults(func=cmd_send)
318
400
 
@@ -33,7 +33,7 @@ import jinja2
33
33
  import yaml
34
34
  from aiohttp import web
35
35
 
36
- from . import prompt_router, security
36
+ from . import __version__, prompt_router, security
37
37
  from .cached_status import CachedStatusChecker
38
38
  from .config import Config, load_config
39
39
  from .routes.artifacts import ArtifactsRoutesMixin, register_artifacts_routes
@@ -66,8 +66,6 @@ from .security import (
66
66
  from .ssh import ssh_base_opts
67
67
  from .worktree import parse_session_name
68
68
 
69
- __version__ = "1.3.0"
70
-
71
69
  logger = logging.getLogger(__name__)
72
70
 
73
71
  # Static asset serving (#488): gzip text on the fly + Cache-Control headers.
@@ -2479,6 +2477,19 @@ class AgentWireServer(
2479
2477
  ["send", "-s", session_name, "--wait-ready", "--timeout", "60", "--", message]
2480
2478
  )
2481
2479
  if not success:
2480
+ if result.get("fallback") in ("inbox", "already_delivered"):
2481
+ # #835: an unverified send now recovers on its own -- either
2482
+ # it was already delivered and the confirm read was just
2483
+ # ambiguous, or it's queued to the durable msg inbox. Either
2484
+ # way the old "paste it manually" toast would be stale,
2485
+ # actively wrong advice.
2486
+ logger.info(f"First message for {session_name} recovered via {result.get('fallback')} fallback")
2487
+ await self._post_toast(
2488
+ f"First message to {session_name} queued for guaranteed delivery"
2489
+ if result.get("fallback") == "inbox" else
2490
+ f"First message to {session_name} delivered (confirmation was just delayed)",
2491
+ session=session_name, priority="normal", id_prefix="firstmsg")
2492
+ return
2482
2493
  logger.warning(f"First message delivery failed for {session_name}: {result.get('error')}")
2483
2494
  await self._post_toast(
2484
2495
  f"First message not delivered to {session_name} — paste it manually",
@@ -590,6 +590,19 @@ def clear_input_box(session: str, pane_index: int = 0) -> bool:
590
590
  text]`` chip) and confirms emptiness with the drain's own SGR-aware gate
591
591
  (``prompt_router.prompt_is_empty``), so "cleared" here means exactly
592
592
  "the drain will deliver". Returns True iff the box ends up empty.
593
+
594
+ Refuses to press Escape while the screen shows a live select-menu/dialog
595
+ (#835 review): this function was written for a brand-new session's
596
+ failed first-message seed, where nothing else could plausibly be on
597
+ screen. It is also reused for an already-running, independently-busy
598
+ session (``agentwire send --verify`` falling back after a failed
599
+ delivery) — there, "box not empty" can mean a permission dialog or
600
+ ``AskUserQuestion`` menu belonging to the recipient's own unrelated
601
+ work, not our stuck paste. Escape is the conventional cancel/decline key
602
+ for those, so pressing it blind would silently cancel a decision that
603
+ had nothing to do with us. Returns False without touching the pane in
604
+ that case; the caller's msg-inbox fallback still gets enqueued and
605
+ waits for the box to become genuinely idle on its own.
593
606
  """
594
607
  from agentwire import pane_manager, prompt_router
595
608
 
@@ -602,6 +615,8 @@ def clear_input_box(session: str, pane_index: int = 0) -> bool:
602
615
  try:
603
616
  if empty():
604
617
  return True
618
+ if prompt_router.screen_shows_live_menu(_snapshot(session, pane_index)):
619
+ return False
605
620
  pane_manager.run_command(
606
621
  ["tmux", "send-keys", "-t", target, "Escape"], timeout=5
607
622
  )
@@ -188,12 +188,19 @@ class TestCmdSendWaitReady:
188
188
  def _payload(self, capsys):
189
189
  return json.loads(capsys.readouterr().out.strip())
190
190
 
191
+ def _mock_has_session(self, monkeypatch):
192
+ has_session = MagicMock(returncode=0)
193
+ monkeypatch.setattr("agentwire.send_cli.subprocess.run", lambda *a, **k: has_session)
194
+ # get_current_session shells out to real tmux and depends on the test
195
+ # runner's own environment ($TMUX_PANE) -- pin it so fallback_sender
196
+ # resolution is deterministic regardless of where tests run.
197
+ monkeypatch.setattr("agentwire.send_cli.pane_manager.get_current_session", lambda: None)
198
+
191
199
  def test_happy_path_verified(self, capsys, monkeypatch):
192
200
  from agentwire import session_ready
193
201
  from agentwire.send_cli import cmd_send
194
202
 
195
- has_session = MagicMock(returncode=0)
196
- monkeypatch.setattr("agentwire.send_cli.subprocess.run", lambda *a, **k: has_session)
203
+ self._mock_has_session(monkeypatch)
197
204
  monkeypatch.setattr(session_ready, "wait_for_session_ready", lambda s, timeout: True)
198
205
  monkeypatch.setattr(session_ready, "send_verified", lambda s, m: True)
199
206
 
@@ -201,13 +208,13 @@ class TestCmdSendWaitReady:
201
208
  payload = self._payload(capsys)
202
209
  assert payload["success"] is True
203
210
  assert payload["verified"] is True
211
+ assert payload["fallback"] is None
204
212
 
205
213
  def test_not_ready_fails(self, capsys, monkeypatch):
206
214
  from agentwire import session_ready
207
215
  from agentwire.send_cli import cmd_send
208
216
 
209
- has_session = MagicMock(returncode=0)
210
- monkeypatch.setattr("agentwire.send_cli.subprocess.run", lambda *a, **k: has_session)
217
+ self._mock_has_session(monkeypatch)
211
218
  monkeypatch.setattr(session_ready, "wait_for_session_ready", lambda s, timeout: False)
212
219
 
213
220
  assert cmd_send(self._args()) == 1
@@ -215,18 +222,56 @@ class TestCmdSendWaitReady:
215
222
  assert payload["success"] is False
216
223
  assert "not ready" in payload["error"]
217
224
 
218
- def test_unverified_fails(self, capsys, monkeypatch):
219
- from agentwire import session_ready
225
+ def test_unverified_falls_back_to_inbox(self, capsys, monkeypatch):
226
+ """#834: an unverified send must never just hand the problem back to
227
+ whichever caller reads the response — it queues to the durable msg
228
+ inbox so delivery is retried and eventually dead-lettered LOUDLY
229
+ instead of silently depending on the caller noticing and resending."""
230
+ from agentwire import send_cli, session_ready
220
231
  from agentwire.send_cli import cmd_send
221
232
 
222
- has_session = MagicMock(returncode=0)
223
- monkeypatch.setattr("agentwire.send_cli.subprocess.run", lambda *a, **k: has_session)
233
+ self._mock_has_session(monkeypatch)
224
234
  monkeypatch.setattr(session_ready, "wait_for_session_ready", lambda s, timeout: True)
225
235
  monkeypatch.setattr(session_ready, "send_verified", lambda s, m: False)
236
+ recover = MagicMock(return_value="inbox")
237
+ monkeypatch.setattr(send_cli, "_recover_unverified_send", recover)
226
238
 
227
239
  assert cmd_send(self._args()) == 1
228
240
  payload = self._payload(capsys)
229
241
  assert payload["verified"] is False
242
+ assert payload["fallback"] == "inbox"
243
+ recover.assert_called_once_with("proj", "my idea", "agentwire")
244
+
245
+ def test_unverified_and_fallback_fails_is_still_reported(self, capsys, monkeypatch):
246
+ from agentwire import send_cli, session_ready
247
+ from agentwire.send_cli import cmd_send
248
+
249
+ self._mock_has_session(monkeypatch)
250
+ monkeypatch.setattr(session_ready, "wait_for_session_ready", lambda s, timeout: True)
251
+ monkeypatch.setattr(session_ready, "send_verified", lambda s, m: False)
252
+ monkeypatch.setattr(send_cli, "_recover_unverified_send", lambda s, m, sender: None)
253
+
254
+ assert cmd_send(self._args()) == 1
255
+ payload = self._payload(capsys)
256
+ assert payload["verified"] is False
257
+ assert payload["fallback"] is None
258
+
259
+ def test_caller_session_arg_wins_over_autodetect(self, capsys, monkeypatch):
260
+ """#835 review: attribute a fallback's msg-inbox entry to the real
261
+ calling session (threaded via --caller-session from the MCP layer),
262
+ not the generic 'agentwire' -- matters for dead-letter email
263
+ attribution and the rendered [MSG from ...] header."""
264
+ from agentwire import send_cli, session_ready
265
+ from agentwire.send_cli import cmd_send
266
+
267
+ self._mock_has_session(monkeypatch)
268
+ monkeypatch.setattr(session_ready, "wait_for_session_ready", lambda s, timeout: True)
269
+ monkeypatch.setattr(session_ready, "send_verified", lambda s, m: False)
270
+ recover = MagicMock(return_value="inbox")
271
+ monkeypatch.setattr(send_cli, "_recover_unverified_send", recover)
272
+
273
+ cmd_send(self._args(caller_session="council-brain"))
274
+ recover.assert_called_once_with("proj", "my idea", "council-brain")
230
275
 
231
276
  def test_remote_rejected(self, capsys):
232
277
  from agentwire.send_cli import cmd_send
@@ -243,6 +288,114 @@ class TestCmdSendWaitReady:
243
288
  assert "--pane" in payload["error"]
244
289
 
245
290
 
291
+ # --- cmd_send --verify (no --wait-ready) ---
292
+
293
+ class TestCmdSendVerify:
294
+ def _args(self, **overrides):
295
+ defaults = dict(
296
+ session="proj", pane=None, prompt=["my", "idea"],
297
+ json=True, wait_ready=False, verify=True, timeout=None,
298
+ )
299
+ defaults.update(overrides)
300
+ return argparse.Namespace(**defaults)
301
+
302
+ def _payload(self, capsys):
303
+ return json.loads(capsys.readouterr().out.strip())
304
+
305
+ def _mock_has_session(self, monkeypatch):
306
+ has_session = MagicMock(returncode=0)
307
+ monkeypatch.setattr("agentwire.send_cli.subprocess.run", lambda *a, **k: has_session)
308
+ monkeypatch.setattr("agentwire.send_cli.pane_manager.get_current_session", lambda: None)
309
+
310
+ def test_happy_path_verified_skips_fallback(self, capsys, monkeypatch):
311
+ from agentwire import send_cli, session_ready
312
+ from agentwire.send_cli import cmd_send
313
+
314
+ self._mock_has_session(monkeypatch)
315
+ monkeypatch.setattr(session_ready, "send_verified", lambda s, m, retries=1: True)
316
+ recover = MagicMock()
317
+ monkeypatch.setattr(send_cli, "_recover_unverified_send", recover)
318
+
319
+ assert cmd_send(self._args()) == 0
320
+ payload = self._payload(capsys)
321
+ assert payload["verified"] is True
322
+ assert payload["fallback"] is None
323
+ recover.assert_not_called()
324
+
325
+ def test_unverified_falls_back_to_inbox(self, capsys, monkeypatch):
326
+ """#834: same durable-fallback guarantee as --wait-ready."""
327
+ from agentwire import send_cli, session_ready
328
+ from agentwire.send_cli import cmd_send
329
+
330
+ self._mock_has_session(monkeypatch)
331
+ monkeypatch.setattr(session_ready, "send_verified", lambda s, m, retries=1: False)
332
+ recover = MagicMock(return_value="inbox")
333
+ monkeypatch.setattr(send_cli, "_recover_unverified_send", recover)
334
+
335
+ assert cmd_send(self._args()) == 0 # verify-without-wait-ready reports success=True; verified carries the real state
336
+ payload = self._payload(capsys)
337
+ assert payload["verified"] is False
338
+ assert payload["fallback"] == "inbox"
339
+ recover.assert_called_once_with("proj", "my idea", "agentwire")
340
+
341
+ def test_remote_with_verify_never_touches_the_fallback(self, capsys, monkeypatch):
342
+ """Remote (session@machine) sends return from an earlier branch
343
+ entirely -- verify=True there only marks the result unverifiable
344
+ across SSH, and must never reach the new fallback machinery."""
345
+ from agentwire import send_cli
346
+ from agentwire.send_cli import cmd_send
347
+
348
+ recover = MagicMock()
349
+ monkeypatch.setattr(send_cli, "_recover_unverified_send", recover)
350
+ monkeypatch.setattr(
351
+ "agentwire.send_cli._run_remote",
352
+ lambda machine_id, cmd: MagicMock(returncode=0),
353
+ )
354
+ monkeypatch.setattr(
355
+ "agentwire.send_cli._get_machine_config",
356
+ lambda machine_id: {"host": "example.com"},
357
+ )
358
+
359
+ assert cmd_send(self._args(session="proj@gpu")) == 0
360
+ payload = self._payload(capsys)
361
+ assert payload["verified"] is None
362
+ assert "fallback" not in payload
363
+ recover.assert_not_called()
364
+
365
+
366
+ class TestRecoverUnverifiedSend:
367
+ """#835 review finding 2: the msg-inbox drain's dedup matches the
368
+ WRAPPED `[MSG from ... ] ... <id>` render, never the bare text a direct
369
+ paste puts on screen -- so blindly enqueuing risks a real duplicate
370
+ delivery when the original send actually landed and only the confirm
371
+ read was ambiguous. _recover_unverified_send closes the common case by
372
+ checking scrollback for the bare message first."""
373
+
374
+ def test_already_on_scrollback_skips_the_inbox_enqueue(self, monkeypatch):
375
+ from agentwire import session_ready
376
+ from agentwire.send_cli import _recover_unverified_send
377
+
378
+ monkeypatch.setattr(session_ready, "scrollback", lambda s, pane_index=0: "...fake capture...")
379
+ monkeypatch.setattr(session_ready, "message_on_scrollback", lambda cap, msg: True)
380
+ recover = MagicMock()
381
+ monkeypatch.setattr(session_ready, "recover_failed_seed", recover)
382
+
383
+ assert _recover_unverified_send("proj", "already sent", "agentwire") == "already_delivered"
384
+ recover.assert_not_called()
385
+
386
+ def test_not_on_scrollback_falls_back_to_the_inbox(self, monkeypatch):
387
+ from agentwire import session_ready
388
+ from agentwire.send_cli import _recover_unverified_send
389
+
390
+ monkeypatch.setattr(session_ready, "scrollback", lambda s, pane_index=0: "...fake capture...")
391
+ monkeypatch.setattr(session_ready, "message_on_scrollback", lambda cap, msg: False)
392
+ recover = MagicMock(return_value="inbox")
393
+ monkeypatch.setattr(session_ready, "recover_failed_seed", recover)
394
+
395
+ assert _recover_unverified_send("proj", "genuinely stuck", "council-brain") == "inbox"
396
+ recover.assert_called_once_with("proj", "genuinely stuck", sender="council-brain")
397
+
398
+
246
399
  # --- cmd_new --first-message ---
247
400
 
248
401
  class TestCmdNewFirstMessage:
@@ -151,6 +151,57 @@ class TestFormatProjectsBehavior:
151
151
  assert ".agentwire.yml" not in result
152
152
 
153
153
 
154
+ class TestDeliveryResultBehavior:
155
+ """#834: an unverified send must report its inbox fallback, not just
156
+ hand an inert 'check the pane or resend' string back to the caller."""
157
+
158
+ def test_verified_true(self):
159
+ from agentwire.mcp_core import _delivery_result
160
+ result = _delivery_result({"verified": True}, "to session 'proj'")
161
+ assert "verified in pane" in result
162
+
163
+ def test_unverified_with_inbox_fallback_reports_no_action_needed(self):
164
+ from agentwire.mcp_core import _delivery_result
165
+ result = _delivery_result({"verified": False, "fallback": "inbox"}, "to session 'proj'")
166
+ assert "queued to its msg inbox" in result
167
+ assert "No action needed" in result
168
+
169
+ def test_unverified_but_already_delivered_reports_no_action_needed(self):
170
+ """#835 second-pass review: the 'already_delivered' branch (the
171
+ confirm read was ambiguous but the message was actually on
172
+ scrollback already) had no direct test pinning its wording."""
173
+ from agentwire.mcp_core import _delivery_result
174
+ result = _delivery_result({"verified": False, "fallback": "already_delivered"}, "to session 'proj'")
175
+ assert "already visible on scrollback" in result
176
+ assert "No action needed" in result
177
+
178
+ def test_unverified_with_no_fallback_still_warns(self):
179
+ from agentwire.mcp_core import _delivery_result
180
+ result = _delivery_result({"verified": False, "fallback": None}, "to session 'proj'")
181
+ assert "may be lost" in result
182
+
183
+ def test_pane_send_has_no_fallback_key_and_must_not_claim_one_failed(self):
184
+ """pane_send's `agentwire send --pane` branch never attempts the
185
+ inbox fallback (the msg inbox only addresses sessions, not panes) —
186
+ it omits the `fallback` key entirely. This must read as the original
187
+ 'may have been dropped' warning, not falsely claim a fallback ran
188
+ and failed."""
189
+ from agentwire.mcp_core import _delivery_result
190
+ result = _delivery_result({"verified": False}, "to pane 1")
191
+ assert "may have been dropped" in result
192
+ assert "msg-inbox fallback" not in result
193
+
194
+ def test_remote_unverifiable(self):
195
+ from agentwire.mcp_core import _delivery_result
196
+ result = _delivery_result({"verified": None}, "to session 'proj'")
197
+ assert "can't be verified across SSH" in result
198
+
199
+ def test_no_verified_key_plain_sent(self):
200
+ from agentwire.mcp_core import _delivery_result
201
+ result = _delivery_result({}, "to session 'proj'")
202
+ assert result == "Message sent to session 'proj'."
203
+
204
+
154
205
  class TestFormatRolesBehavior:
155
206
  def test_full_role_format(self):
156
207
  from agentwire.mcp_core import format_roles
@@ -129,6 +129,10 @@ class TestSessionTools:
129
129
  sent_msg = args[4] # message follows --verify
130
130
  assert '[MESSAGE FROM SESSION "orchestrator"' in sent_msg
131
131
  assert 'session_send(session="orchestrator"' in sent_msg
132
+ # #835 review: a msg-inbox fallback attributes to the real caller
133
+ # (dead-letter emails, the rendered header) instead of the generic
134
+ # "agentwire" -- the CLI subprocess can't auto-detect it itself.
135
+ assert args[5:] == ["--caller-session", "orchestrator"]
132
136
 
133
137
  @patch("agentwire.mcp_session.run_agentwire_cmd")
134
138
  @patch("agentwire.mcp_session.get_caller_session", return_value=None)
@@ -68,6 +68,18 @@ class TestHealthEndpoint:
68
68
  assert data["status"] == "ok"
69
69
  assert "version" in data
70
70
 
71
+ async def test_health_reports_the_real_package_version(self, portal_client):
72
+ """server.py used to hardcode its own __version__ = "1.3.0",
73
+ disconnected from agentwire/__init__.py and stale since 2026-02 --
74
+ /health silently lied about what was actually running. Pin against
75
+ the real SSOT so a reintroduced hardcode fails this test."""
76
+ from agentwire import __version__ as real_version
77
+
78
+ client, _ = portal_client
79
+ resp = await client.get("/health")
80
+ data = await resp.json()
81
+ assert data["version"] == real_version
82
+
71
83
 
72
84
  class TestPwaSurface:
73
85
  """PWA manifest + service worker + push API (#483)."""
@@ -280,6 +292,58 @@ class TestApiCreateSession:
280
292
  if c[0][0] == "notification"]
281
293
  assert len(notify_calls) == 1
282
294
 
295
+ async def test_create_first_message_unverified_but_queued_does_not_say_paste_manually(self, portal_client):
296
+ """#835: an unverified first-message send that recovered via the
297
+ msg-inbox fallback (or was found already delivered) must not show
298
+ the stale 'paste it manually' toast -- the system already handled
299
+ it, and telling the human to intervene would be actively wrong."""
300
+ import asyncio
301
+
302
+ client, server = portal_client
303
+
304
+ async def cmd_router(args, json_output=True):
305
+ if args[0] == "send":
306
+ return (False, {"error": "Delivery not verified", "fallback": "inbox"})
307
+ return (True, {"session": "ideaproj", "path": "/p"})
308
+
309
+ with patch.object(server, "run_agentwire_cmd", side_effect=cmd_router):
310
+ server.broadcast_dashboard = AsyncMock()
311
+ resp = await client.post("/api/create", json={
312
+ "name": "ideaproj", "first_message": "an idea",
313
+ })
314
+ assert (await resp.json()).get("success") is True
315
+ await asyncio.gather(*server._background_tasks)
316
+ toasts = [n for n in server.active_notifications.values()
317
+ if n["session"] == "ideaproj"]
318
+ assert len(toasts) == 1
319
+ assert "paste it manually" not in toasts[0]["text"]
320
+ assert "queued" in toasts[0]["text"]
321
+
322
+ async def test_create_first_message_already_delivered_does_not_say_paste_manually(self, portal_client):
323
+ """#835 second-pass review: the 'already_delivered' arm of the same
324
+ ternary had no direct test -- only 'inbox' was exercised."""
325
+ import asyncio
326
+
327
+ client, server = portal_client
328
+
329
+ async def cmd_router(args, json_output=True):
330
+ if args[0] == "send":
331
+ return (False, {"error": "Delivery not verified", "fallback": "already_delivered"})
332
+ return (True, {"session": "ideaproj", "path": "/p"})
333
+
334
+ with patch.object(server, "run_agentwire_cmd", side_effect=cmd_router):
335
+ server.broadcast_dashboard = AsyncMock()
336
+ resp = await client.post("/api/create", json={
337
+ "name": "ideaproj", "first_message": "an idea",
338
+ })
339
+ assert (await resp.json()).get("success") is True
340
+ await asyncio.gather(*server._background_tasks)
341
+ toasts = [n for n in server.active_notifications.values()
342
+ if n["session"] == "ideaproj"]
343
+ assert len(toasts) == 1
344
+ assert "paste it manually" not in toasts[0]["text"]
345
+ assert "delivered" in toasts[0]["text"]
346
+
283
347
  async def test_create_without_first_message_no_background_task(self, portal_client):
284
348
  client, server = portal_client
285
349
  with patch.object(server, "run_agentwire_cmd", new_callable=AsyncMock) as mock_cmd: