agentwire-dev 1.64.0__tar.gz → 1.65.1__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.64.0 → agentwire_dev-1.65.1}/PKG-INFO +1 -1
  2. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/__init__.py +1 -1
  3. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/config.py +0 -2
  4. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/core.py +13 -1
  5. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/council/cli.py +22 -19
  6. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/inbox.py +65 -32
  7. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/mcp_council.py +7 -6
  8. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/mcp_desktop.py +28 -33
  9. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/mcp_notify.py +11 -1
  10. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/mcp_scheduler.py +1 -1
  11. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/mcp_session.py +10 -6
  12. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/mcp_worktree.py +10 -5
  13. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/notify_cli.py +15 -14
  14. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/projects.py +75 -5
  15. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/roles/__init__.py +41 -27
  16. agentwire_dev-1.65.1/agentwire/roles/reviewer-worktree.md +36 -0
  17. agentwire_dev-1.65.1/agentwire/roles/reviewer.md +29 -0
  18. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/roles_cli.py +143 -0
  19. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/routes/desktop.py +29 -13
  20. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/routes/projects.py +94 -0
  21. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/scheduler_cli.py +3 -3
  22. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/server.py +21 -2
  23. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/session_cli.py +39 -15
  24. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/static/css/desktop.css +142 -7
  25. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/static/js/command-palette.js +190 -4
  26. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/static/js/desktop.js +17 -3
  27. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/static/js/notifications-panel.js +73 -30
  28. agentwire_dev-1.65.1/agentwire/static/js/session-hud-notices.js +107 -0
  29. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/static/js/session-hud.js +50 -9
  30. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/static/js/topology-render.js +11 -6
  31. agentwire_dev-1.65.1/agentwire/static/js/utils/rich-text.js +40 -0
  32. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/docs/wiki/council.md +3 -2
  33. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/docs/wiki/sessions/messaging.md +8 -2
  34. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/tests/conftest.py +1 -1
  35. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/tests/integration/test_worktree_cmd.py +24 -0
  36. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/tests/unit/test_cli_commands.py +14 -0
  37. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/tests/unit/test_cli_smoke.py +17 -0
  38. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/tests/unit/test_core_created_by_rooting.py +11 -0
  39. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/tests/unit/test_council_minutes.py +11 -11
  40. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/tests/unit/test_inbox.py +71 -7
  41. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/tests/unit/test_mcp_tools_args.py +18 -2
  42. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/tests/unit/test_portal_api.py +65 -0
  43. agentwire_dev-1.65.1/tests/unit/test_projects_registry.py +274 -0
  44. agentwire_dev-1.65.1/tests/unit/test_rich_text_js.py +61 -0
  45. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/tests/unit/test_roles.py +95 -7
  46. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/tests/unit/test_routes_snapshot.py +3 -0
  47. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/.agentwire.yml.example +0 -0
  48. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/.claude/commands/handoff.md +0 -0
  49. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/.claude/skills/wiki/SKILL.md +0 -0
  50. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/.github/FUNDING.yml +0 -0
  51. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
  52. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
  53. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/.github/ISSUE_TEMPLATE/question.md +0 -0
  54. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
  55. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/.github/workflows/pytest.yml +0 -0
  56. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/.github/workflows/ruff.yml +0 -0
  57. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/.github/workflows/security.yml +0 -0
  58. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/.github/workflows/tts-smoke.yml +0 -0
  59. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/.gitignore +0 -0
  60. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/AGENTS.md +0 -0
  61. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/CODE_OF_CONDUCT.md +0 -0
  62. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/CONTRIBUTING.md +0 -0
  63. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/Dockerfile.local +0 -0
  64. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/LICENSE +0 -0
  65. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/README.md +0 -0
  66. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/RELEASING.md +0 -0
  67. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/SECURITY.md +0 -0
  68. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/SPONSORS.md +0 -0
  69. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/__main__.py +0 -0
  70. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/agents/__init__.py +0 -0
  71. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/agents/base.py +0 -0
  72. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/agents/tmux.py +0 -0
  73. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/cached_status.py +0 -0
  74. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/channels/__init__.py +0 -0
  75. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/channels/base.py +0 -0
  76. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/channels/email.py +0 -0
  77. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/channels/push.py +0 -0
  78. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/channels/quo.py +0 -0
  79. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/channels_cli.py +0 -0
  80. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/chrome_tabs.py +0 -0
  81. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/completion.py +0 -0
  82. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/config_cli.py +0 -0
  83. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/council/__init__.py +0 -0
  84. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/council/inbox.py +0 -0
  85. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/council/minutes.py +0 -0
  86. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/council/state.py +0 -0
  87. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/council/view.py +0 -0
  88. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/devices.py +0 -0
  89. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/diff_cli.py +0 -0
  90. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/doctor_cli.py +0 -0
  91. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/doctor_voice.py +0 -0
  92. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/ensure_cli.py +0 -0
  93. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/fetch.py +0 -0
  94. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/handoff/__init__.py +0 -0
  95. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/handoff/git_state.py +0 -0
  96. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/handoff/instructions.py +0 -0
  97. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/handoff/parser.py +0 -0
  98. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/handoff/renderer.py +0 -0
  99. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/handoff/schema.py +0 -0
  100. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/handoff_cli.py +0 -0
  101. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/history.py +0 -0
  102. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/history_cli.py +0 -0
  103. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/hooks/__init__.py +0 -0
  104. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/hooks/agentwire-permission.sh +0 -0
  105. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/hooks/damage-control/__init__.py +0 -0
  106. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/hooks/damage-control/audit_logger.py +0 -0
  107. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/hooks/damage-control/bash-tool-damage-control.py +0 -0
  108. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/hooks/damage-control/edit-tool-damage-control.py +0 -0
  109. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/hooks/damage-control/mcp-tool-damage-control.py +0 -0
  110. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/hooks/damage-control/read-tool-damage-control.py +0 -0
  111. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/hooks/damage-control/rules/agentwire.yaml +0 -0
  112. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/hooks/damage-control/rules/aws.yaml +0 -0
  113. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/hooks/damage-control/rules/cloud-hosting.yaml +0 -0
  114. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/hooks/damage-control/rules/containers.yaml +0 -0
  115. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/hooks/damage-control/rules/control-plane.yaml +0 -0
  116. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/hooks/damage-control/rules/core.yaml +0 -0
  117. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/hooks/damage-control/rules/databases.yaml +0 -0
  118. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/hooks/damage-control/rules/firebase.yaml +0 -0
  119. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/hooks/damage-control/rules/gcp.yaml +0 -0
  120. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/hooks/damage-control/rules/git.yaml +0 -0
  121. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/hooks/damage-control/rules/gws.yaml +0 -0
  122. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/hooks/damage-control/rules/infrastructure.yaml +0 -0
  123. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/hooks/damage-control/rules/outbound.yaml +0 -0
  124. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/hooks/damage-control/rules/publish.yaml +0 -0
  125. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/hooks/damage-control/rules/remote.yaml +0 -0
  126. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/hooks/damage-control/write-tool-damage-control.py +0 -0
  127. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/hooks/idle-handler.sh +0 -0
  128. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/hooks/queue-processor.sh +0 -0
  129. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/hooks_cli.py +0 -0
  130. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/limits_cli.py +0 -0
  131. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/listen.py +0 -0
  132. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/locking.py +0 -0
  133. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/machine_cli.py +0 -0
  134. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/mcp_channels.py +0 -0
  135. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/mcp_chrome.py +0 -0
  136. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/mcp_cli.py +0 -0
  137. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/mcp_core.py +0 -0
  138. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/mcp_handoff.py +0 -0
  139. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/mcp_history.py +0 -0
  140. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/mcp_listen.py +0 -0
  141. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/mcp_lock.py +0 -0
  142. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/mcp_machine.py +0 -0
  143. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/mcp_msg.py +0 -0
  144. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/mcp_pane.py +0 -0
  145. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/mcp_projects.py +0 -0
  146. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/mcp_scratchpad.py +0 -0
  147. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/mcp_server.py +0 -0
  148. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/mcp_services.py +0 -0
  149. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/mcp_status.py +0 -0
  150. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/mcp_task.py +0 -0
  151. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/mcp_tunnels.py +0 -0
  152. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/mcp_voice.py +0 -0
  153. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/mcp_wiki.py +0 -0
  154. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/msg_cli.py +0 -0
  155. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/network.py +0 -0
  156. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/onboarding.py +0 -0
  157. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/palette_cli.py +0 -0
  158. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/pane_cli.py +0 -0
  159. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/pane_manager.py +0 -0
  160. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/portal_cli.py +0 -0
  161. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/project_config.py +0 -0
  162. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/prompt_router.py +0 -0
  163. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/prompts_cli.py +0 -0
  164. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/push_cli.py +0 -0
  165. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/push_store.py +0 -0
  166. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/repo_cli.py +0 -0
  167. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/research.py +0 -0
  168. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/roles/agentwire.md +0 -0
  169. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/roles/anchor.md +0 -0
  170. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/roles/chatbot.md +0 -0
  171. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/roles/contributor.md +0 -0
  172. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/roles/correspondent.md +0 -0
  173. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/roles/council-brain.md +0 -0
  174. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/roles/council-conscience.md +0 -0
  175. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/roles/council-critic.md +0 -0
  176. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/roles/council-devils-advocate.md +0 -0
  177. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/roles/council-gut.md +0 -0
  178. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/roles/council-historian.md +0 -0
  179. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/roles/council-member.md +0 -0
  180. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/roles/council-orchestrator.md +0 -0
  181. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/roles/init.md +0 -0
  182. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/roles/notifications.md +0 -0
  183. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/roles/orchestrator.md +0 -0
  184. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/roles/soul.md +0 -0
  185. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/roles/task-runner.md +0 -0
  186. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/roles/voice.md +0 -0
  187. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/roles/worker-worktree.md +0 -0
  188. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/roles/worker.md +0 -0
  189. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/routes/__init__.py +0 -0
  190. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/routes/artifacts.py +0 -0
  191. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/routes/config.py +0 -0
  192. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/routes/council.py +0 -0
  193. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/routes/history.py +0 -0
  194. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/routes/machines.py +0 -0
  195. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/routes/notify.py +0 -0
  196. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/routes/palette.py +0 -0
  197. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/routes/permission.py +0 -0
  198. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/routes/push.py +0 -0
  199. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/routes/safety.py +0 -0
  200. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/routes/scheduler.py +0 -0
  201. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/routes/scratchpad.py +0 -0
  202. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/routes/sessions.py +0 -0
  203. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/routes/sessions_admin.py +0 -0
  204. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/routes/voice.py +0 -0
  205. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/safety/__init__.py +0 -0
  206. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/safety/_core.py +0 -0
  207. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/safety_cli.py +0 -0
  208. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/safety_commands.py +0 -0
  209. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/scheduler/__init__.py +0 -0
  210. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/scheduler/dispatch.py +0 -0
  211. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/scheduler/gates.py +0 -0
  212. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/scheduler/loop.py +0 -0
  213. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/scheduler/models.py +0 -0
  214. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/scheduler/report.py +0 -0
  215. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/scheduler/schedule.py +0 -0
  216. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/scheduler/state.py +0 -0
  217. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/scheduler/zombie.py +0 -0
  218. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/scratchpad.py +0 -0
  219. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/security.py +0 -0
  220. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/send_cli.py +0 -0
  221. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/services.py +0 -0
  222. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/session_context.py +0 -0
  223. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/session_ready.py +0 -0
  224. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/ssh.py +0 -0
  225. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/static/agentwire-splash-logo-layers--agentwire-text.png +0 -0
  226. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/static/agentwire-splash-logo-layers--echo-claw-fg.png +0 -0
  227. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/static/agentwire-splash-logo-layers--echo.png +0 -0
  228. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/static/agentwire-splash-logo-layers--telephone.png +0 -0
  229. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/static/agentwire-splash-logo-layers--tree.png +0 -0
  230. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/static/announcements.json +0 -0
  231. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/static/apple-touch-icon.png +0 -0
  232. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/static/css/mobile.css +0 -0
  233. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/static/favicon-32.png +0 -0
  234. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/static/favicon-64.png +0 -0
  235. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/static/icons/sessions/bear.webp +0 -0
  236. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/static/icons/sessions/cat.webp +0 -0
  237. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/static/icons/sessions/crown.webp +0 -0
  238. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/static/icons/sessions/custom/agentwire-portal.webp +0 -0
  239. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/static/icons/sessions/custom/agentwire-tts.webp +0 -0
  240. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/static/icons/sessions/custom/agentwire.webp +0 -0
  241. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/static/icons/sessions/deer.webp +0 -0
  242. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/static/icons/sessions/drone.webp +0 -0
  243. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/static/icons/sessions/eagle.webp +0 -0
  244. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/static/icons/sessions/fox.webp +0 -0
  245. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/static/icons/sessions/hawk.webp +0 -0
  246. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/static/icons/sessions/horse.webp +0 -0
  247. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/static/icons/sessions/lion.webp +0 -0
  248. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/static/icons/sessions/rabbit.webp +0 -0
  249. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/static/icons/sessions/robot.webp +0 -0
  250. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/static/icons/sessions/tiger.webp +0 -0
  251. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/static/icons/sessions/wolf.webp +0 -0
  252. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/static/img/icon-192.png +0 -0
  253. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/static/img/icon-512.png +0 -0
  254. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/static/js/.gitkeep +0 -0
  255. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/static/js/announcement-modal.js +0 -0
  256. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/static/js/api.js +0 -0
  257. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/static/js/artifact-window.js +0 -0
  258. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/static/js/card-terminal.js +0 -0
  259. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/static/js/collage.js +0 -0
  260. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/static/js/council-window.js +0 -0
  261. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/static/js/dead-key-suppressor.js +0 -0
  262. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/static/js/desktop-manager.js +0 -0
  263. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/static/js/help-modal.js +0 -0
  264. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/static/js/icon-manager.js +0 -0
  265. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/static/js/lineage.js +0 -0
  266. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/static/js/mobile.js +0 -0
  267. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/static/js/notification-prefs.js +0 -0
  268. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/static/js/ptt.js +0 -0
  269. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/static/js/push-client.js +0 -0
  270. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/static/js/review-window.js +0 -0
  271. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/static/js/safety-shared.js +0 -0
  272. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/static/js/safety-window.js +0 -0
  273. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/static/js/scratchpad.js +0 -0
  274. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/static/js/service-classification.js +0 -0
  275. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/static/js/session-hud-controller.js +0 -0
  276. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/static/js/session-hud-spawn.js +0 -0
  277. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/static/js/session-id.js +0 -0
  278. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/static/js/session-window.js +0 -0
  279. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/static/js/shortcuts.js +0 -0
  280. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/static/js/sidebar/artifacts-section.js +0 -0
  281. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/static/js/sidebar/config-section.js +0 -0
  282. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/static/js/sidebar/council-section.js +0 -0
  283. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/static/js/sidebar/machines-section.js +0 -0
  284. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/static/js/sidebar/projects-section.js +0 -0
  285. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/static/js/sidebar/safety-section.js +0 -0
  286. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/static/js/sidebar/scheduler-section.js +0 -0
  287. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/static/js/sidebar/services-section.js +0 -0
  288. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/static/js/sidebar/sessions-section.js +0 -0
  289. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/static/js/sidebar.js +0 -0
  290. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/static/js/spawn-ghost.js +0 -0
  291. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/static/js/terminal-font-prefs.js +0 -0
  292. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/static/js/terminal-pane.js +0 -0
  293. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/static/js/tile-manager.js +0 -0
  294. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/static/js/toast.js +0 -0
  295. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/static/js/token-modal.js +0 -0
  296. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/static/js/utils/ansi.js +0 -0
  297. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/static/js/utils/swipe.js +0 -0
  298. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/static/js/voice/autosend-prefs.js +0 -0
  299. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/static/js/voice/browser-stt.js +0 -0
  300. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/static/js/voice/browser-tts.js +0 -0
  301. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/static/js/voice/jargon.js +0 -0
  302. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/static/js/voice/prompt.js +0 -0
  303. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/static/js/winbox.bundle.min.js +0 -0
  304. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/static/js/workspace-window.js +0 -0
  305. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/static/manifest.webmanifest +0 -0
  306. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/static/service-worker.js +0 -0
  307. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/static/topology-harness.html +0 -0
  308. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/stt/__init__.py +0 -0
  309. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/stt/base.py +0 -0
  310. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/stt/cloud.py +0 -0
  311. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/stt/engine.py +0 -0
  312. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/stt/local.py +0 -0
  313. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/stt/server_backend.py +0 -0
  314. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/stt/stt_server.py +0 -0
  315. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/system_cli.py +0 -0
  316. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/tabs_cli.py +0 -0
  317. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/tasks.py +0 -0
  318. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/tasks_cli.py +0 -0
  319. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/templates/__init__.py +0 -0
  320. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/templates/base.html +0 -0
  321. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/templates/council/minutes.html.j2 +0 -0
  322. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/templates/desktop.html +0 -0
  323. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/templates/email_notification.html +0 -0
  324. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/templates/handoff/show-the-story.html.j2 +0 -0
  325. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/templates/handoff/theme.css.j2 +0 -0
  326. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/templates/mobile.html +0 -0
  327. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/templates/pair.html +0 -0
  328. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/templates/tmux.conf +0 -0
  329. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/templating.py +0 -0
  330. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/tooldefs/aws.yaml +0 -0
  331. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/tooldefs/docker.yaml +0 -0
  332. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/tooldefs/gcp.yaml +0 -0
  333. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/tooldefs/gh.yaml +0 -0
  334. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/tooldefs/git.yaml +0 -0
  335. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/tooldefs/gws.yaml +0 -0
  336. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/tooldefs/kubectl.yaml +0 -0
  337. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/tooldefs/npm.yaml +0 -0
  338. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/tooldefs/terraform.yaml +0 -0
  339. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/tooldefs/uv.yaml +0 -0
  340. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/tts/__init__.py +0 -0
  341. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/tts/audio.py +0 -0
  342. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/tts/base.py +0 -0
  343. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/tts/engines/__init__.py +0 -0
  344. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/tts/engines/chatterbox.py +0 -0
  345. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/tts/engines/kokoro.py +0 -0
  346. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/tts/engines/zonos.py +0 -0
  347. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/tts/kokoro_server.py +0 -0
  348. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/tts/local.py +0 -0
  349. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/tts/registry.py +0 -0
  350. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/tts_cli.py +0 -0
  351. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/tts_server.py +0 -0
  352. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/tunnels.py +0 -0
  353. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/tunnels_cli.py +0 -0
  354. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/usage_limit.py +0 -0
  355. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/utils/__init__.py +0 -0
  356. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/utils/chunker.py +0 -0
  357. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/utils/event_log.py +0 -0
  358. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/utils/file_io.py +0 -0
  359. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/utils/paths.py +0 -0
  360. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/utils/speech.py +0 -0
  361. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/utils/subprocess.py +0 -0
  362. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/validation.py +0 -0
  363. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/voice_status.py +0 -0
  364. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/wiki.py +0 -0
  365. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/wiki_audit.py +0 -0
  366. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/wiki_cli.py +0 -0
  367. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/worktree.py +0 -0
  368. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/agentwire/worktree_registry.py +0 -0
  369. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/docs/decisions/obsidian-second-brain.md +0 -0
  370. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/docs/design/session-card-fields.md +0 -0
  371. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/docs/design/session-card-recommendation.md +0 -0
  372. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/docs/logo.png +0 -0
  373. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/docs/wiki/INDEX.md +0 -0
  374. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/docs/wiki/architecture.md +0 -0
  375. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/docs/wiki/briefing-mode.md +0 -0
  376. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/docs/wiki/communication/channels.md +0 -0
  377. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/docs/wiki/communication/hammerspoon.md +0 -0
  378. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/docs/wiki/communication/handoff.md +0 -0
  379. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/docs/wiki/concepts.md +0 -0
  380. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/docs/wiki/deployment/remote-access.md +0 -0
  381. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/docs/wiki/deployment/remote-machines.md +0 -0
  382. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/docs/wiki/glossary.md +0 -0
  383. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/docs/wiki/integrations/gws-google-workspace-cli.md +0 -0
  384. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/docs/wiki/internals/damage-control.md +0 -0
  385. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/docs/wiki/internals/parallel-refactor.md +0 -0
  386. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/docs/wiki/internals/portal.md +0 -0
  387. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/docs/wiki/internals/session-topology.md +0 -0
  388. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/docs/wiki/internals/shell-escaping.md +0 -0
  389. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/docs/wiki/internals/troubleshooting.md +0 -0
  390. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/docs/wiki/internals/window-collage.md +0 -0
  391. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/docs/wiki/quickstart.md +0 -0
  392. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/docs/wiki/research/briefing-mode-feasibility.md +0 -0
  393. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/docs/wiki/research/orchestration-transport-alternatives.md +0 -0
  394. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/docs/wiki/scheduling/scheduled-workloads.md +0 -0
  395. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/docs/wiki/security/damage-control-hardening.md +0 -0
  396. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/docs/wiki/security/pip-audit.md +0 -0
  397. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/docs/wiki/security/remote-access-hardening.md +0 -0
  398. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/docs/wiki/security/secrets.md +0 -0
  399. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/docs/wiki/services.md +0 -0
  400. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/docs/wiki/sessions/claude-code-auto-mode.md +0 -0
  401. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/docs/wiki/sessions/prompt-routing.md +0 -0
  402. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/docs/wiki/sessions/window-sizing.md +0 -0
  403. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/docs/wiki/sessions/worktree-sessions.md +0 -0
  404. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/docs/wiki/usage-limit-recovery.md +0 -0
  405. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/docs/wiki/voice/shim-contract.md +0 -0
  406. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/docs/wiki/voice/stt-cloud.md +0 -0
  407. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/docs/wiki/voice/stt-self-hosted.md +0 -0
  408. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/docs/wiki/voice/tts-self-hosted.md +0 -0
  409. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/pyproject.toml +0 -0
  410. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/tests/e2e/test_portal_ui.py +0 -0
  411. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/tests/fixtures/sample_agentwire.yml +0 -0
  412. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/tests/fixtures/sample_config.yaml +0 -0
  413. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/tests/fixtures/sample_scheduler.yaml +0 -0
  414. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/tests/integration/test_council_portal.py +0 -0
  415. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/tests/integration/test_scheduler_board.py +0 -0
  416. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/tests/integration/test_send_verified_tmux.py +0 -0
  417. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/tests/integration/test_server_websockets.py +0 -0
  418. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/tests/unit/test_announcements.py +0 -0
  419. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/tests/unit/test_build_agent_command.py +0 -0
  420. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/tests/unit/test_channels.py +0 -0
  421. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/tests/unit/test_chrome_tabs.py +0 -0
  422. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/tests/unit/test_cli_output.py +0 -0
  423. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/tests/unit/test_config.py +0 -0
  424. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/tests/unit/test_config_cli.py +0 -0
  425. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/tests/unit/test_control_plane_protection.py +0 -0
  426. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/tests/unit/test_council_cli.py +0 -0
  427. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/tests/unit/test_council_inbox.py +0 -0
  428. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/tests/unit/test_council_state.py +0 -0
  429. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/tests/unit/test_council_view.py +0 -0
  430. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/tests/unit/test_damage_control_bypass.py +0 -0
  431. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/tests/unit/test_damage_control_hooks.py +0 -0
  432. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/tests/unit/test_damage_control_sync.py +0 -0
  433. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/tests/unit/test_dangling_worktrees.py +0 -0
  434. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/tests/unit/test_devices.py +0 -0
  435. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/tests/unit/test_diff_cli.py +0 -0
  436. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/tests/unit/test_doctor_scheduler_staleness.py +0 -0
  437. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/tests/unit/test_doctor_task_migration.py +0 -0
  438. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/tests/unit/test_doctor_voice.py +0 -0
  439. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/tests/unit/test_event_log.py +0 -0
  440. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/tests/unit/test_file_io.py +0 -0
  441. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/tests/unit/test_guarded_launch_command.py +0 -0
  442. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/tests/unit/test_handoff_git_state.py +0 -0
  443. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/tests/unit/test_handoff_instructions.py +0 -0
  444. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/tests/unit/test_handoff_parser.py +0 -0
  445. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/tests/unit/test_handoff_renderer.py +0 -0
  446. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/tests/unit/test_history.py +0 -0
  447. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/tests/unit/test_hooks_install.py +0 -0
  448. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/tests/unit/test_idle_handler.py +0 -0
  449. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/tests/unit/test_idle_nag.py +0 -0
  450. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/tests/unit/test_init_command.py +0 -0
  451. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/tests/unit/test_install_parity.py +0 -0
  452. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/tests/unit/test_limits_tick_isolation.py +0 -0
  453. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/tests/unit/test_locking.py +0 -0
  454. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/tests/unit/test_mcp_server.py +0 -0
  455. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/tests/unit/test_msg_cli.py +0 -0
  456. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/tests/unit/test_notify_cli.py +0 -0
  457. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/tests/unit/test_onboarding_reinit.py +0 -0
  458. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/tests/unit/test_palette_cli.py +0 -0
  459. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/tests/unit/test_pip_environment.py +0 -0
  460. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/tests/unit/test_posture_default.py +0 -0
  461. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/tests/unit/test_project_config.py +0 -0
  462. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/tests/unit/test_prompt_router.py +0 -0
  463. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/tests/unit/test_push.py +0 -0
  464. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/tests/unit/test_rebuild_guard.py +0 -0
  465. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/tests/unit/test_repo_cli.py +0 -0
  466. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/tests/unit/test_safety_commands.py +0 -0
  467. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/tests/unit/test_safety_disabled_rules.py +0 -0
  468. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/tests/unit/test_safety_escape_hatch.py +0 -0
  469. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/tests/unit/test_safety_heal.py +0 -0
  470. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/tests/unit/test_safety_kill_switch.py +0 -0
  471. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/tests/unit/test_scheduler.py +0 -0
  472. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/tests/unit/test_scheduler_parsing.py +0 -0
  473. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/tests/unit/test_scheduler_zombie.py +0 -0
  474. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/tests/unit/test_scratchpad.py +0 -0
  475. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/tests/unit/test_security.py +0 -0
  476. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/tests/unit/test_server_async.py +0 -0
  477. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/tests/unit/test_server_pure.py +0 -0
  478. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/tests/unit/test_services.py +0 -0
  479. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/tests/unit/test_session_context.py +0 -0
  480. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/tests/unit/test_session_created_by_env.py +0 -0
  481. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/tests/unit/test_session_ready.py +0 -0
  482. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/tests/unit/test_shared_dir_guard.py +0 -0
  483. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/tests/unit/test_shim_selfheal.py +0 -0
  484. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/tests/unit/test_skill_install.py +0 -0
  485. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/tests/unit/test_speech_tags.py +0 -0
  486. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/tests/unit/test_ssh.py +0 -0
  487. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/tests/unit/test_stt_backend.py +0 -0
  488. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/tests/unit/test_stt_cloud.py +0 -0
  489. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/tests/unit/test_stt_engine.py +0 -0
  490. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/tests/unit/test_task_cli.py +0 -0
  491. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/tests/unit/test_tasks.py +0 -0
  492. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/tests/unit/test_tasks_cli.py +0 -0
  493. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/tests/unit/test_templating.py +0 -0
  494. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/tests/unit/test_terminal_resize.py +0 -0
  495. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/tests/unit/test_tmux_template.py +0 -0
  496. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/tests/unit/test_tts_engine_resolution.py +0 -0
  497. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/tests/unit/test_tts_local.py +0 -0
  498. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/tests/unit/test_tunnels_probe.py +0 -0
  499. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/tests/unit/test_unattended_env_isolation.py +0 -0
  500. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/tests/unit/test_usage_limit.py +0 -0
  501. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/tests/unit/test_validation.py +0 -0
  502. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/tests/unit/test_voice_status.py +0 -0
  503. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/tests/unit/test_wiki.py +0 -0
  504. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/tests/unit/test_wiki_audit.py +0 -0
  505. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/tests/unit/test_window_cycling_binding.py +0 -0
  506. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/tests/unit/test_worktree.py +0 -0
  507. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/tests/unit/test_worktree_branch_cleanup.py +0 -0
  508. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/tests/unit/test_worktree_layout.py +0 -0
  509. {agentwire_dev-1.64.0 → agentwire_dev-1.65.1}/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.64.0
