agentwire-dev 1.65.1__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.1 → agentwire_dev-1.65.3}/PKG-INFO +1 -1
  2. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/__init__.py +1 -1
  3. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/mcp_core.py +23 -0
  4. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/mcp_session.py +5 -0
  5. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/routes/desktop.py +17 -1
  6. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/send_cli.py +87 -5
  7. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/server.py +14 -3
  8. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/session_cli.py +23 -3
  9. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/session_ready.py +15 -0
  10. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/static/js/desktop.js +19 -1
  11. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/static/js/notifications-panel.js +12 -3
  12. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/worktree.py +33 -0
  13. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/tests/integration/test_worktree_cmd.py +32 -0
  14. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/tests/unit/test_cli_commands.py +161 -8
  15. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/tests/unit/test_mcp_server.py +51 -0
  16. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/tests/unit/test_mcp_tools_args.py +33 -0
  17. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/tests/unit/test_portal_api.py +133 -3
  18. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/tests/unit/test_session_ready.py +22 -1
  19. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/tests/unit/test_worktree.py +43 -0
  20. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/.agentwire.yml.example +0 -0
  21. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/.claude/commands/handoff.md +0 -0
  22. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/.claude/skills/wiki/SKILL.md +0 -0
  23. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/.github/FUNDING.yml +0 -0
  24. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
  25. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
  26. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/.github/ISSUE_TEMPLATE/question.md +0 -0
  27. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
  28. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/.github/workflows/pytest.yml +0 -0
  29. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/.github/workflows/ruff.yml +0 -0
  30. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/.github/workflows/security.yml +0 -0
  31. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/.github/workflows/tts-smoke.yml +0 -0
  32. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/.gitignore +0 -0
  33. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/AGENTS.md +0 -0
  34. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/CODE_OF_CONDUCT.md +0 -0
  35. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/CONTRIBUTING.md +0 -0
  36. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/Dockerfile.local +0 -0
  37. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/LICENSE +0 -0
  38. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/README.md +0 -0
  39. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/RELEASING.md +0 -0
  40. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/SECURITY.md +0 -0
  41. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/SPONSORS.md +0 -0
  42. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/__main__.py +0 -0
  43. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/agents/__init__.py +0 -0
  44. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/agents/base.py +0 -0
  45. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/agents/tmux.py +0 -0
  46. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/cached_status.py +0 -0
  47. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/channels/__init__.py +0 -0
  48. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/channels/base.py +0 -0
  49. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/channels/email.py +0 -0
  50. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/channels/push.py +0 -0
  51. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/channels/quo.py +0 -0
  52. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/channels_cli.py +0 -0
  53. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/chrome_tabs.py +0 -0
  54. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/completion.py +0 -0
  55. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/config.py +0 -0
  56. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/config_cli.py +0 -0
  57. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/core.py +0 -0
  58. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/council/__init__.py +0 -0
  59. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/council/cli.py +0 -0
  60. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/council/inbox.py +0 -0
  61. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/council/minutes.py +0 -0
  62. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/council/state.py +0 -0
  63. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/council/view.py +0 -0
  64. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/devices.py +0 -0
  65. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/diff_cli.py +0 -0
  66. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/doctor_cli.py +0 -0
  67. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/doctor_voice.py +0 -0
  68. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/ensure_cli.py +0 -0
  69. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/fetch.py +0 -0
  70. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/handoff/__init__.py +0 -0
  71. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/handoff/git_state.py +0 -0
  72. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/handoff/instructions.py +0 -0
  73. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/handoff/parser.py +0 -0
  74. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/handoff/renderer.py +0 -0
  75. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/handoff/schema.py +0 -0
  76. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/handoff_cli.py +0 -0
  77. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/history.py +0 -0
  78. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/history_cli.py +0 -0
  79. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/hooks/__init__.py +0 -0
  80. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/hooks/agentwire-permission.sh +0 -0
  81. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/hooks/damage-control/__init__.py +0 -0
  82. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/hooks/damage-control/audit_logger.py +0 -0
  83. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/hooks/damage-control/bash-tool-damage-control.py +0 -0
  84. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/hooks/damage-control/edit-tool-damage-control.py +0 -0
  85. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/hooks/damage-control/mcp-tool-damage-control.py +0 -0
  86. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/hooks/damage-control/read-tool-damage-control.py +0 -0
  87. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/hooks/damage-control/rules/agentwire.yaml +0 -0
  88. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/hooks/damage-control/rules/aws.yaml +0 -0
  89. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/hooks/damage-control/rules/cloud-hosting.yaml +0 -0
  90. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/hooks/damage-control/rules/containers.yaml +0 -0
  91. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/hooks/damage-control/rules/control-plane.yaml +0 -0
  92. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/hooks/damage-control/rules/core.yaml +0 -0
  93. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/hooks/damage-control/rules/databases.yaml +0 -0
  94. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/hooks/damage-control/rules/firebase.yaml +0 -0
  95. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/hooks/damage-control/rules/gcp.yaml +0 -0
  96. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/hooks/damage-control/rules/git.yaml +0 -0
  97. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/hooks/damage-control/rules/gws.yaml +0 -0
  98. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/hooks/damage-control/rules/infrastructure.yaml +0 -0
  99. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/hooks/damage-control/rules/outbound.yaml +0 -0
  100. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/hooks/damage-control/rules/publish.yaml +0 -0
  101. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/hooks/damage-control/rules/remote.yaml +0 -0
  102. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/hooks/damage-control/write-tool-damage-control.py +0 -0
  103. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/hooks/idle-handler.sh +0 -0
  104. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/hooks/queue-processor.sh +0 -0
  105. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/hooks_cli.py +0 -0
  106. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/inbox.py +0 -0
  107. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/limits_cli.py +0 -0
  108. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/listen.py +0 -0
  109. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/locking.py +0 -0
  110. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/machine_cli.py +0 -0
  111. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/mcp_channels.py +0 -0
  112. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/mcp_chrome.py +0 -0
  113. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/mcp_cli.py +0 -0
  114. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/mcp_council.py +0 -0
  115. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/mcp_desktop.py +0 -0
  116. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/mcp_handoff.py +0 -0
  117. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/mcp_history.py +0 -0
  118. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/mcp_listen.py +0 -0
  119. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/mcp_lock.py +0 -0
  120. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/mcp_machine.py +0 -0
  121. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/mcp_msg.py +0 -0
  122. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/mcp_notify.py +0 -0
  123. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/mcp_pane.py +0 -0
  124. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/mcp_projects.py +0 -0
  125. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/mcp_scheduler.py +0 -0
  126. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/mcp_scratchpad.py +0 -0
  127. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/mcp_server.py +0 -0
  128. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/mcp_services.py +0 -0
  129. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/mcp_status.py +0 -0
  130. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/mcp_task.py +0 -0
  131. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/mcp_tunnels.py +0 -0
  132. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/mcp_voice.py +0 -0
  133. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/mcp_wiki.py +0 -0
  134. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/mcp_worktree.py +0 -0
  135. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/msg_cli.py +0 -0
  136. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/network.py +0 -0
  137. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/notify_cli.py +0 -0
  138. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/onboarding.py +0 -0
  139. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/palette_cli.py +0 -0
  140. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/pane_cli.py +0 -0
  141. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/pane_manager.py +0 -0
  142. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/portal_cli.py +0 -0
  143. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/project_config.py +0 -0
  144. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/projects.py +0 -0
  145. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/prompt_router.py +0 -0
  146. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/prompts_cli.py +0 -0
  147. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/push_cli.py +0 -0
  148. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/push_store.py +0 -0
  149. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/repo_cli.py +0 -0
  150. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/research.py +0 -0
  151. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/roles/__init__.py +0 -0
  152. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/roles/agentwire.md +0 -0
  153. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/roles/anchor.md +0 -0
  154. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/roles/chatbot.md +0 -0
  155. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/roles/contributor.md +0 -0
  156. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/roles/correspondent.md +0 -0
  157. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/roles/council-brain.md +0 -0
  158. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/roles/council-conscience.md +0 -0
  159. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/roles/council-critic.md +0 -0
  160. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/roles/council-devils-advocate.md +0 -0
  161. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/roles/council-gut.md +0 -0
  162. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/roles/council-historian.md +0 -0
  163. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/roles/council-member.md +0 -0
  164. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/roles/council-orchestrator.md +0 -0
  165. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/roles/init.md +0 -0
  166. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/roles/notifications.md +0 -0
  167. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/roles/orchestrator.md +0 -0
  168. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/roles/reviewer-worktree.md +0 -0
  169. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/roles/reviewer.md +0 -0
  170. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/roles/soul.md +0 -0
  171. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/roles/task-runner.md +0 -0
  172. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/roles/voice.md +0 -0
  173. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/roles/worker-worktree.md +0 -0
  174. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/roles/worker.md +0 -0
  175. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/roles_cli.py +0 -0
  176. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/routes/__init__.py +0 -0
  177. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/routes/artifacts.py +0 -0
  178. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/routes/config.py +0 -0
  179. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/routes/council.py +0 -0
  180. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/routes/history.py +0 -0
  181. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/routes/machines.py +0 -0
  182. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/routes/notify.py +0 -0
  183. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/routes/palette.py +0 -0
  184. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/routes/permission.py +0 -0
  185. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/routes/projects.py +0 -0
  186. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/routes/push.py +0 -0
  187. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/routes/safety.py +0 -0
  188. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/routes/scheduler.py +0 -0
  189. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/routes/scratchpad.py +0 -0
  190. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/routes/sessions.py +0 -0
  191. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/routes/sessions_admin.py +0 -0
  192. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/routes/voice.py +0 -0
  193. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/safety/__init__.py +0 -0
  194. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/safety/_core.py +0 -0
  195. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/safety_cli.py +0 -0
  196. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/safety_commands.py +0 -0
  197. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/scheduler/__init__.py +0 -0
  198. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/scheduler/dispatch.py +0 -0
  199. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/scheduler/gates.py +0 -0
  200. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/scheduler/loop.py +0 -0
  201. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/scheduler/models.py +0 -0
  202. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/scheduler/report.py +0 -0
  203. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/scheduler/schedule.py +0 -0
  204. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/scheduler/state.py +0 -0
  205. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/scheduler/zombie.py +0 -0
  206. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/scheduler_cli.py +0 -0
  207. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/scratchpad.py +0 -0
  208. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/security.py +0 -0
  209. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/services.py +0 -0
  210. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/session_context.py +0 -0
  211. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/ssh.py +0 -0
  212. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/static/agentwire-splash-logo-layers--agentwire-text.png +0 -0
  213. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/static/agentwire-splash-logo-layers--echo-claw-fg.png +0 -0
  214. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/static/agentwire-splash-logo-layers--echo.png +0 -0
  215. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/static/agentwire-splash-logo-layers--telephone.png +0 -0
  216. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/static/agentwire-splash-logo-layers--tree.png +0 -0
  217. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/static/announcements.json +0 -0
  218. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/static/apple-touch-icon.png +0 -0
  219. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/static/css/desktop.css +0 -0
  220. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/static/css/mobile.css +0 -0
  221. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/static/favicon-32.png +0 -0
  222. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/static/favicon-64.png +0 -0
  223. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/static/icons/sessions/bear.webp +0 -0
  224. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/static/icons/sessions/cat.webp +0 -0
  225. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/static/icons/sessions/crown.webp +0 -0
  226. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/static/icons/sessions/custom/agentwire-portal.webp +0 -0
  227. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/static/icons/sessions/custom/agentwire-tts.webp +0 -0
  228. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/static/icons/sessions/custom/agentwire.webp +0 -0
  229. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/static/icons/sessions/deer.webp +0 -0
  230. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/static/icons/sessions/drone.webp +0 -0
  231. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/static/icons/sessions/eagle.webp +0 -0
  232. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/static/icons/sessions/fox.webp +0 -0
  233. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/static/icons/sessions/hawk.webp +0 -0
  234. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/static/icons/sessions/horse.webp +0 -0
  235. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/static/icons/sessions/lion.webp +0 -0
  236. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/static/icons/sessions/rabbit.webp +0 -0
  237. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/static/icons/sessions/robot.webp +0 -0
  238. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/static/icons/sessions/tiger.webp +0 -0
  239. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/static/icons/sessions/wolf.webp +0 -0
  240. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/static/img/icon-192.png +0 -0
  241. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/static/img/icon-512.png +0 -0
  242. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/static/js/.gitkeep +0 -0
  243. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/static/js/announcement-modal.js +0 -0
  244. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/static/js/api.js +0 -0
  245. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/static/js/artifact-window.js +0 -0
  246. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/static/js/card-terminal.js +0 -0
  247. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/static/js/collage.js +0 -0
  248. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/static/js/command-palette.js +0 -0
  249. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/static/js/council-window.js +0 -0
  250. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/static/js/dead-key-suppressor.js +0 -0
  251. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/static/js/desktop-manager.js +0 -0
  252. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/static/js/help-modal.js +0 -0
  253. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/static/js/icon-manager.js +0 -0
  254. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/static/js/lineage.js +0 -0
  255. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/static/js/mobile.js +0 -0
  256. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/static/js/notification-prefs.js +0 -0
  257. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/static/js/ptt.js +0 -0
  258. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/static/js/push-client.js +0 -0
  259. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/static/js/review-window.js +0 -0
  260. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/static/js/safety-shared.js +0 -0
  261. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/static/js/safety-window.js +0 -0
  262. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/static/js/scratchpad.js +0 -0
  263. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/static/js/service-classification.js +0 -0
  264. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/static/js/session-hud-controller.js +0 -0
  265. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/static/js/session-hud-notices.js +0 -0
  266. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/static/js/session-hud-spawn.js +0 -0
  267. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/static/js/session-hud.js +0 -0
  268. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/static/js/session-id.js +0 -0
  269. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/static/js/session-window.js +0 -0
  270. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/static/js/shortcuts.js +0 -0
  271. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/static/js/sidebar/artifacts-section.js +0 -0
  272. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/static/js/sidebar/config-section.js +0 -0
  273. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/static/js/sidebar/council-section.js +0 -0
  274. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/static/js/sidebar/machines-section.js +0 -0
  275. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/static/js/sidebar/projects-section.js +0 -0
  276. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/static/js/sidebar/safety-section.js +0 -0
  277. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/static/js/sidebar/scheduler-section.js +0 -0
  278. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/static/js/sidebar/services-section.js +0 -0
  279. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/static/js/sidebar/sessions-section.js +0 -0
  280. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/static/js/sidebar.js +0 -0
  281. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/static/js/spawn-ghost.js +0 -0
  282. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/static/js/terminal-font-prefs.js +0 -0
  283. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/static/js/terminal-pane.js +0 -0
  284. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/static/js/tile-manager.js +0 -0
  285. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/static/js/toast.js +0 -0
  286. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/static/js/token-modal.js +0 -0
  287. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/static/js/topology-render.js +0 -0
  288. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/static/js/utils/ansi.js +0 -0
  289. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/static/js/utils/rich-text.js +0 -0
  290. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/static/js/utils/swipe.js +0 -0
  291. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/static/js/voice/autosend-prefs.js +0 -0
  292. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/static/js/voice/browser-stt.js +0 -0
  293. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/static/js/voice/browser-tts.js +0 -0
  294. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/static/js/voice/jargon.js +0 -0
  295. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/static/js/voice/prompt.js +0 -0
  296. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/static/js/winbox.bundle.min.js +0 -0
  297. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/static/js/workspace-window.js +0 -0
  298. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/static/manifest.webmanifest +0 -0
  299. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/static/service-worker.js +0 -0
  300. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/static/topology-harness.html +0 -0
  301. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/stt/__init__.py +0 -0
  302. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/stt/base.py +0 -0
  303. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/stt/cloud.py +0 -0
  304. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/stt/engine.py +0 -0
  305. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/stt/local.py +0 -0
  306. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/stt/server_backend.py +0 -0
  307. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/stt/stt_server.py +0 -0
  308. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/system_cli.py +0 -0
  309. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/tabs_cli.py +0 -0
  310. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/tasks.py +0 -0
  311. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/tasks_cli.py +0 -0
  312. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/templates/__init__.py +0 -0
  313. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/templates/base.html +0 -0
  314. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/templates/council/minutes.html.j2 +0 -0
  315. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/templates/desktop.html +0 -0
  316. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/templates/email_notification.html +0 -0
  317. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/templates/handoff/show-the-story.html.j2 +0 -0
  318. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/templates/handoff/theme.css.j2 +0 -0
  319. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/templates/mobile.html +0 -0
  320. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/templates/pair.html +0 -0
  321. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/templates/tmux.conf +0 -0
  322. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/templating.py +0 -0
  323. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/tooldefs/aws.yaml +0 -0
  324. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/tooldefs/docker.yaml +0 -0
  325. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/tooldefs/gcp.yaml +0 -0
  326. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/tooldefs/gh.yaml +0 -0
  327. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/tooldefs/git.yaml +0 -0
  328. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/tooldefs/gws.yaml +0 -0
  329. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/tooldefs/kubectl.yaml +0 -0
  330. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/tooldefs/npm.yaml +0 -0
  331. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/tooldefs/terraform.yaml +0 -0
  332. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/tooldefs/uv.yaml +0 -0
  333. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/tts/__init__.py +0 -0
  334. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/tts/audio.py +0 -0
  335. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/tts/base.py +0 -0
  336. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/tts/engines/__init__.py +0 -0
  337. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/tts/engines/chatterbox.py +0 -0
  338. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/tts/engines/kokoro.py +0 -0
  339. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/tts/engines/zonos.py +0 -0
  340. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/tts/kokoro_server.py +0 -0
  341. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/tts/local.py +0 -0
  342. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/tts/registry.py +0 -0
  343. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/tts_cli.py +0 -0
  344. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/tts_server.py +0 -0
  345. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/tunnels.py +0 -0
  346. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/tunnels_cli.py +0 -0
  347. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/usage_limit.py +0 -0
  348. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/utils/__init__.py +0 -0
  349. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/utils/chunker.py +0 -0
  350. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/utils/event_log.py +0 -0
  351. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/utils/file_io.py +0 -0
  352. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/utils/paths.py +0 -0
  353. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/utils/speech.py +0 -0
  354. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/utils/subprocess.py +0 -0
  355. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/validation.py +0 -0
  356. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/voice_status.py +0 -0
  357. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/wiki.py +0 -0
  358. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/wiki_audit.py +0 -0
  359. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/wiki_cli.py +0 -0
  360. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/agentwire/worktree_registry.py +0 -0
  361. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/docs/decisions/obsidian-second-brain.md +0 -0
  362. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/docs/design/session-card-fields.md +0 -0
  363. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/docs/design/session-card-recommendation.md +0 -0
  364. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/docs/logo.png +0 -0
  365. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/docs/wiki/INDEX.md +0 -0
  366. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/docs/wiki/architecture.md +0 -0
  367. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/docs/wiki/briefing-mode.md +0 -0
  368. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/docs/wiki/communication/channels.md +0 -0
  369. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/docs/wiki/communication/hammerspoon.md +0 -0
  370. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/docs/wiki/communication/handoff.md +0 -0
  371. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/docs/wiki/concepts.md +0 -0
  372. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/docs/wiki/council.md +0 -0
  373. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/docs/wiki/deployment/remote-access.md +0 -0
  374. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/docs/wiki/deployment/remote-machines.md +0 -0
  375. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/docs/wiki/glossary.md +0 -0
  376. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/docs/wiki/integrations/gws-google-workspace-cli.md +0 -0
  377. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/docs/wiki/internals/damage-control.md +0 -0
  378. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/docs/wiki/internals/parallel-refactor.md +0 -0
  379. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/docs/wiki/internals/portal.md +0 -0
  380. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/docs/wiki/internals/session-topology.md +0 -0
  381. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/docs/wiki/internals/shell-escaping.md +0 -0
  382. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/docs/wiki/internals/troubleshooting.md +0 -0
  383. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/docs/wiki/internals/window-collage.md +0 -0
  384. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/docs/wiki/quickstart.md +0 -0
  385. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/docs/wiki/research/briefing-mode-feasibility.md +0 -0
  386. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/docs/wiki/research/orchestration-transport-alternatives.md +0 -0
  387. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/docs/wiki/scheduling/scheduled-workloads.md +0 -0
  388. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/docs/wiki/security/damage-control-hardening.md +0 -0
  389. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/docs/wiki/security/pip-audit.md +0 -0
  390. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/docs/wiki/security/remote-access-hardening.md +0 -0
  391. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/docs/wiki/security/secrets.md +0 -0
  392. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/docs/wiki/services.md +0 -0
  393. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/docs/wiki/sessions/claude-code-auto-mode.md +0 -0
  394. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/docs/wiki/sessions/messaging.md +0 -0
  395. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/docs/wiki/sessions/prompt-routing.md +0 -0
  396. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/docs/wiki/sessions/window-sizing.md +0 -0
  397. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/docs/wiki/sessions/worktree-sessions.md +0 -0
  398. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/docs/wiki/usage-limit-recovery.md +0 -0
  399. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/docs/wiki/voice/shim-contract.md +0 -0
  400. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/docs/wiki/voice/stt-cloud.md +0 -0
  401. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/docs/wiki/voice/stt-self-hosted.md +0 -0
  402. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/docs/wiki/voice/tts-self-hosted.md +0 -0
  403. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/pyproject.toml +0 -0
  404. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/tests/conftest.py +0 -0
  405. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/tests/e2e/test_portal_ui.py +0 -0
  406. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/tests/fixtures/sample_agentwire.yml +0 -0
  407. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/tests/fixtures/sample_config.yaml +0 -0
  408. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/tests/fixtures/sample_scheduler.yaml +0 -0
  409. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/tests/integration/test_council_portal.py +0 -0
  410. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/tests/integration/test_scheduler_board.py +0 -0
  411. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/tests/integration/test_send_verified_tmux.py +0 -0
  412. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/tests/integration/test_server_websockets.py +0 -0
  413. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/tests/unit/test_announcements.py +0 -0
  414. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/tests/unit/test_build_agent_command.py +0 -0
  415. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/tests/unit/test_channels.py +0 -0
  416. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/tests/unit/test_chrome_tabs.py +0 -0
  417. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/tests/unit/test_cli_output.py +0 -0
  418. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/tests/unit/test_cli_smoke.py +0 -0
  419. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/tests/unit/test_config.py +0 -0
  420. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/tests/unit/test_config_cli.py +0 -0
  421. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/tests/unit/test_control_plane_protection.py +0 -0
  422. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/tests/unit/test_core_created_by_rooting.py +0 -0
  423. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/tests/unit/test_council_cli.py +0 -0
  424. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/tests/unit/test_council_inbox.py +0 -0
  425. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/tests/unit/test_council_minutes.py +0 -0
  426. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/tests/unit/test_council_state.py +0 -0
  427. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/tests/unit/test_council_view.py +0 -0
  428. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/tests/unit/test_damage_control_bypass.py +0 -0
  429. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/tests/unit/test_damage_control_hooks.py +0 -0
  430. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/tests/unit/test_damage_control_sync.py +0 -0
  431. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/tests/unit/test_dangling_worktrees.py +0 -0
  432. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/tests/unit/test_devices.py +0 -0
  433. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/tests/unit/test_diff_cli.py +0 -0
  434. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/tests/unit/test_doctor_scheduler_staleness.py +0 -0
  435. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/tests/unit/test_doctor_task_migration.py +0 -0
  436. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/tests/unit/test_doctor_voice.py +0 -0
  437. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/tests/unit/test_event_log.py +0 -0
  438. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/tests/unit/test_file_io.py +0 -0
  439. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/tests/unit/test_guarded_launch_command.py +0 -0
  440. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/tests/unit/test_handoff_git_state.py +0 -0
  441. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/tests/unit/test_handoff_instructions.py +0 -0
  442. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/tests/unit/test_handoff_parser.py +0 -0
  443. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/tests/unit/test_handoff_renderer.py +0 -0
  444. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/tests/unit/test_history.py +0 -0
  445. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/tests/unit/test_hooks_install.py +0 -0
  446. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/tests/unit/test_idle_handler.py +0 -0
  447. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/tests/unit/test_idle_nag.py +0 -0
  448. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/tests/unit/test_inbox.py +0 -0
  449. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/tests/unit/test_init_command.py +0 -0
  450. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/tests/unit/test_install_parity.py +0 -0
  451. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/tests/unit/test_limits_tick_isolation.py +0 -0
  452. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/tests/unit/test_locking.py +0 -0
  453. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/tests/unit/test_msg_cli.py +0 -0
  454. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/tests/unit/test_notify_cli.py +0 -0
  455. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/tests/unit/test_onboarding_reinit.py +0 -0
  456. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/tests/unit/test_palette_cli.py +0 -0
  457. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/tests/unit/test_pip_environment.py +0 -0
  458. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/tests/unit/test_posture_default.py +0 -0
  459. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/tests/unit/test_project_config.py +0 -0
  460. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/tests/unit/test_projects_registry.py +0 -0
  461. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/tests/unit/test_prompt_router.py +0 -0
  462. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/tests/unit/test_push.py +0 -0
  463. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/tests/unit/test_rebuild_guard.py +0 -0
  464. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/tests/unit/test_repo_cli.py +0 -0
  465. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/tests/unit/test_rich_text_js.py +0 -0
  466. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/tests/unit/test_roles.py +0 -0
  467. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/tests/unit/test_routes_snapshot.py +0 -0
  468. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/tests/unit/test_safety_commands.py +0 -0
  469. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/tests/unit/test_safety_disabled_rules.py +0 -0
  470. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/tests/unit/test_safety_escape_hatch.py +0 -0
  471. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/tests/unit/test_safety_heal.py +0 -0
  472. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/tests/unit/test_safety_kill_switch.py +0 -0
  473. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/tests/unit/test_scheduler.py +0 -0
  474. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/tests/unit/test_scheduler_parsing.py +0 -0
  475. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/tests/unit/test_scheduler_zombie.py +0 -0
  476. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/tests/unit/test_scratchpad.py +0 -0
  477. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/tests/unit/test_security.py +0 -0
  478. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/tests/unit/test_server_async.py +0 -0
  479. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/tests/unit/test_server_pure.py +0 -0
  480. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/tests/unit/test_services.py +0 -0
  481. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/tests/unit/test_session_context.py +0 -0
  482. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/tests/unit/test_session_created_by_env.py +0 -0
  483. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/tests/unit/test_shared_dir_guard.py +0 -0
  484. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/tests/unit/test_shim_selfheal.py +0 -0
  485. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/tests/unit/test_skill_install.py +0 -0
  486. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/tests/unit/test_speech_tags.py +0 -0
  487. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/tests/unit/test_ssh.py +0 -0
  488. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/tests/unit/test_stt_backend.py +0 -0
  489. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/tests/unit/test_stt_cloud.py +0 -0
  490. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/tests/unit/test_stt_engine.py +0 -0
  491. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/tests/unit/test_task_cli.py +0 -0
  492. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/tests/unit/test_tasks.py +0 -0
  493. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/tests/unit/test_tasks_cli.py +0 -0
  494. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/tests/unit/test_templating.py +0 -0
  495. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/tests/unit/test_terminal_resize.py +0 -0
  496. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/tests/unit/test_tmux_template.py +0 -0
  497. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/tests/unit/test_tts_engine_resolution.py +0 -0
  498. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/tests/unit/test_tts_local.py +0 -0
  499. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/tests/unit/test_tunnels_probe.py +0 -0
  500. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/tests/unit/test_unattended_env_isolation.py +0 -0
  501. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/tests/unit/test_usage_limit.py +0 -0
  502. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/tests/unit/test_validation.py +0 -0
  503. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/tests/unit/test_voice_status.py +0 -0
  504. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/tests/unit/test_wiki.py +0 -0
  505. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/tests/unit/test_wiki_audit.py +0 -0
  506. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/tests/unit/test_window_cycling_binding.py +0 -0
  507. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/tests/unit/test_worktree_branch_cleanup.py +0 -0
  508. {agentwire_dev-1.65.1 → agentwire_dev-1.65.3}/tests/unit/test_worktree_layout.py +0 -0
  509. {agentwire_dev-1.65.1 → 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.1
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.1"
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')}"
@@ -10,6 +10,22 @@ through the composed server's MRO.
10
10
  from aiohttp import web
11
11
 
12
12
 
13
+ def _artifact_url_hash(url: str) -> str:
14
+ """FNV-1a 32-bit hash of ``url``, as 8 lowercase hex chars.
15
+
16
+ Must match ``artifactUrlHash`` in static/js/desktop.js byte-for-byte —
17
+ the server and frontend both derive the same fallback artifact id from
18
+ the same URL, and a naive char-substitution slug (the prior approach)
19
+ let distinct URLs like "reports/jan.html" and "reports-jan.html" collide
20
+ onto the same id. A hash isn't lossy the way substitution is.
21
+ """
22
+ h = 0x811C9DC5
23
+ for b in url.encode("utf-8"):
24
+ h ^= b
25
+ h = (h * 0x01000193) & 0xFFFFFFFF
26
+ return f"{h:08x}"
27
+
28
+
13
29
  class DesktopRoutesMixin:
14
30
  async def api_desktop_windows(self, request):
15
31
  """GET /api/desktop/windows — query browser clients for open windows."""
@@ -173,7 +189,7 @@ class DesktopRoutesMixin:
173
189
  "url": url,
174
190
  "title": title,
175
191
  "artifact_id": artifact.get("artifact_id")
176
- or f"artifact-{url.replace('/', '-').replace('.', '-')}",
192
+ or f"artifact-{_artifact_url_hash(url)}",
177
193
  }