3
+ Version: 1.65.1
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.64.0"
3
+ __version__ = "1.65.1"
@@ -122,7 +122,6 @@ class ProjectsConfig:
122
122
 
123
123
  dir: Path = field(default_factory=lambda: Path.home() / "projects")
124
124
  worktrees: WorktreesConfig = field(default_factory=WorktreesConfig)
125
- extra: list = field(default_factory=list)
126
125
 
127
126
  def __post_init__(self):
128
127
  self.dir = _expand_path(self.dir) or Path.home() / "projects"
@@ -636,7 +635,6 @@ def _dict_to_config(data: dict) -> Config:
636
635
  projects = ProjectsConfig(
637
636
  dir=projects_data.get("dir", "~/projects"),
638
637
  worktrees=worktrees,
639
- extra=projects_data.get("extra", []),
640
638
  )
641
639
 
642
640
  # Worktree-session orchestration (`worktree:` key).
@@ -479,9 +479,21 @@ def resolve_default_created_by(caller: str | None, target_path: Path) -> str | N
479
479
  `{project}-{name}`, and would misjudge same/cross-project); if the
480
480
  caller's real cwd can't be confirmed, treat it as unknown (no inheritance)
481
481
  rather than risk a wrong guess.
482
+
483
+ A service session (agentwire-portal, -tts, -stt, -kokoro, ...) never
484
+ qualifies as a parent: it's infrastructure, not an agent that will ever
485
+ drain its msg inbox, so anything parented to it dead-letters forever. A
486
+ subprocess the portal shells out to inherits its TMUX_PANE and resolves
487
+ ``caller`` right back to "agentwire-portal" — this was the root cause of
488
+ a 147-message dead-letter storm (each mailing the owner individually,
489
+ 2026-07-19).
482
490
  """
483
491
  if not caller:
484
492
  return None
493
+ from .services import is_service_session
494
+
495
+ if is_service_session(caller):
496
+ return None
485
497
  caller_path = _live_session_cwd(caller)
486
498
  if caller_path is None:
487
499
  return None
@@ -741,7 +753,7 @@ def _record_session_creator(session_name: str, created_by: str | None, via: str)
741
753
 
742
754
 
743
755
  def _record_session_role(session_name: str, role: str | None) -> None:
744
- """Record the session's ROLE axis (orchestrator/worker) to disk (merge-preserving).
756
+ """Record the session's ROLE axis (orchestrator/worker/reviewer) to disk (merge-preserving).
745
757
 
746
758
  Distinct from the etiquette/persona ``roles:`` list in ``.agentwire.yml`` —
747
759
  this is the fundamental authority axis derived at creation time (``kind``
@@ -164,11 +164,14 @@ def current_session() -> str | None:
164
164
  return pane_manager.get_current_session()
165
165
 
166
166
 
167
- def open_artifact_window(url: str, title: str) -> bool:
168
- """Best-effort: open a rendered artifact as a portal window.
169
-
170
- Returns True only when the portal accepted the open; a down or erroring
171
- portal returns Falsethe artifact file exists on disk either way.
167
+ def notify_artifact(url: str, title: str) -> bool:
168
+ """Best-effort: announce a rendered artifact via a portal notification.
169
+
170
+ Posts a click-to-open notice (toast + HUD entry, #817) rather than
171
+ force-opening a windowa background render must never steal focus from
172
+ whatever the human is working in. Returns True only when the portal
173
+ accepted the notification; a down or erroring portal returns False — the
174
+ artifact file exists on disk either way.
172
175
  """
173
176
  import os
174
177
 
@@ -184,8 +187,8 @@ def open_artifact_window(url: str, title: str) -> bool:
184
187
  try:
185
188
  resp = core.portal_request(
186
189
  "POST",
187
- f"{portal}/api/desktop/window/open",
188
- json={"type": "artifact", "url": url, "title": title},
190
+ f"{portal}/api/desktop/notification",
191
+ json={"artifact": {"url": url, "title": title}},
189
192
  timeout=5,
190
193
  )
191
194
  return resp.status_code == 200 and bool(resp.json().get("success"))
@@ -372,20 +375,20 @@ def _synthesis_text(value: str | None) -> str:
372
375
  def _render_minutes(
373
376
  name: str, prompt_ids: list[int] | None = None, synthesis: str = ""
374
377
  ) -> tuple[str | None, bool | None]:
375
- """Write the minutes artifact and best-effort open it in the portal.
378
+ """Write the minutes artifact and best-effort announce it in the portal.
376
379
 
377
- Returns ``(path, opened)`` — both None when the sitting has no matching
378
- prompt history (nothing rendered, nothing opened).
380
+ Returns ``(path, notified)`` — both None when the sitting has no matching
381
+ prompt history (nothing rendered, nothing announced).
379
382
  """
380
383
  from agentwire.council import minutes
381
384
 
382
385
  path = minutes.write_minutes(name, prompt_ids, synthesis=synthesis)
383
386
  if path is None:
384
387
  return None, None
385
- opened = open_artifact_window(
388
+ notified = notify_artifact(
386
389
  minutes.artifact_url(name), f"Council minutes — {name}"
387
390
  )
388
- return str(path), opened
391
+ return str(path), notified
389
392
 
390
393
 
391
394
  def cmd_council_stop(args) -> int:
@@ -399,9 +402,9 @@ def cmd_council_stop(args) -> int:
399
402
  # Minutes before teardown (#708): tri-state --minutes/--no-minutes,
400
403
  # default (None) renders exactly when any prompt history exists.
401
404
  minutes_path: str | None = None
402
- minutes_opened: bool | None = None
405
+ minutes_notified: bool | None = None
403
406
  if getattr(args, "minutes", None) is not False:
404
- minutes_path, minutes_opened = _render_minutes(
407
+ minutes_path, minutes_notified = _render_minutes(
405
408
  name, synthesis=_synthesis_text(getattr(args, "synthesis", None))
406
409
  )
407
410
 
@@ -420,7 +423,7 @@ def cmd_council_stop(args) -> int:
420
423
  "killed": killed,
421
424
  "not_running": not_running,
422
425
  "minutes": minutes_path,
423
- "minutes_opened": minutes_opened,
426
+ "minutes_notified": minutes_notified,
424
427
  }
425
428
  human = (
426
429
  f"Council '{name}' stopped ({len(killed)} sessions killed). "
@@ -456,14 +459,14 @@ def cmd_council_minutes(args) -> int:
456
459
  f"(available: {', '.join(map(str, available))})",
457
460
  )
458
461
 
459
- path, opened = _render_minutes(
462
+ path, notified = _render_minutes(
460
463
  name, prompt_ids, synthesis=_synthesis_text(getattr(args, "synthesis", None))
461
464
  )
462
465
 
463
- payload = {"success": True, "path": path, "opened": opened}
466
+ payload = {"success": True, "path": path, "notified": notified}
464
467
  human = f"Minutes: {path}"
465
- if opened:
466
- human += "\nOpened as a portal artifact window."
468
+ if notified:
469
+ human += "\nAnnounced in the portal click the notification to open."
467
470
  return _emit(args, payload, human, council=name)
468
471
 
469
472
 
@@ -453,6 +453,7 @@ def gc_sender(sender: str) -> dict:
453
453
  # delivered, not lost. Skip GC for this recipient this round.
454
454
  continue
455
455
  try:
456
+ newly_dead: list[Message] = []
456
457
  for path in paths:
457
458
  if not path.exists():
458
459
  continue # delivered + unlinked just before we locked
@@ -472,7 +473,7 @@ def gc_sender(sender: str) -> dict:
472
473
  attempts=msg.attempts, reason="sender_exited",
473
474
  )
474
475
  dead += 1
475
- _escalate_dead_letter(msg, "sender_exited")
476
+ newly_dead.append(msg)
476
477
  except OSError:
477
478
  pass
478
479
  else:
@@ -481,6 +482,8 @@ def gc_sender(sender: str) -> dict:
481
482
  dropped += 1
482
483
  except OSError:
483
484
  pass
485
+ # One digest per recipient, not one email per message (#836).
486
+ _escalate_dead_letters(newly_dead, "sender_exited")
484
487
  finally:
485
488
  _release_lock(lock)
486
489
 
@@ -608,17 +611,32 @@ def _fmt_ts(ms: int) -> str:
608
611
  return time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(ms / 1000))
609
612
 
610
613
 
611
- def _escalate_dead_letter(msg: Message, reason: str) -> None:
612
- """Email the owner when a load-bearing report-back dead-letters.
614
+ # A single stuck recipient (e.g. a session wrongly parented to a service
615
+ # session that can never drain its inbox) can dead-letter dozens of messages
616
+ # in one drain pass — cap the per-message detail in the digest so the email
617
+ # stays readable instead of dumping an unbounded wall of text.
618
+ _ESCALATE_DIGEST_DETAIL_CAP = 10
619
+
620
+
621
+ def _escalate_dead_letters(messages: list[Message], reason: str) -> None:
622
+ """Email the owner once per batch when load-bearing report-backs dead-letter.
613
623
 
614
624
  ``done`` / ``request`` / ``escalation`` are load-bearing — a silently-dropped
615
625
  one is a real loss, so we surface it out-of-band via the shared Resend wiring
616
626
  (the same owner-escalation channel usage-limit parking uses). ``note`` and
617
- ``ingest`` are not escalated. Best-effort: a missing key or send failure must
618
- never break the drain — the corpse already sits in ``dead/`` for
619
- ``agentwire msg dead``.
627
+ ``ingest`` are not escalated.
628
+
629
+ *messages* is everything dead-lettered by one caller's batch (one drain
630
+ pass for one recipient, or one sender's GC sweep) — a single digest email
631
+ covers the whole batch instead of one email per message, so a recipient
632
+ that's been permanently undeliverable for a while (e.g. parented to a
633
+ service session that never drains) can't spam the owner's inbox one email
634
+ per stuck message (147 individual emails in ~2s, 2026-07-19). Best-effort:
635
+ a missing key or send failure must never break the drain — each corpse
636
+ already sits in ``dead/`` for ``agentwire msg dead``.
620
637
  """