178
194
  if not text:
179
195
  text = f"**{title}** is ready — click to open"
@@ -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",
@@ -62,6 +62,7 @@ from .worktree import (
62
62
  default_base_branch,
63
63
  ensure_worktree,
64
64
  git_root,
65
+ is_registered_worktree,
65
66
  is_valid_branch_name,
66
67
  parse_session_name,
67
68
  remove_worktree,
@@ -1561,7 +1562,17 @@ def _teardown_entry(
1561
1562
  Never reports worktree_removed=True while the dir is still on disk: if
1562
1563
  `git worktree remove --force` can't clear it, this fails LOUDLY
1563
1564
  (success: False) and leaves the registry entry in place, instead of
1564
- silently "unregistering" an orphan.
1565
+ silently "unregistering" an orphan — UNLESS git *already had no record of
1566
+ the path before we touched it* (see `is_registered_worktree`), in which
1567
+ case there's no registered worktree left to protect and the leftover
1568
+ directory (a stale build-tool cache, typically) is hard-deleted instead.
1569
+
1570
+ That pre-check matters: `git worktree prune` below runs unconditionally
1571
+ and clears any entry git marks "prunable" (e.g. one whose linked `.git`
1572
+ file was deleted) as a side effect of THIS call — checking registration
1573
+ after prune would misread a worktree that was real and registered right
1574
+ up until this attempt as a pre-existing orphan, and hard-delete content
1575
+ the fail-loud path exists to protect.
1565
1576
 
1566
1577
  The worktree removal is attempted BEFORE the session is killed, and the
1567
1578
  session is only killed once removal is confirmed — never the reverse.
@@ -1569,10 +1580,17 @@ def _teardown_entry(
1569
1580
  disk with no session left to notice, on any removal failure (bad
1570
1581
  project_path, a stuck worktree, ...) (#740).
1571
1582
  """
1583
+ was_registered = is_registered_worktree(project_path, worktree_path)
1584
+
1572
1585
  # Force-remove the git worktree, then prune admin files either way.
1573
1586
  _, remove_error = remove_worktree(project_path, worktree_path, force=True)
1574
1587
  subprocess.run(["git", "-C", str(project_path), "worktree", "prune"], capture_output=True)
1575
1588
 
1589
+ hard_deleted_orphan = False
1590
+ if worktree_path.exists() and not was_registered:
1591
+ shutil.rmtree(worktree_path, ignore_errors=True)
1592
+ hard_deleted_orphan = not worktree_path.exists()
1593
+
1576
1594
  if worktree_path.exists():
1577
1595
  reason = remove_error or "worktree directory still present after `git worktree remove --force`"
1578
1596
  return {"success": False, "session": session_name, "path": str(worktree_path),
@@ -1605,7 +1623,7 @@ def _teardown_entry(
1605
1623
  return {"success": True, "session": session_name, "path": str(worktree_path),
1606
1624
  "killed": killed, "worktree_removed": True,
1607
1625
  "branch": branch, "branch_deleted": branch_deleted, "branch_note": branch_note,
1608
- "orphaned_tabs": orphaned_tabs}
1626
+ "orphaned_tabs": orphaned_tabs, "hard_deleted_orphan": hard_deleted_orphan}
1609
1627
 
1610
1628
 
1611
1629
  def _worktree_remove(args, project_path: Path, worktree_dir: Path, json_mode: bool) -> int:
@@ -1641,7 +1659,9 @@ def _worktree_remove(args, project_path: Path, worktree_dir: Path, json_mode: bo
1641
1659
  else:
1642
1660
  msg = (f"Removed worktree session '{result['session']}'"
1643
1661
  + (" (killed live session)" if result["killed"] else "")
1644
- + f"; worktree {result['path']} removed")
1662
+ + f"; worktree {result['path']} removed"
1663
+ + (" (git had no registration for it — hard-deleted the leftover directory)"
1664
+ if result.get("hard_deleted_orphan") else ""))
1645
1665
  if result["branch"]:
1646
1666
  msg += f"; branch '{result['branch']}' " + ("deleted" if result["branch_deleted"] else f"kept ({result['branch_note']})")
1647
1667
  if result["orphaned_tabs"]:
@@ -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
  )
@@ -824,6 +824,24 @@ function _mountSessionWindow(session, mode, machine, id) {
824
824
  addTaskbarButton(id, sw);
825
825
  }
826
826
 
827
+ /**
828
+ * FNV-1a 32-bit hash of `url`, as 8 lowercase hex chars. Must match
829
+ * `_artifact_url_hash` in routes/desktop.py byte-for-byte — server and
830
+ * frontend both derive the same fallback artifact id from the same URL. A
831
+ * hash isn't lossy the way the prior char-substitution slug was (distinct
832
+ * URLs like "reports/jan.html" and "reports-jan.html" collided onto the
833
+ * same id).
834
+ */
835
+ function artifactUrlHash(url) {
836
+ let h = 0x811c9dc5;
837
+ const bytes = new TextEncoder().encode(url);
838
+ for (const b of bytes) {
839
+ h ^= b;
840
+ h = Math.imul(h, 0x01000193) >>> 0;
841
+ }
842
+ return h.toString(16).padStart(8, '0');
843
+ }
844
+
827
845
  /**
828
846
  * Open an artifact window (agent-generated HTML or external URL).
829
847
  *
@@ -832,7 +850,7 @@ function _mountSessionWindow(session, mode, machine, id) {
832
850
  * @param {string|null} artifactId - Optional explicit window ID
833
851
  */
834
852
  export function openArtifactWindow(url, title = 'Artifact', artifactId = null) {
835
- const id = artifactId || `artifact-${url.replace(/[\/\.]/g, '-')}`;
853
+ const id = artifactId || `artifact-${artifactUrlHash(url)}`;
836
854
 
837
855
  // Check if already open — restore if minimized, otherwise focus
838
856
  if (artifactWindows.has(id)) {
@@ -86,10 +86,19 @@ class NotificationsPanel {
86
86
  this._removeToast(id, false);
87
87
  }
88
88
 
89
- // Evict oldest if at capacity
89
+ // Evict the oldest toast NOT carrying an artifact notice, if at
90
+ // capacity. Artifact toasts are exempt regardless of priority: an
91
+ // unclicked deliverable must not silently fade (#817) — the cap
92
+ // only trims ordinary toasts (sticky `high`-priority ones included).
93
+ // If every current toast is an artifact notice, the panel
94
+ // temporarily exceeds MAX_TOASTS rather than dropping one.
90
95
  if (this.toasts.size >= MAX_TOASTS) {
91
- const oldest = this.toasts.keys().next().value;
92
- this._removeToast(oldest, false);
96
+ for (const id of this.toasts.keys()) {
97
+ if (!this.artifactNotices.has(id)) {
98
+ this._removeToast(id, false);
99
+ break;
100
+ }
101
+ }
93
102
  }
94
103
 
95
104
  // Resolve auto-fade: explicit timeout wins (0 = sticky); otherwise
@@ -309,6 +309,39 @@ def remove_worktree(project_path: Path, worktree_path: Path, *, force: bool = Tr
309
309
  return False, (result.stderr or result.stdout).strip()
310
310
 
311
311
 
312
+ def is_registered_worktree(project_path: Path, worktree_path: Path) -> bool:
313
+ """Does git's own worktree registry (still) know about ``worktree_path``?
314
+
315
+ A directory can outlive its registration — e.g. `git worktree remove`
316
+ succeeded on a prior teardown attempt but the `rm -rf` half crashed
317
+ before clearing a build-tool cache dir left inside, or the admin file
318
+ under `.git/worktrees/` was pruned independently. In that state git
319
+ reports "fatal: ... is not a working tree" for every future removal
320
+ attempt, forever — this lets a caller distinguish that from a real
321
+ registered worktree that `remove --force` merely failed to clear. It
322
+ says nothing about whether the directory holds valuable content — that
323
+ judgment (e.g. "orphaned + unregistered is safe to hard-delete") belongs
324
+ to the caller, not this function.
325
+
326
+ Fails closed on an inconclusive read: if `git worktree list` itself
327
+ errors (corrupt repo, I/O, lock contention), that's reported as
328
+ registered rather than not — a caller gating a destructive action on
329
+ this should default to "assume real" when unsure, not "assume orphan".
330
+ """
331
+ result = subprocess.run(
332
+ ["git", "worktree", "list", "--porcelain"],
333
+ cwd=project_path, capture_output=True, text=True,
334
+ )
335
+ if result.returncode != 0:
336
+ return True
337
+ target = str(worktree_path.resolve())
338
+ for line in result.stdout.splitlines():
339
+ if line.startswith("worktree "):
340
+ if str(Path(line[len("worktree "):]).resolve()) == target:
341
+ return True
342
+ return False
343
+
344
+
312
345
  def worktree_status(worktree_path: Path) -> dict:
313
346
  """Read-only git status for a worktree. Local git only — no network, no gh.
314
347
 
@@ -643,6 +643,38 @@ def test_remove_fails_loudly_when_dir_survives(tmp_path, monkeypatch, wt_env, ca
643
643
  assert payload["error"]
644
644
 
645
645
 
646
+ def test_remove_hard_deletes_unregistered_orphan_directory(tmp_path, monkeypatch, wt_env, capsys):
647
+ """A directory git no longer registers as a worktree at all (its
648
+ `.git/worktrees/<name>` admin entry is gone, e.g. from a prior teardown
649
+ that crashed mid-way) must not get stuck failing `git worktree remove`
650
+ forever — since git has nothing left to lose, the leftover directory is
651
+ hard-deleted and teardown proceeds and succeeds."""
652
+ import shutil
653
+
654
+ _, clone = _origin_and_clone(tmp_path, default_branch="develop")
655
+ wt_dir = tmp_path / "worktrees"
656
+ cfg = _config(wt_dir)
657
+ assert _run(monkeypatch, cfg, name="orphan", project=str(clone)) == 0
658
+ wt_path = wt_dir / "clone-repo" / "orphan"
659
+ assert wt_path.exists()
660
+
661
+ # Simulate the crashed-partial-teardown state: git's own registration is
662
+ # gone, but the directory (with leftover content) survives on disk.
663
+ shutil.rmtree(clone / ".git" / "worktrees" / "orphan")
664
+ (wt_path / "stale-cache-file").write_text("leftover\n")
665
+
666
+ capsys.readouterr()
667
+ rc = _run(monkeypatch, cfg, name="orphan", project=str(clone), remove=True)
668
+ assert rc == 0
669
+ assert not wt_path.exists()
670
+ assert reg.entries(clone.resolve()) == []
671
+
672
+ payload = json.loads(capsys.readouterr().out)
673
+ assert payload["success"] is True
674
+ assert payload["worktree_removed"] is True
675
+ assert payload["hard_deleted_orphan"] is True
676
+
677
+
646
678
  def test_remove_kills_alive_session(tmp_path, monkeypatch, wt_env, capsys):
647
679
  _, clone = _origin_and_clone(tmp_path, default_branch="develop")
648
680
  wt_dir = tmp_path / "worktrees"