621
- if msg.kind not in ESCALATE_KINDS:
638
+ batch = [m for m in messages if m.kind in ESCALATE_KINDS]
639
+ if not batch:
622
640
  return
623
641
  try:
624
642
  import socket
@@ -626,36 +644,47 @@ def _escalate_dead_letter(msg: Message, reason: str) -> None:
626
644
  from .channels.email import send_email
627
645
 
628
646
  host = socket.gethostname()
629
- subject = (
630
- f"[agentwire] undelivered {msg.kind}: {msg.sender} → {msg.to} (dead-lettered)"
631
- )
632
- body = "\n".join([
633
- f"A **{msg.kind}** message from **{msg.sender}** to **{msg.to}** on "
634
- f"`{host}` was never delivered after {msg.attempts} attempts and has "
635
- f"been dead-lettered.",
636
- "",
637
- f"- **Kind:** {msg.kind}",
638
- f"- **From:** {msg.sender}",
639
- f"- **To:** {msg.to}",
640
- f"- **Last defer reason:** {reason}",
641
- f"- **Sent:** {_fmt_ts(msg.ts)}",
642
- f"- **Dead-lettered:** {_fmt_ts(msg.dead_ts)}",
643
- "",
644
- "Message text:",
647
+ if len(batch) == 1:
648
+ msg = batch[0]
649
+ subject = (
650
+ f"[agentwire] undelivered {msg.kind}: {msg.sender} → {msg.to} (dead-lettered)"
651
+ )
652
+ else:
653
+ to = batch[0].to
654
+ subject = (
655
+ f"[agentwire] {len(batch)} undelivered messages → {to} (dead-lettered)"
656
+ )
657
+ noun = "message" if len(batch) == 1 else "messages"
658
+ verb = "was" if len(batch) == 1 else "were"
659
+ lines = [
660
+ f"{len(batch)} load-bearing {noun} on `{host}` {verb} never delivered "
661
+ f"and {'has' if len(batch) == 1 else 'have'} been dead-lettered "
662
+ f"(last defer reason: {reason}).",
645
663
  "",
646
- "```",
647
- msg.text,
648
- "```",
664
+ ]
665
+ for msg in batch[:_ESCALATE_DIGEST_DETAIL_CAP]:
666
+ lines += [
667
+ f"- **{msg.kind}** {msg.sender} → {msg.to}, sent {_fmt_ts(msg.ts)}, "
668
+ f"dead-lettered {_fmt_ts(msg.dead_ts)}, {msg.attempts} attempts:",
669
+ " ```",
670
+ f" {msg.text}",
671
+ " ```",
672
+ ]
673
+ remaining = len(batch) - _ESCALATE_DIGEST_DETAIL_CAP
674
+ if remaining > 0:
675
+ lines.append(f"- ...and {remaining} more.")
676
+ lines += [
649
677
  "",
650
- f"Saved in the dead-letter store — review with `agentwire msg dead -s {msg.to}`.",
651
- ])
652
- result = send_email(subject=subject, body=body)
678
+ f"Saved in the dead-letter store — review with "
679
+ f"`agentwire msg dead -s {batch[0].to}`.",
680
+ ]
681
+ result = send_email(subject=subject, body="\n".join(lines))
653
682
  _log_event(
654
- "dead_letter_escalated", id=msg.id, to=msg.to, kind=msg.kind,
683
+ "dead_letter_escalated", to=batch[0].to, count=len(batch), reason=reason,
655
684
  ok=bool(getattr(result, "success", False)),
656
685
  )
657
686
  except Exception as exc: # escalation is best-effort; never break the drain
658
- _log_event("dead_letter_escalate_failed", id=msg.id, to=msg.to, error=str(exc))
687
+ _log_event("dead_letter_escalate_failed", to=batch[0].to, count=len(batch), error=str(exc))
659
688
 
660
689
 
661
690
  def _bump_attempts(messages: list[Message], reason: str = "") -> int:
@@ -675,6 +704,7 @@ def _bump_attempts(messages: list[Message], reason: str = "") -> int:
675
704
  burns out on schedule.
676
705
  """
677
706
  dead = 0
707
+ newly_dead: list[Message] = []
678
708
  for msg in messages:
679
709
  if msg.path is None:
680
710
  continue
@@ -705,7 +735,7 @@ def _bump_attempts(messages: list[Message], reason: str = "") -> int:
705
735
  attempts=msg.attempts, reason=reason,
706
736
  )
707
737
  dead += 1
708
- _escalate_dead_letter(msg, reason)
738
+ newly_dead.append(msg)
709
739
  except OSError:
710
740
  pass
711
741
  else:
@@ -713,6 +743,9 @@ def _bump_attempts(messages: list[Message], reason: str = "") -> int:
713
743
  _write_message(msg.path, msg)
714
744
  except OSError:
715
745
  pass
746
+ # One digest email for the whole batch (all share the same recipient —
747
+ # `messages` is always one session's inbox), not one per message (#836).
748
+ _escalate_dead_letters(newly_dead, reason)
716
749
  return dead
717
750
 
718
751
 
@@ -212,9 +212,10 @@ def council_minutes(name: str = "", prompt: str = "", synthesis: str = "") -> st
212
212
  Deterministically renders the sitting's persisted prompt history
213
213
  (question + attributed take/ack/pass replies) plus your optional
214
214
  synthesis into a self-contained HTML artifact at
215
- ``~/.agentwire/artifacts/council-<name>-minutes/index.html``, and opens
216
- it as a portal artifact window when the portal is up. Works for live and
217
- dismissed sittings alike prompt history survives ``council_stop``.
215
+ ``~/.agentwire/artifacts/council-<name>-minutes/index.html``, and
216
+ announces it as a click-to-open portal notification when the portal is
217
+ up (#817never steals focus). Works for live and dismissed sittings
218
+ alike — prompt history survives ``council_stop``.
218
219
 
219
220
  Args:
220
221
  prompt: Prompt id to render, or 'all' (empty = all)
@@ -222,7 +223,7 @@ def council_minutes(name: str = "", prompt: str = "", synthesis: str = "") -> st
222
223
  name: Sitting name (empty = cwd-repo-slug / sole live sitting)
223
224
 
224
225
  Returns:
225
- The rendered artifact's path, and whether a portal window opened.
226
+ The rendered artifact's path, and whether the portal was notified.
226
227
  """
227
228
  args = ["council", "minutes"]
228
229
  if name:
@@ -235,6 +236,6 @@ def council_minutes(name: str = "", prompt: str = "", synthesis: str = "") -> st
235
236
  if not data.get("success"):
236
237
  return f"Failed to render minutes: {data.get('error') or data}"
237
238
  out = f"{_council_tag(data)}Minutes: {data.get('path')}"
238
- if data.get("opened"):
239
- out += "\nOpened as a portal artifact window."
239
+ if data.get("notified"):
240
+ out += "\nAnnounced in the portal the human clicks the notification to open."
240
241
  return out
@@ -106,9 +106,23 @@ def desktop_open_panel(panel_type: str) -> str:
106
106
  return f"Failed to open panel: {data.get('error', 'Unknown error')}"
107
107
 
108
108
 
109
+ def _announce_artifact(url: str, title: str, artifact_id: str | None) -> dict:
110
+ """POST the click-to-open artifact notification (#817) — the single
111
+ portal-side path for surfacing an artifact; there is no force-open."""
112
+ artifact = {"url": url, "title": title}
113
+ if artifact_id:
114
+ artifact["artifact_id"] = artifact_id
115
+ return _portal_request("POST", "/api/desktop/notification", {"artifact": artifact})
116
+
117
+
109
118
  @mcp.tool()
110
119
  def desktop_open_artifact(url: str, title: str = "Artifact", artifact_id: str | None = None) -> str:
111
- """Open a URL or local artifact file in an iframe window on the portal desktop.
120
+ """Announce a URL or local artifact file on the portal desktop (click-to-open).
121
+
122
+ Posts a notification (toast + Session HUD entry) carrying the artifact
123
+ target instead of force-opening a window (#817) — a background-produced
124
+ artifact must never steal focus. The human clicks the notice to open the
125
+ artifact window, focused.
112
126
 
113
127
  For local files, use a filename from ~/.agentwire/artifacts/ (e.g., "dashboard.html").
114
128
  For external sites, use a full URL (e.g., "https://example.com").
@@ -119,21 +133,12 @@ def desktop_open_artifact(url: str, title: str = "Artifact", artifact_id: str |
119
133
  artifact_id: Optional unique window ID. If omitted, derived from URL.
120
134
 
121
135
  Returns:
122
- Window ID of the opened window or error.
136
+ Notification ID or error description.
123
137
  """
124
- body = {
125
- "type": "artifact",
126
- "url": url,
127
- "title": title,
128
- }
129
- if artifact_id:
130
- body["artifact_id"] = artifact_id
131
-
132
- data = _portal_request("POST", "/api/desktop/window/open", body)
138
+ data = _announce_artifact(url, title, artifact_id)
133
139
  if data.get("success"):
134
- wid = data.get("window_id", "unknown")
135
- return f"Opened artifact window '{title}' (id: {wid})."
136
- return f"Failed to open artifact window: {data.get('error', 'Unknown error')}"
140
+ return f"Artifact '{title}' announced (notification id: {data.get('id', 'unknown')}) — the human clicks to open."
141
+ return f"Failed to announce artifact: {data.get('error', 'Unknown error')}"
137
142
 
138
143
 
139
144
  @mcp.tool()
@@ -143,11 +148,12 @@ def desktop_write_artifact(
143
148
  title: str = "Artifact",
144
149
  artifact_id: str | None = None,
145
150
  ) -> str:
146
- """Write HTML content to a file and open it as an artifact window.
151
+ """Write HTML content to a file and announce it as a click-to-open artifact.
147
152
 
148
- Atomically writes content to ~/.agentwire/artifacts/<filename>, then opens
149
- it in an iframe window on the portal desktop. Use this to display
150
- dashboards, diagrams, reports, or any HTML content.
153
+ Atomically writes content to ~/.agentwire/artifacts/<filename>, then posts
154
+ a click-to-open notification (toast + Session HUD entry, #817) the human
155
+ clicks to open the artifact window; it never steals focus. Use this to
156
+ deliver dashboards, diagrams, reports, or any HTML content.
151
157
 
152
158
  Args:
153
159
  filename: Output filename (must end in .html, e.g., "dashboard.html")
@@ -156,9 +162,8 @@ def desktop_write_artifact(
156
162
  artifact_id: Optional unique window ID. If omitted, derived from filename.
157
163
 
158
164
  Returns:
159
- Window ID of the opened window or error.
165
+ Notification ID or error description.
160
166
  """
161
- # Step 1: Upload the file
162
167
  upload_data = _portal_request("POST", "/api/artifacts/upload", {
163
168
  "filename": filename,
164
169
  "content": html_content,
@@ -166,20 +171,10 @@ def desktop_write_artifact(
166
171
  if not upload_data.get("success"):
167
172
  return f"Failed to write artifact: {upload_data.get('error', 'Unknown error')}"
168
173
 
169
- # Step 2: Open it as a window
170
- body = {
171
- "type": "artifact",
172
- "url": filename,
173
- "title": title,
174
- }
175
- if artifact_id:
176
- body["artifact_id"] = artifact_id
177
-
178
- open_data = _portal_request("POST", "/api/desktop/window/open", body)
174
+ open_data = _announce_artifact(filename, title, artifact_id)
179
175
  if open_data.get("success"):
180
- wid = open_data.get("window_id", "unknown")
181
- return f"Artifact '{filename}' written and opened (id: {wid})."
182
- return f"File written but failed to open window: {open_data.get('error', 'Unknown error')}"
176
+ return f"Artifact '{filename}' written and announced (notification id: {open_data.get('id', 'unknown')})."
177
+ return f"File written but failed to announce it: {open_data.get('error', 'Unknown error')}"
183
178
 
184
179
 
185
180
  @mcp.tool()
@@ -65,7 +65,8 @@ def notify_event(event: str, session: str | None = None) -> str:
65
65
 
66
66
 
67
67
  @mcp.tool()
68
- def notify_user(text: str, session: str | None = None, priority: str = "normal") -> str:
68
+ def notify_user(text: str, session: str | None = None, priority: str = "normal",
69
+ artifact_url: str | None = None, artifact_title: str | None = None) -> str:
69
70
  """Show the HUMAN a desktop toast on the portal (persistent, visual).
70
71
 
71
72
  The human-screen channel — the asymmetric text partner to `say` (audio).
@@ -74,11 +75,18 @@ def notify_user(text: str, session: str | None = None, priority: str = "normal")
74
75
  (portal lifecycle). Clicking the toast opens the session that generated the
75
76
  notification (the `session` below); a toast with no session is non-clickable.
76
77
 
78
+ With `artifact_url` set, the toast instead becomes a click-to-open artifact
79
+ notice (#817): it sticks until dismissed, also appears in the Session HUD,
80
+ and clicking it opens that artifact window — use this to hand the human a
81
+ rendered deliverable without stealing focus.
82
+
77
83
  Args:
78
84
  text: Notification text. Bold (**x**), line breaks, and [links](https://…)
79
85
  render; everything else is escaped.
80
86
  session: Session this relates to (shown as a badge).
81
87
  priority: 'normal' or 'high' (high gets an accent border).
88
+ artifact_url: URL or ~/.agentwire/artifacts/ filename to open on click.
89
+ artifact_title: Window title for the artifact (default: "Artifact").
82
90
 
83
91
  Returns:
84
92
  Notification ID or error description.
@@ -86,6 +94,8 @@ def notify_user(text: str, session: str | None = None, priority: str = "normal")
86
94
  body = {"text": text, "priority": priority}
87
95
  if session:
88
96
  body["session"] = session
97
+ if artifact_url:
98
+ body["artifact"] = {"url": artifact_url, "title": artifact_title or "Artifact"}
89
99
  data = _portal_request("POST", "/api/desktop/notification", body)
90
100
  if not data.get("success"):
91
101
  return f"Failed to post notification: {data.get('error', 'Unknown error')}"
@@ -258,7 +258,7 @@ def scheduler_report(since: str = "8h", artifact: bool = False) -> str:
258
258
 
259
259
  Args:
260
260
  since: Time window to cover (e.g. '8h', '12h', '1d') default: '8h'
261
- artifact: If True, open the report as a portal artifact window
261
+ artifact: If True, announce the report as a click-to-open portal notification
262
262
 
263
263
  Returns:
264
264
  Path to generated HTML report and summary statistics.
@@ -151,12 +151,16 @@ def session_create(
151
151
  spawns already auto-root (#715), so this is mainly for a
152
152
  same-project session you want detached, or to force standalone
153
153
  explicitly. Ignored when `created_by` is set (that wins).
154
- kind: Session role — "worker" or "orchestrator". A flat name (no
155
- branch) already defaults to orchestrator; a project/branch name
156
- defaults to worker (safety-railed: isolation/verify/draft-PR/
157
- notify). Pass "orchestrator" to override that default for a
158
- project/branch name — e.g. a durable branch-pinned project
159
- window. Leave empty for the derived default.
154
+ kind: Session role — "worker", "orchestrator", or "reviewer". A flat
155
+ name (no branch) already defaults to orchestrator; a
156
+ project/branch name defaults to worker (safety-railed:
157
+ isolation/verify/draft-PR/notify). Pass "orchestrator" to
158
+ override that default for a project/branch name — e.g. a durable
159
+ branch-pinned project window. Pass "reviewer" for a PR-review
160
+ station that adversarially reviews a sibling session's PR and
161
+ never opens/merges one of its own (safety-railed the other way —
162
+ non-overridable, parented rooting like worker, not rooted like
163
+ orchestrator). Leave empty for the derived default.
160
164
 
161
165
  Returns:
162
166
  Success message or error description.
@@ -33,9 +33,10 @@ def worktree_create(
33
33
  Args:
34
34
  name: Worktree/branch name (becomes the branch + session suffix).
35
35
  project_dir: Path to the git repo (default: server cwd).
36
- roles: Comma-separated roles STACKED on the intrinsic worker etiquette
37
- (e.g. "correspondent"). Never replaces the safety rail (kind=worker;
38
- for kind="orchestrator" these REPLACE the default persona instead).
36
+ roles: Comma-separated roles STACKED on the intrinsic worker/reviewer
37
+ etiquette (e.g. "correspondent"). Never replaces the safety rail
38
+ (kind=worker or kind=reviewer; for kind="orchestrator" these
39
+ REPLACE the default persona instead).
39
40
  base: Base branch to fork from (default: the repo's origin/HEAD).
40
41
  prompt: Optional first message — delivered once the agent is booted and
41
42
  ready (verified paste). Lets you spawn AND seed the task in one call
@@ -50,9 +51,13 @@ def worktree_create(
50
51
  roots by default (a durable orchestrator shouldn't inherit
51
52
  whoever spawned it).
52
53
  kind: Session role — "worker" (default: safety-railed, isolation/
53
- verify/draft-PR/notify, non-overridable) or "orchestrator" (a
54
+ verify/draft-PR/notify, non-overridable), "orchestrator" (a
54
55
  durable, replaceable-persona project window instead of a
55
- subordinate). Leave empty for the default.
56
+ subordinate), or "reviewer" (safety-railed the other way:
57
+ adversarially reviews a sibling session's PR, never opens or
58
+ merges one of its own; stays parented like worker, not rooted
59
+ like orchestrator — for anyone who needs a local checkout to e2e
60
+ a sibling's branch). Leave empty for the default.
56
61
 
57
62
  Returns:
58
63
  Success message with the session name + worktree path, or an error.
@@ -149,7 +149,11 @@ def cmd_notify_parent(args) -> int:
149
149
 
150
150
 
151
151
  def cmd_open(args) -> int:
152
- """Open a URL or local file as an artifact window in the portal.
152
+ """Announce a URL or local file as a click-to-open artifact notification.
153
+
154
+ Posts a portal notification (toast + Session HUD entry) carrying the
155
+ artifact target instead of force-opening a window (#817) — the window
156
+ opens, focused, only when the human clicks the notice.
153
157
 
154
158
  Examples:
155
159
  agentwire open dashboard.html --title "Dashboard"
@@ -167,26 +171,23 @@ def cmd_open(args) -> int:
167
171
 
168
172
  portal_url = _get_portal_url()
169
173
 
170
- body = {
171
- "type": "artifact",
172
- "url": url,
173
- "title": title,
174
- }
174
+ artifact = {"url": url, "title": title}
175
175
  if artifact_id:
176
- body["artifact_id"] = artifact_id
176
+ artifact["artifact_id"] = artifact_id
177
177
 
178
178
  try:
179
179
  resp = portal_request(
180
180
  "POST",
181
- f"{portal_url}/api/desktop/window/open",
182
- json=body,
181
+ f"{portal_url}/api/desktop/notification",
182
+ json={"artifact": artifact},
183
183
  )
184
184
  data = resp.json()
185
185
 
186
186
  if json_output:
187
187
  print(json.dumps(data))
188
188
  elif data.get("success"):
189
- print(f"Opened artifact window: {title} (id: {data.get('window_id', 'unknown')})")
189
+ print(f"Artifact announced: {title} (notification id: {data.get('id', 'unknown')}) "
190
+ "— click the toast or HUD entry to open")
190
191
  else:
191
192
  print(f"Failed: {data.get('error', 'Unknown error')}", file=sys.stderr)
192
193
  return 1
@@ -311,11 +312,11 @@ def register_notify_parser(subparsers) -> None:
311
312
  notify_cmd_parser.add_argument("--json", action="store_true", help="Output as JSON")
312
313
  notify_cmd_parser.set_defaults(func=cmd_notify_parent)
313
314
 
314
- # === open command (artifact windows) ===
315
- open_parser = subparsers.add_parser("open", help="Open a URL or local file as an artifact window in the portal")
316
- open_parser.add_argument("url", help="URL or filename to open (filenames served from ~/.agentwire/artifacts/)")
315
+ # === open command (artifact notifications) ===
316
+ open_parser = subparsers.add_parser("open", help="Announce a URL or local file as a click-to-open artifact notification in the portal")
317
+ open_parser.add_argument("url", help="URL or filename to announce (filenames served from ~/.agentwire/artifacts/)")
317
318
  open_parser.add_argument("--title", "-t", type=str, default="Artifact", help="Window title")
318
- open_parser.add_argument("--artifact-id", type=str, help="Unique window ID (auto-generated if omitted)")
319
+ open_parser.add_argument("--artifact-id", type=str, help="Unique window ID for the opened artifact (auto-generated if omitted)")
319
320
  open_parser.add_argument("--json", action="store_true", help="Output JSON")
320
321
  open_parser.set_defaults(func=cmd_open)
321
322