agentwire-dev 1.60.0__tar.gz → 1.62.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (500) hide show
  1. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/PKG-INFO +1 -1
  2. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/__init__.py +1 -1
  3. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/core.py +117 -20
  4. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/doctor_cli.py +24 -0
  5. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/limits_cli.py +16 -6
  6. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/mcp_worktree.py +9 -1
  7. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/pane_cli.py +2 -0
  8. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/routes/notify.py +12 -1
  9. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/routes/projects.py +62 -0
  10. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/routes/sessions_admin.py +4 -4
  11. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/scheduler/__init__.py +4 -0
  12. agentwire_dev-1.62.0/agentwire/scheduler/zombie.py +160 -0
  13. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/session_cli.py +151 -47
  14. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/static/css/desktop.css +893 -0
  15. agentwire_dev-1.62.0/agentwire/static/js/card-terminal.js +260 -0
  16. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/static/js/collage.js +110 -5
  17. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/static/js/desktop-manager.js +11 -1
  18. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/static/js/desktop.js +274 -7
  19. agentwire_dev-1.62.0/agentwire/static/js/lineage.js +138 -0
  20. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/static/js/scratchpad.js +4 -0
  21. agentwire_dev-1.62.0/agentwire/static/js/session-hud-controller.js +227 -0
  22. agentwire_dev-1.62.0/agentwire/static/js/session-hud-spawn.js +144 -0
  23. agentwire_dev-1.62.0/agentwire/static/js/session-hud.js +299 -0
  24. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/static/js/session-window.js +97 -569
  25. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/static/js/shortcuts.js +1 -0
  26. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/static/js/sidebar/config-section.js +37 -2
  27. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/static/js/sidebar/sessions-section.js +34 -3
  28. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/static/js/sidebar.js +6 -3
  29. agentwire_dev-1.62.0/agentwire/static/js/spawn-ghost.js +105 -0
  30. agentwire_dev-1.62.0/agentwire/static/js/terminal-pane.js +779 -0
  31. agentwire_dev-1.62.0/agentwire/static/js/topology-render.js +610 -0
  32. agentwire_dev-1.62.0/agentwire/static/js/workspace-window.js +141 -0
  33. agentwire_dev-1.62.0/agentwire/static/topology-harness.html +120 -0
  34. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/docs/wiki/INDEX.md +1 -0
  35. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/docs/wiki/internals/portal.md +3 -1
  36. agentwire_dev-1.62.0/docs/wiki/internals/session-topology.md +93 -0
  37. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/docs/wiki/internals/window-collage.md +4 -1
  38. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/docs/wiki/sessions/worktree-sessions.md +25 -0
  39. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/tests/integration/test_worktree_cmd.py +182 -0
  40. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/tests/unit/test_cli_commands.py +81 -0
  41. agentwire_dev-1.62.0/tests/unit/test_guarded_launch_command.py +73 -0
  42. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/tests/unit/test_limits_tick_isolation.py +5 -2
  43. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/tests/unit/test_portal_api.py +51 -0
  44. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/tests/unit/test_routes_snapshot.py +2 -0
  45. agentwire_dev-1.62.0/tests/unit/test_scheduler_zombie.py +269 -0
  46. agentwire_dev-1.62.0/tests/unit/test_session_created_by_env.py +56 -0
  47. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/tests/unit/test_worktree_branch_cleanup.py +112 -0
  48. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/.agentwire.yml.example +0 -0
  49. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/.claude/commands/handoff.md +0 -0
  50. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/.claude/skills/wiki/SKILL.md +0 -0
  51. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/.github/FUNDING.yml +0 -0
  52. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
  53. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
  54. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/.github/ISSUE_TEMPLATE/question.md +0 -0
  55. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
  56. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/.github/workflows/pytest.yml +0 -0
  57. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/.github/workflows/ruff.yml +0 -0
  58. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/.github/workflows/security.yml +0 -0
  59. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/.github/workflows/tts-smoke.yml +0 -0
  60. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/.gitignore +0 -0
  61. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/AGENTS.md +0 -0
  62. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/CODE_OF_CONDUCT.md +0 -0
  63. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/CONTRIBUTING.md +0 -0
  64. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/Dockerfile.local +0 -0
  65. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/LICENSE +0 -0
  66. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/README.md +0 -0
  67. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/RELEASING.md +0 -0
  68. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/SECURITY.md +0 -0
  69. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/SPONSORS.md +0 -0
  70. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/__main__.py +0 -0
  71. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/agents/__init__.py +0 -0
  72. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/agents/base.py +0 -0
  73. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/agents/tmux.py +0 -0
  74. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/cached_status.py +0 -0
  75. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/channels/__init__.py +0 -0
  76. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/channels/base.py +0 -0
  77. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/channels/email.py +0 -0
  78. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/channels/push.py +0 -0
  79. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/channels/quo.py +0 -0
  80. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/channels_cli.py +0 -0
  81. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/chrome_tabs.py +0 -0
  82. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/completion.py +0 -0
  83. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/config.py +0 -0
  84. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/config_cli.py +0 -0
  85. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/council/__init__.py +0 -0
  86. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/council/cli.py +0 -0
  87. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/council/inbox.py +0 -0
  88. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/council/minutes.py +0 -0
  89. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/council/state.py +0 -0
  90. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/council/view.py +0 -0
  91. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/devices.py +0 -0
  92. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/diff_cli.py +0 -0
  93. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/doctor_voice.py +0 -0
  94. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/ensure_cli.py +0 -0
  95. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/fetch.py +0 -0
  96. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/handoff/__init__.py +0 -0
  97. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/handoff/git_state.py +0 -0
  98. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/handoff/instructions.py +0 -0
  99. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/handoff/parser.py +0 -0
  100. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/handoff/renderer.py +0 -0
  101. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/handoff/schema.py +0 -0
  102. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/handoff_cli.py +0 -0
  103. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/history.py +0 -0
  104. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/history_cli.py +0 -0
  105. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/hooks/__init__.py +0 -0
  106. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/hooks/agentwire-permission.sh +0 -0
  107. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/hooks/damage-control/__init__.py +0 -0
  108. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/hooks/damage-control/audit_logger.py +0 -0
  109. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/hooks/damage-control/bash-tool-damage-control.py +0 -0
  110. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/hooks/damage-control/edit-tool-damage-control.py +0 -0
  111. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/hooks/damage-control/mcp-tool-damage-control.py +0 -0
  112. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/hooks/damage-control/read-tool-damage-control.py +0 -0
  113. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/hooks/damage-control/rules/agentwire.yaml +0 -0
  114. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/hooks/damage-control/rules/aws.yaml +0 -0
  115. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/hooks/damage-control/rules/cloud-hosting.yaml +0 -0
  116. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/hooks/damage-control/rules/containers.yaml +0 -0
  117. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/hooks/damage-control/rules/control-plane.yaml +0 -0
  118. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/hooks/damage-control/rules/core.yaml +0 -0
  119. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/hooks/damage-control/rules/databases.yaml +0 -0
  120. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/hooks/damage-control/rules/firebase.yaml +0 -0
  121. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/hooks/damage-control/rules/gcp.yaml +0 -0
  122. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/hooks/damage-control/rules/git.yaml +0 -0
  123. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/hooks/damage-control/rules/gws.yaml +0 -0
  124. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/hooks/damage-control/rules/infrastructure.yaml +0 -0
  125. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/hooks/damage-control/rules/outbound.yaml +0 -0
  126. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/hooks/damage-control/rules/publish.yaml +0 -0
  127. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/hooks/damage-control/rules/remote.yaml +0 -0
  128. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/hooks/damage-control/write-tool-damage-control.py +0 -0
  129. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/hooks/idle-handler.sh +0 -0
  130. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/hooks/queue-processor.sh +0 -0
  131. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/hooks_cli.py +0 -0
  132. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/inbox.py +0 -0
  133. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/listen.py +0 -0
  134. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/locking.py +0 -0
  135. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/machine_cli.py +0 -0
  136. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/mcp_channels.py +0 -0
  137. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/mcp_chrome.py +0 -0
  138. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/mcp_cli.py +0 -0
  139. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/mcp_core.py +0 -0
  140. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/mcp_council.py +0 -0
  141. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/mcp_desktop.py +0 -0
  142. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/mcp_handoff.py +0 -0
  143. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/mcp_history.py +0 -0
  144. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/mcp_listen.py +0 -0
  145. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/mcp_lock.py +0 -0
  146. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/mcp_machine.py +0 -0
  147. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/mcp_msg.py +0 -0
  148. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/mcp_notify.py +0 -0
  149. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/mcp_pane.py +0 -0
  150. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/mcp_projects.py +0 -0
  151. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/mcp_scheduler.py +0 -0
  152. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/mcp_scratchpad.py +0 -0
  153. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/mcp_server.py +0 -0
  154. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/mcp_services.py +0 -0
  155. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/mcp_session.py +0 -0
  156. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/mcp_status.py +0 -0
  157. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/mcp_task.py +0 -0
  158. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/mcp_tunnels.py +0 -0
  159. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/mcp_voice.py +0 -0
  160. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/mcp_wiki.py +0 -0
  161. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/msg_cli.py +0 -0
  162. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/network.py +0 -0
  163. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/notify_cli.py +0 -0
  164. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/onboarding.py +0 -0
  165. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/palette_cli.py +0 -0
  166. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/pane_manager.py +0 -0
  167. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/portal_cli.py +0 -0
  168. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/project_config.py +0 -0
  169. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/projects.py +0 -0
  170. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/prompt_router.py +0 -0
  171. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/prompts_cli.py +0 -0
  172. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/push_cli.py +0 -0
  173. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/push_store.py +0 -0
  174. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/repo_cli.py +0 -0
  175. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/research.py +0 -0
  176. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/roles/__init__.py +0 -0
  177. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/roles/agentwire.md +0 -0
  178. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/roles/anchor.md +0 -0
  179. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/roles/chatbot.md +0 -0
  180. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/roles/contributor.md +0 -0
  181. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/roles/correspondent.md +0 -0
  182. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/roles/council-brain.md +0 -0
  183. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/roles/council-conscience.md +0 -0
  184. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/roles/council-critic.md +0 -0
  185. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/roles/council-devils-advocate.md +0 -0
  186. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/roles/council-gut.md +0 -0
  187. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/roles/council-historian.md +0 -0
  188. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/roles/council-member.md +0 -0
  189. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/roles/council-orchestrator.md +0 -0
  190. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/roles/init.md +0 -0
  191. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/roles/notifications.md +0 -0
  192. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/roles/orchestrator.md +0 -0
  193. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/roles/soul.md +0 -0
  194. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/roles/task-runner.md +0 -0
  195. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/roles/voice.md +0 -0
  196. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/roles/worker-worktree.md +0 -0
  197. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/roles/worker.md +0 -0
  198. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/roles_cli.py +0 -0
  199. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/routes/__init__.py +0 -0
  200. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/routes/artifacts.py +0 -0
  201. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/routes/config.py +0 -0
  202. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/routes/council.py +0 -0
  203. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/routes/desktop.py +0 -0
  204. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/routes/history.py +0 -0
  205. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/routes/machines.py +0 -0
  206. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/routes/palette.py +0 -0
  207. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/routes/permission.py +0 -0
  208. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/routes/push.py +0 -0
  209. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/routes/safety.py +0 -0
  210. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/routes/scheduler.py +0 -0
  211. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/routes/scratchpad.py +0 -0
  212. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/routes/sessions.py +0 -0
  213. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/routes/voice.py +0 -0
  214. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/safety/__init__.py +0 -0
  215. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/safety/_core.py +0 -0
  216. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/safety_cli.py +0 -0
  217. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/safety_commands.py +0 -0
  218. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/scheduler/dispatch.py +0 -0
  219. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/scheduler/gates.py +0 -0
  220. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/scheduler/loop.py +0 -0
  221. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/scheduler/models.py +0 -0
  222. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/scheduler/report.py +0 -0
  223. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/scheduler/schedule.py +0 -0
  224. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/scheduler/state.py +0 -0
  225. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/scheduler_cli.py +0 -0
  226. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/scratchpad.py +0 -0
  227. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/security.py +0 -0
  228. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/send_cli.py +0 -0
  229. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/server.py +0 -0
  230. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/services.py +0 -0
  231. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/session_context.py +0 -0
  232. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/session_ready.py +0 -0
  233. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/ssh.py +0 -0
  234. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/static/agentwire-splash-logo-layers--agentwire-text.png +0 -0
  235. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/static/agentwire-splash-logo-layers--echo-claw-fg.png +0 -0
  236. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/static/agentwire-splash-logo-layers--echo.png +0 -0
  237. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/static/agentwire-splash-logo-layers--telephone.png +0 -0
  238. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/static/agentwire-splash-logo-layers--tree.png +0 -0
  239. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/static/announcements.json +0 -0
  240. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/static/apple-touch-icon.png +0 -0
  241. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/static/css/mobile.css +0 -0
  242. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/static/favicon-32.png +0 -0
  243. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/static/favicon-64.png +0 -0
  244. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/static/icons/sessions/bear.webp +0 -0
  245. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/static/icons/sessions/cat.webp +0 -0
  246. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/static/icons/sessions/crown.webp +0 -0
  247. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/static/icons/sessions/custom/agentwire-portal.webp +0 -0
  248. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/static/icons/sessions/custom/agentwire-tts.webp +0 -0
  249. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/static/icons/sessions/custom/agentwire.webp +0 -0
  250. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/static/icons/sessions/deer.webp +0 -0
  251. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/static/icons/sessions/drone.webp +0 -0
  252. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/static/icons/sessions/eagle.webp +0 -0
  253. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/static/icons/sessions/fox.webp +0 -0
  254. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/static/icons/sessions/hawk.webp +0 -0
  255. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/static/icons/sessions/horse.webp +0 -0
  256. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/static/icons/sessions/lion.webp +0 -0
  257. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/static/icons/sessions/rabbit.webp +0 -0
  258. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/static/icons/sessions/robot.webp +0 -0
  259. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/static/icons/sessions/tiger.webp +0 -0
  260. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/static/icons/sessions/wolf.webp +0 -0
  261. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/static/img/icon-192.png +0 -0
  262. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/static/img/icon-512.png +0 -0
  263. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/static/js/.gitkeep +0 -0
  264. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/static/js/announcement-modal.js +0 -0
  265. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/static/js/api.js +0 -0
  266. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/static/js/artifact-window.js +0 -0
  267. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/static/js/command-palette.js +0 -0
  268. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/static/js/council-window.js +0 -0
  269. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/static/js/dead-key-suppressor.js +0 -0
  270. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/static/js/help-modal.js +0 -0
  271. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/static/js/icon-manager.js +0 -0
  272. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/static/js/mobile.js +0 -0
  273. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/static/js/notification-prefs.js +0 -0
  274. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/static/js/notifications-panel.js +0 -0
  275. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/static/js/ptt.js +0 -0
  276. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/static/js/push-client.js +0 -0
  277. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/static/js/review-window.js +0 -0
  278. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/static/js/safety-shared.js +0 -0
  279. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/static/js/safety-window.js +0 -0
  280. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/static/js/service-classification.js +0 -0
  281. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/static/js/session-id.js +0 -0
  282. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/static/js/sidebar/artifacts-section.js +0 -0
  283. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/static/js/sidebar/council-section.js +0 -0
  284. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/static/js/sidebar/machines-section.js +0 -0
  285. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/static/js/sidebar/projects-section.js +0 -0
  286. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/static/js/sidebar/safety-section.js +0 -0
  287. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/static/js/sidebar/scheduler-section.js +0 -0
  288. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/static/js/sidebar/services-section.js +0 -0
  289. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/static/js/terminal-font-prefs.js +0 -0
  290. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/static/js/tile-manager.js +0 -0
  291. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/static/js/toast.js +0 -0
  292. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/static/js/token-modal.js +0 -0
  293. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/static/js/utils/ansi.js +0 -0
  294. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/static/js/utils/swipe.js +0 -0
  295. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/static/js/voice/autosend-prefs.js +0 -0
  296. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/static/js/voice/browser-stt.js +0 -0
  297. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/static/js/voice/browser-tts.js +0 -0
  298. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/static/js/voice/jargon.js +0 -0
  299. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/static/js/voice/prompt.js +0 -0
  300. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/static/js/winbox.bundle.min.js +0 -0
  301. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/static/manifest.webmanifest +0 -0
  302. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/static/service-worker.js +0 -0
  303. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/stt/__init__.py +0 -0
  304. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/stt/base.py +0 -0
  305. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/stt/cloud.py +0 -0
  306. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/stt/engine.py +0 -0
  307. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/stt/local.py +0 -0
  308. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/stt/server_backend.py +0 -0
  309. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/stt/stt_server.py +0 -0
  310. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/system_cli.py +0 -0
  311. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/tabs_cli.py +0 -0
  312. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/tasks.py +0 -0
  313. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/tasks_cli.py +0 -0
  314. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/templates/__init__.py +0 -0
  315. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/templates/base.html +0 -0
  316. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/templates/council/minutes.html.j2 +0 -0
  317. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/templates/desktop.html +0 -0
  318. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/templates/email_notification.html +0 -0
  319. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/templates/handoff/show-the-story.html.j2 +0 -0
  320. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/templates/handoff/theme.css.j2 +0 -0
  321. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/templates/mobile.html +0 -0
  322. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/templates/pair.html +0 -0
  323. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/templates/tmux.conf +0 -0
  324. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/templating.py +0 -0
  325. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/tooldefs/aws.yaml +0 -0
  326. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/tooldefs/docker.yaml +0 -0
  327. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/tooldefs/gcp.yaml +0 -0
  328. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/tooldefs/gh.yaml +0 -0
  329. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/tooldefs/git.yaml +0 -0
  330. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/tooldefs/gws.yaml +0 -0
  331. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/tooldefs/kubectl.yaml +0 -0
  332. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/tooldefs/npm.yaml +0 -0
  333. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/tooldefs/terraform.yaml +0 -0
  334. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/tooldefs/uv.yaml +0 -0
  335. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/tts/__init__.py +0 -0
  336. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/tts/audio.py +0 -0
  337. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/tts/base.py +0 -0
  338. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/tts/engines/__init__.py +0 -0
  339. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/tts/engines/chatterbox.py +0 -0
  340. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/tts/engines/kokoro.py +0 -0
  341. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/tts/engines/zonos.py +0 -0
  342. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/tts/kokoro_server.py +0 -0
  343. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/tts/local.py +0 -0
  344. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/tts/registry.py +0 -0
  345. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/tts_cli.py +0 -0
  346. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/tts_server.py +0 -0
  347. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/tunnels.py +0 -0
  348. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/tunnels_cli.py +0 -0
  349. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/usage_limit.py +0 -0
  350. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/utils/__init__.py +0 -0
  351. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/utils/chunker.py +0 -0
  352. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/utils/event_log.py +0 -0
  353. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/utils/file_io.py +0 -0
  354. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/utils/paths.py +0 -0
  355. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/utils/speech.py +0 -0
  356. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/utils/subprocess.py +0 -0
  357. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/validation.py +0 -0
  358. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/voice_status.py +0 -0
  359. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/wiki.py +0 -0
  360. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/wiki_audit.py +0 -0
  361. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/wiki_cli.py +0 -0
  362. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/worktree.py +0 -0
  363. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/agentwire/worktree_registry.py +0 -0
  364. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/docs/decisions/obsidian-second-brain.md +0 -0
  365. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/docs/logo.png +0 -0
  366. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/docs/wiki/architecture.md +0 -0
  367. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/docs/wiki/briefing-mode.md +0 -0
  368. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/docs/wiki/communication/channels.md +0 -0
  369. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/docs/wiki/communication/hammerspoon.md +0 -0
  370. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/docs/wiki/communication/handoff.md +0 -0
  371. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/docs/wiki/concepts.md +0 -0
  372. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/docs/wiki/council.md +0 -0
  373. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/docs/wiki/deployment/remote-access.md +0 -0
  374. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/docs/wiki/deployment/remote-machines.md +0 -0
  375. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/docs/wiki/glossary.md +0 -0
  376. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/docs/wiki/integrations/gws-google-workspace-cli.md +0 -0
  377. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/docs/wiki/internals/damage-control.md +0 -0
  378. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/docs/wiki/internals/parallel-refactor.md +0 -0
  379. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/docs/wiki/internals/shell-escaping.md +0 -0
  380. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/docs/wiki/internals/troubleshooting.md +0 -0
  381. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/docs/wiki/quickstart.md +0 -0
  382. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/docs/wiki/research/briefing-mode-feasibility.md +0 -0
  383. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/docs/wiki/research/orchestration-transport-alternatives.md +0 -0
  384. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/docs/wiki/scheduling/scheduled-workloads.md +0 -0
  385. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/docs/wiki/security/damage-control-hardening.md +0 -0
  386. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/docs/wiki/security/pip-audit.md +0 -0
  387. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/docs/wiki/security/remote-access-hardening.md +0 -0
  388. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/docs/wiki/security/secrets.md +0 -0
  389. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/docs/wiki/services.md +0 -0
  390. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/docs/wiki/sessions/claude-code-auto-mode.md +0 -0
  391. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/docs/wiki/sessions/messaging.md +0 -0
  392. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/docs/wiki/sessions/prompt-routing.md +0 -0
  393. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/docs/wiki/sessions/window-sizing.md +0 -0
  394. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/docs/wiki/usage-limit-recovery.md +0 -0
  395. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/docs/wiki/voice/shim-contract.md +0 -0
  396. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/docs/wiki/voice/stt-cloud.md +0 -0
  397. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/docs/wiki/voice/stt-self-hosted.md +0 -0
  398. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/docs/wiki/voice/tts-self-hosted.md +0 -0
  399. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/pyproject.toml +0 -0
  400. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/tests/conftest.py +0 -0
  401. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/tests/e2e/test_portal_ui.py +0 -0
  402. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/tests/fixtures/sample_agentwire.yml +0 -0
  403. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/tests/fixtures/sample_config.yaml +0 -0
  404. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/tests/fixtures/sample_scheduler.yaml +0 -0
  405. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/tests/integration/test_council_portal.py +0 -0
  406. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/tests/integration/test_scheduler_board.py +0 -0
  407. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/tests/integration/test_send_verified_tmux.py +0 -0
  408. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/tests/integration/test_server_websockets.py +0 -0
  409. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/tests/unit/test_announcements.py +0 -0
  410. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/tests/unit/test_build_agent_command.py +0 -0
  411. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/tests/unit/test_channels.py +0 -0
  412. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/tests/unit/test_chrome_tabs.py +0 -0
  413. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/tests/unit/test_cli_output.py +0 -0
  414. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/tests/unit/test_cli_smoke.py +0 -0
  415. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/tests/unit/test_config.py +0 -0
  416. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/tests/unit/test_config_cli.py +0 -0
  417. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/tests/unit/test_control_plane_protection.py +0 -0
  418. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/tests/unit/test_core_created_by_rooting.py +0 -0
  419. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/tests/unit/test_council_cli.py +0 -0
  420. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/tests/unit/test_council_inbox.py +0 -0
  421. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/tests/unit/test_council_minutes.py +0 -0
  422. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/tests/unit/test_council_state.py +0 -0
  423. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/tests/unit/test_council_view.py +0 -0
  424. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/tests/unit/test_damage_control_bypass.py +0 -0
  425. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/tests/unit/test_damage_control_hooks.py +0 -0
  426. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/tests/unit/test_damage_control_sync.py +0 -0
  427. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/tests/unit/test_dangling_worktrees.py +0 -0
  428. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/tests/unit/test_devices.py +0 -0
  429. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/tests/unit/test_diff_cli.py +0 -0
  430. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/tests/unit/test_doctor_task_migration.py +0 -0
  431. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/tests/unit/test_doctor_voice.py +0 -0
  432. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/tests/unit/test_event_log.py +0 -0
  433. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/tests/unit/test_file_io.py +0 -0
  434. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/tests/unit/test_handoff_git_state.py +0 -0
  435. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/tests/unit/test_handoff_instructions.py +0 -0
  436. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/tests/unit/test_handoff_parser.py +0 -0
  437. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/tests/unit/test_handoff_renderer.py +0 -0
  438. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/tests/unit/test_history.py +0 -0
  439. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/tests/unit/test_hooks_install.py +0 -0
  440. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/tests/unit/test_idle_handler.py +0 -0
  441. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/tests/unit/test_idle_nag.py +0 -0
  442. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/tests/unit/test_inbox.py +0 -0
  443. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/tests/unit/test_init_command.py +0 -0
  444. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/tests/unit/test_install_parity.py +0 -0
  445. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/tests/unit/test_locking.py +0 -0
  446. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/tests/unit/test_mcp_server.py +0 -0
  447. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/tests/unit/test_mcp_tools_args.py +0 -0
  448. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/tests/unit/test_msg_cli.py +0 -0
  449. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/tests/unit/test_notify_cli.py +0 -0
  450. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/tests/unit/test_onboarding_reinit.py +0 -0
  451. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/tests/unit/test_palette_cli.py +0 -0
  452. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/tests/unit/test_pip_environment.py +0 -0
  453. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/tests/unit/test_posture_default.py +0 -0
  454. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/tests/unit/test_project_config.py +0 -0
  455. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/tests/unit/test_prompt_router.py +0 -0
  456. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/tests/unit/test_push.py +0 -0
  457. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/tests/unit/test_rebuild_guard.py +0 -0
  458. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/tests/unit/test_repo_cli.py +0 -0
  459. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/tests/unit/test_roles.py +0 -0
  460. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/tests/unit/test_safety_commands.py +0 -0
  461. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/tests/unit/test_safety_disabled_rules.py +0 -0
  462. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/tests/unit/test_safety_escape_hatch.py +0 -0
  463. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/tests/unit/test_safety_heal.py +0 -0
  464. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/tests/unit/test_safety_kill_switch.py +0 -0
  465. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/tests/unit/test_scheduler.py +0 -0
  466. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/tests/unit/test_scheduler_parsing.py +0 -0
  467. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/tests/unit/test_scratchpad.py +0 -0
  468. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/tests/unit/test_security.py +0 -0
  469. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/tests/unit/test_server_async.py +0 -0
  470. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/tests/unit/test_server_pure.py +0 -0
  471. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/tests/unit/test_services.py +0 -0
  472. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/tests/unit/test_session_context.py +0 -0
  473. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/tests/unit/test_session_ready.py +0 -0
  474. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/tests/unit/test_shared_dir_guard.py +0 -0
  475. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/tests/unit/test_shim_selfheal.py +0 -0
  476. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/tests/unit/test_skill_install.py +0 -0
  477. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/tests/unit/test_speech_tags.py +0 -0
  478. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/tests/unit/test_ssh.py +0 -0
  479. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/tests/unit/test_stt_backend.py +0 -0
  480. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/tests/unit/test_stt_cloud.py +0 -0
  481. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/tests/unit/test_stt_engine.py +0 -0
  482. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/tests/unit/test_task_cli.py +0 -0
  483. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/tests/unit/test_tasks.py +0 -0
  484. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/tests/unit/test_tasks_cli.py +0 -0
  485. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/tests/unit/test_templating.py +0 -0
  486. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/tests/unit/test_terminal_resize.py +0 -0
  487. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/tests/unit/test_tmux_template.py +0 -0
  488. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/tests/unit/test_tts_engine_resolution.py +0 -0
  489. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/tests/unit/test_tts_local.py +0 -0
  490. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/tests/unit/test_tunnels_probe.py +0 -0
  491. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/tests/unit/test_unattended_env_isolation.py +0 -0
  492. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/tests/unit/test_usage_limit.py +0 -0
  493. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/tests/unit/test_validation.py +0 -0
  494. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/tests/unit/test_voice_status.py +0 -0
  495. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/tests/unit/test_wiki.py +0 -0
  496. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/tests/unit/test_wiki_audit.py +0 -0
  497. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/tests/unit/test_window_cycling_binding.py +0 -0
  498. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/tests/unit/test_worktree.py +0 -0
  499. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/tests/unit/test_worktree_layout.py +0 -0
  500. {agentwire_dev-1.60.0 → agentwire_dev-1.62.0}/tests/unit/test_worktree_registry.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: agentwire-dev
3
- Version: 1.60.0
3
+ Version: 1.62.0
4
4
  Summary: Multi-session voice web interface for AI coding agents
5
5
  Project-URL: Homepage, https://agentwire.dev
6
6
  Project-URL: Repository, https://github.com/dotdevdotdev/agentwire-dev
@@ -1,3 +1,3 @@
1
1
  """AgentWire - Multi-session voice web interface for AI coding agents."""
2
2
 
3
- __version__ = "1.60.0"
3
+ __version__ = "1.62.0"
@@ -148,15 +148,25 @@ def _build_tmux_env_flags_shell(env: dict[str, str]) -> str:
148
148
  return " ".join(parts) + " "
149
149
 
150
150
 
151
- def _set_session_name_env(agent: "AgentCommand", session_name: str) -> None:
152
- """Stamp ``AGENTWIRE_SESSION_NAME`` onto an ``AgentCommand.env``.
151
+ def _set_session_name_env(agent: "AgentCommand", session_name: str, created_by: str | None = None) -> None:
152
+ """Stamp ``AGENTWIRE_SESSION_NAME`` (and, when there's a real parent,
153
+ ``AGENTWIRE_CREATED_BY``) onto an ``AgentCommand.env``.
153
154
 
154
155
  Every session created via ``cmd_new`` / ``cmd_spawn`` / ``cmd_recreate``
155
- / ``cmd_fork`` / scheduler-spawn paths gets this so downstream tooling
156
- (notably the worker damage-control rules in ``safety/_core.py``)
157
- can identify which agentwire session the running tool is part of.
156
+ / ``cmd_fork`` / scheduler-spawn paths gets ``AGENTWIRE_SESSION_NAME`` so
157
+ downstream tooling (notably the worker damage-control rules in
158
+ ``safety/_core.py``) can identify which agentwire session the running
159
+ tool is part of.
160
+
161
+ ``created_by`` of ``''`` (root/orchestrator) or ``None`` means no
162
+ parent — ``AGENTWIRE_CREATED_BY`` is deliberately left UNSET rather than
163
+ set to an empty string, so the bare pre-agent shell's launch-crash guard
164
+ (``_guarded_launch_command``) can tell "has a parent to escalate to"
165
+ apart from "root session, email the owner" with a plain ``-n`` test (#743).
158
166
  """
159
167
  agent.env["AGENTWIRE_SESSION_NAME"] = session_name
168
+ if created_by:
169
+ agent.env["AGENTWIRE_CREATED_BY"] = created_by
160
170
 
161
171
 
162
172
  def inject_session_env(session: str, env: dict[str, str], remote_host: str | None = None) -> None:
@@ -730,6 +740,54 @@ def _record_session_creator(session_name: str, created_by: str | None, via: str)
730
740
  store_session_metadata(session_name, metadata)
731
741
 
732
742
 
743
+ def _record_session_role(session_name: str, role: str | None) -> None:
744
+ """Record the session's ROLE axis (orchestrator/worker) to disk (merge-preserving).
745
+
746
+ Distinct from the etiquette/persona ``roles:`` list in ``.agentwire.yml`` —
747
+ this is the fundamental authority axis derived at creation time (``kind``
748
+ in cmd_new, ``effective_kind`` in cmd_worktree, "worker" for cmd_spawn).
749
+ Read back by list_local_sessions() and the session_created notify lookup.
750
+ """
751
+ if not role:
752
+ return
753
+ metadata = load_session_metadata(session_name)
754
+ metadata["role"] = role
755
+ store_session_metadata(session_name, metadata)
756
+
757
+
758
+ def notify_portal_session_created(session_name: str, parent: str | None, role: str | None) -> None:
759
+ """Tell the portal a session was just created, with topology context (#747).
760
+
761
+ Fires immediately from the creating process instead of relying solely on
762
+ the global tmux ``session-created`` hook, which only knows the bare
763
+ session name (no parent/role) and can race a slow first-message delivery
764
+ before metadata is written. Fire-and-forget — failures are silently
765
+ ignored since the portal may not be running.
766
+ """
767
+ import ssl
768
+
769
+ payload: dict = {"event": "session_created", "session": session_name}
770
+ if parent:
771
+ payload["parent"] = parent
772
+ if role:
773
+ payload["role"] = role
774
+
775
+ try:
776
+ ctx = ssl.create_default_context()
777
+ ctx.check_hostname = False
778
+ ctx.verify_mode = ssl.CERT_NONE
779
+
780
+ req = urllib.request.Request(
781
+ f"{_default_portal_url()}/api/notify",
782
+ data=json.dumps(payload).encode(),
783
+ headers={"Content-Type": "application/json", **_portal_auth_headers()},
784
+ method="POST",
785
+ )
786
+ urllib.request.urlopen(req, timeout=3, context=ctx)
787
+ except Exception:
788
+ pass
789
+
790
+
733
791
  def _display_parent(session_name: str, path: str = "") -> "str | None":
734
792
  """The session that should visually own this one in the sidebar.
735
793
 
@@ -847,6 +905,52 @@ def _run_remote(machine_id: str, command: str) -> subprocess.CompletedProcess:
847
905
  )
848
906
 
849
907
 
908
+ def _guarded_launch_command(path_str: str, agent_cmd: str | None) -> str:
909
+ """Build the pane's ``cd <path> && <agent_cmd>`` line with a missing-dir guard (#739).
910
+
911
+ A crashed worktree create can leave ``path_str`` absent by the time the
912
+ pane actually runs its ``cd`` (race between ``agentwire new`` reporting
913
+ success and the async pane launch, or an external actor removing the
914
+ dir). Without a guard, ``cd`` fails, the shell prints an error and
915
+ carries on, and ``agent_cmd`` (e.g. ``claude``) then launches from the
916
+ WRONG cwd and crashes — dropping the pane to a bare shell that the
917
+ idle-reaper never touches (it only reaps a *running* agent going idle),
918
+ so it lingers forever.
919
+
920
+ On a missing dir this instead alerts and exits the shell, which tears the
921
+ tmux session down instead of leaving a zombie. ``agent_cmd`` never runs.
922
+
923
+ Two alert routes, both shell-runtime-gated on env vars stamped at launch
924
+ (``_set_session_name_env``), so this function stays a pure string builder
925
+ with no Python-level knowledge of the session's parent (#743):
926
+ - A real recorded parent (``$AGENTWIRE_CREATED_BY`` set) gets the crash
927
+ escalated to its msg inbox — in-band, not just an email the human has
928
+ to forward.
929
+ - No parent (root/orchestrator sessions, the genuine scheduler-dispatch
930
+ case) falls back to the original owner email, still gated on
931
+ ``$AGENTWIRE_UNATTENDED=1`` (see ``_with_unattended_env``).
932
+ """
933
+ quoted_path = shlex.quote(path_str)
934
+ session_ref = "${AGENTWIRE_SESSION_NAME:-unknown session}"
935
+ missing_body = f"cd failed at launch: {path_str}"
936
+ notify_parent = (
937
+ '[ -n "$AGENTWIRE_CREATED_BY" ] && agentwire msg send --to "$AGENTWIRE_CREATED_BY" '
938
+ f'--kind escalation --subject "agentwire: worktree missing at launch — {session_ref}" '
939
+ f'--body "{missing_body}" >/dev/null 2>&1'
940
+ )
941
+ notify_owner = (
942
+ '[ -z "$AGENTWIRE_CREATED_BY" ] && [ "$AGENTWIRE_UNATTENDED" = "1" ] && agentwire email '
943
+ f'--subject "agentwire: worktree missing — {session_ref}" '
944
+ f'--body "{missing_body}" >/dev/null 2>&1'
945
+ )
946
+ alert = (
947
+ f"echo \"agentwire: worktree missing at launch, aborting: {path_str}\" >&2; "
948
+ f"{notify_parent}; {notify_owner}"
949
+ )
950
+ guard = f"cd {quoted_path} || {{ {alert}; exit 1; }}"
951
+ return f"{guard} && {agent_cmd}" if agent_cmd else guard
952
+
953
+
850
954
  def _launch_tmux_session(
851
955
  session_name: str,
852
956
  session_path,
@@ -859,8 +963,9 @@ def _launch_tmux_session(
859
963
  The one launch sequence shared by ``new`` / ``recreate`` / ``fork`` (#630):
860
964
  `tmux new-session -e K=V` injects *env* into the session environment
861
965
  BEFORE the initial shell starts (post-hoc `set-environment` never reaches
862
- it), then `send-keys` cd's into place and, if *agent_cmd* is non-empty,
863
- starts the agent after a short settle.
966
+ it), then `send-keys` cd's into place (guarded see
967
+ ``_guarded_launch_command``) and, if *agent_cmd* is non-empty, starts the
968
+ agent after a short settle.
864
969
 
865
970
  Local (machine_id None): runs subprocess calls with check=True (raises on
866
971
  tmux failure) and returns None. Remote: runs one composite shell command
@@ -869,17 +974,14 @@ def _launch_tmux_session(
869
974
  import time
870
975
 
871
976
  path_str = str(session_path)
977
+ launch_cmd = _guarded_launch_command(path_str, agent_cmd)
872
978
  if machine_id:
873
979
  env_flags = _build_tmux_env_flags_shell(env)
874
980
  create_cmd = (
875
981
  f"tmux new-session -d -s {shlex.quote(session_name)} -c {shlex.quote(path_str)} {env_flags}&& "
876
- f"tmux send-keys -t {shlex.quote(session_name)} 'cd {shlex.quote(path_str)}' Enter"
982
+ f"sleep 0.1 && "
983
+ f"tmux send-keys -t {shlex.quote(session_name)} {shlex.quote(launch_cmd)} Enter"
877
984
  )
878
- if agent_cmd:
879
- create_cmd += (
880
- f" && sleep 0.1 && "
881
- f"tmux send-keys -t {shlex.quote(session_name)} {shlex.quote(agent_cmd)} Enter"
882
- )
883
985
  return _run_remote(machine_id, create_cmd)
884
986
 
885
987
  subprocess.run(
@@ -887,16 +989,11 @@ def _launch_tmux_session(
887
989
  *_build_tmux_env_flags(env)],
888
990
  check=True,
889
991
  )
992
+ time.sleep(0.1)
890
993
  subprocess.run(
891
- ["tmux", "send-keys", "-t", session_name, f"cd {shlex.quote(path_str)}", "Enter"],
994
+ ["tmux", "send-keys", "-t", session_name, launch_cmd, "Enter"],
892
995
  check=True,
893
996
  )
894
- time.sleep(0.1)
895
- if agent_cmd:
896
- subprocess.run(
897
- ["tmux", "send-keys", "-t", session_name, agent_cmd, "Enter"],
898
- check=True,
899
- )
900
997
  return None
901
998
 
902
999
 
@@ -1008,6 +1008,30 @@ def cmd_doctor(args) -> int:
1008
1008
  except Exception as e:
1009
1009
  print(f" [..] Could not check managed voice shim liveness: {e}")
1010
1010
 
1011
+ # 14. Zombie scheduler sessions (#739): a worktree dispatch whose launch
1012
+ # crashed before the agent started (e.g. the worktree dir went missing
1013
+ # between `agentwire new` reporting success and the pane's `cd`) drops to
1014
+ # a bare shell the idle-reaper never touches. `agentwire limits tick`
1015
+ # self-heals these every minute, so a live one here means the watchdog
1016
+ # isn't installed/running, not that reaping is broken.
1017
+ print("\nChecking for zombie scheduler sessions (#739)...")
1018
+ try:
1019
+ from .scheduler import scan_zombie_sessions
1020
+
1021
+ zombie_sessions = scan_zombie_sessions()
1022
+ if not zombie_sessions:
1023
+ print(" [ok] No zombie scheduler sessions found")
1024
+ else:
1025
+ issues_found += 1
1026
+ print(f" [!!] {len(zombie_sessions)} scheduler session(s) stuck at a bare shell:")
1027
+ for z in zombie_sessions:
1028
+ print(f" - {z['session']} ({z['command']}, {z['age_seconds']}s old)")
1029
+ print(" `agentwire limits tick` reaps these automatically — "
1030
+ "run it now, or check the usage-limit watchdog is installed "
1031
+ "(`agentwire limits install`).")
1032
+ except Exception as e:
1033
+ print(f" [..] Could not check for zombie scheduler sessions: {e}")
1034
+
1011
1035
  # Summary
1012
1036
  print()
1013
1037
  print("-" * 60)
@@ -177,16 +177,20 @@ def cmd_limits_tick(args) -> int:
177
177
  """One watchdog pass (called by launchd every minute).
178
178
 
179
179
  Runs the usage-limit sweep FIRST, then prompt routing (#276), then the
180
- polite-message inbox drain (#296), then context auto-management (#442)
181
- the ordering guarantees a usage-limit dialog is parked before any sweep
182
- looks at the pane, that the inbox only ever delivers to panes the prompt
183
- sweep already cleared, and that auto-``/clear`` runs LAST so it never fights
184
- a pending paste/prompt for the same idle, empty box.
180
+ polite-message inbox drain (#296), then context auto-management (#442),
181
+ then the zombie-scheduler-session reap (#739) the ordering guarantees a
182
+ usage-limit dialog is parked before any sweep looks at the pane, that the
183
+ inbox only ever delivers to panes the prompt sweep already cleared, that
184
+ auto-``/clear`` runs before the reap so it never fights a pending
185
+ paste/prompt for the same idle, empty box, and that the reap runs LAST
186
+ since it kills sessions outright (nothing later should still be acting on
187
+ one).
185
188
 
186
189
  Each stage runs inside :func:`_run_stage` so an exception in one subsystem
187
190
  is logged and skipped rather than aborting the whole cycle (#490).
188
191
  """
189
192
  from agentwire import inbox, prompt_router, session_context
193
+ from agentwire.scheduler import zombie as scheduler_zombie
190
194
 
191
195
  result = _run_stage(
192
196
  "usage_limit", usage_limit.tick,
@@ -197,9 +201,12 @@ def cmd_limits_tick(args) -> int:
197
201
  "inbox", inbox.tick, {"flushed": [], "deferred": []})
198
202
  context = _run_stage(
199
203
  "session_context", session_context.tick, {"acted": [], "deferred": []})
204
+ zombies = _run_stage(
205
+ "scheduler_zombie", scheduler_zombie.tick, {"killed": []})
200
206
  if getattr(args, "json", False):
201
207
  print(json.dumps({
202
- **result, "prompts": prompts, "messages": messages, "context": context,
208
+ **result, "prompts": prompts, "messages": messages,
209
+ "context": context, "zombies": zombies,
203
210
  }))
204
211
  return 0
205
212
  if result.get("skipped"):
@@ -237,6 +244,9 @@ def cmd_limits_tick(args) -> int:
237
244
  if ctx_deferred:
238
245
  print("context deferred: " + ", ".join(
239
246
  f"{e['session']}({e['deferred']})" for e in ctx_deferred))
247
+ killed = zombies.get("killed") or []
248
+ if killed:
249
+ print("zombie scheduler sessions reaped: " + ", ".join(killed))
240
250
  return 0
241
251
 
242
252
 
@@ -225,6 +225,7 @@ def worktree_remove(
225
225
  project_dir: str = "",
226
226
  keep_branch: bool = False,
227
227
  force_delete_branch: bool = False,
228
+ close_pr_branch: bool = False,
228
229
  ) -> str:
229
230
  """Tear down a worktree session: kill the session, remove the worktree + branch, unregister.
230
231
 
@@ -245,7 +246,12 @@ def worktree_remove(
245
246
  project_dir: Path to the git repo (default: server cwd).
246
247
  keep_branch: Skip branch cleanup entirely (leave the branch as-is).
247
248
  force_delete_branch: Delete the branch even if not confirmed merged —
248
- use only when you're sure the work is safe to discard.
249
+ use only when you're sure the work is safe to discard. Still
250
+ refuses a branch with an OPEN PR (deleting it would silently
251
+ close the PR) unless close_pr_branch is also set.
252
+ close_pr_branch: Combined with force_delete_branch, also delete a
253
+ branch that has an OPEN PR, closing it. Explicit escape hatch —
254
+ only set this when you mean to close that PR.
249
255
 
250
256
  Returns:
251
257
  Success message describing what was removed, or a loud failure
@@ -258,6 +264,8 @@ def worktree_remove(
258
264
  args += ["--keep-branch"]
259
265
  if force_delete_branch:
260
266
  args += ["--force-delete-branch"]
267
+ if close_pr_branch:
268
+ args += ["--close-pr-branch"]
261
269
  data = run_agentwire_cmd(args)
262
270
  session = data.get("session", name)
263
271
  killed = " (killed live session)" if data.get("killed") else ""
@@ -37,6 +37,7 @@ from .core import (
37
37
  build_agent_command,
38
38
  inject_session_env,
39
39
  load_config,
40
+ load_session_metadata,
40
41
  parse_env_args,
41
42
  tmux_session_exists,
42
43
  )
@@ -172,6 +173,7 @@ def list_local_sessions(show_context: bool = False) -> list[dict]:
172
173
  "posture": cfg.get("posture"),
173
174
  "roles": cfg.get("roles", []),
174
175
  "parent": _display_parent(parts[0], path),
176
+ "role": load_session_metadata(parts[0]).get("role"),
175
177
  }
176
178
  if usage_limit_parked(parts[0]):
177
179
  session_info["usage_limit"] = True
@@ -66,9 +66,20 @@ class NotifyRoutesMixin:
66
66
  await self.broadcast_dashboard("sessions_update", {"sessions": sessions_data})
67
67
 
68
68
  elif event == "session_created":
69
+ # #747: name/parent/role travel in the payload when the
70
+ # creating process (cmd_new et al.) posts this explicitly —
71
+ # that's authoritative, no race. The bare global tmux hook
72
+ # (session-created, any tmux session) carries only the name,
73
+ # so fall back to a fresh lookup for that case (metadata may
74
+ # not be written yet on a very fast reattach — best-effort).
69
75
  self._invalidate_session_caches()
70
- await self.broadcast_dashboard("session_created", {"session": session})
71
76
  sessions_data = await self._get_sessions_data()
77
+ entry = next((s for s in sessions_data if s.get("name") == session), None)
78
+ parent = data.get("parent") or (entry.get("parent") if entry else None)
79
+ role = data.get("role") or (entry.get("role") if entry else None)
80
+ await self.broadcast_dashboard("session_created", {
81
+ "session": session, "name": session, "parent": parent, "role": role,
82
+ })
72
83
  await self.broadcast_dashboard("sessions_update", {"sessions": sessions_data})
73
84
 
74
85
  elif event == "pane_died":
@@ -379,6 +379,66 @@ class ProjectsRoutesMixin:
379
379
 
380
380
  return web.json_response({"existing": result.get("existing", [])})
381
381
 
382
+ async def api_worktree_cleanup(self, request: web.Request) -> web.Response:
383
+ """Tear down an orphaned worktree (Session HUD ghost card "Clean up").
384
+
385
+ Thin wrapper over the plain `agentwire worktree --remove` form — the
386
+ CLI's own merge/open-PR guard decides whether the branch is also
387
+ deleted; this never escalates to --force-delete-branch.
388
+
389
+ Body: {"name": "<branch or session>", "project": "/path/to/repo"}
390
+ Returns whatever the CLI returns verbatim: on success
391
+ {success, session, path, killed, worktree_removed, branch,
392
+ branch_deleted, branch_note, orphaned_tabs}; on failure
393
+ {success: false, error}.
394
+ """
395
+ try:
396
+ data = await request.json()
397
+ except Exception:
398
+ return web.json_response({"success": False, "error": "Invalid JSON body"}, status=400)
399
+
400
+ name = (data.get("name") or "").strip()
401
+ project = (data.get("project") or "").strip()
402
+ if not name or not project:
403
+ return web.json_response({"success": False, "error": "name and project are required"}, status=400)
404
+
405
+ # Thin wrapper: the git/registry/branch-safety logic lives in the CLI (SSOT).
406
+ success, result = await self.run_agentwire_cmd(
407
+ ["worktree", "--remove", name, "-p", project]
408
+ )
409
+ return web.json_response(result, status=200 if success else 400)
410
+
411
+ async def api_worktree_adopt(self, request: web.Request) -> web.Response:
412
+ """Spawn a session into an existing worktree (Session HUD ghost card "Adopt").
413
+
414
+ Thin wrapper over `agentwire worktree <name> -p <project> --existing
415
+ [--created-by <createdBy>]` — checks out the branch already on disk
416
+ (no new branch) and, when the dead session's recorded creator is
417
+ known, roots the new session under that same parent so it reports
418
+ back the way the original session would have.
419
+
420
+ Body: {"name": "<branch>", "project": "/path/to/repo", "createdBy": "<session>"}
421
+ Returns whatever the CLI returns verbatim (same shape as `agentwire new`'s
422
+ json — success/session/path/... — or {success: false, error}).
423
+ """
424
+ try:
425
+ data = await request.json()
426
+ except Exception:
427
+ return web.json_response({"success": False, "error": "Invalid JSON body"}, status=400)
428
+
429
+ name = (data.get("name") or "").strip()
430
+ project = (data.get("project") or "").strip()
431
+ created_by = (data.get("createdBy") or "").strip()
432
+ if not name or not project:
433
+ return web.json_response({"success": False, "error": "name and project are required"}, status=400)
434
+
435
+ args = ["worktree", name, "-p", project, "--existing"]
436
+ if created_by:
437
+ args += ["--created-by", created_by]
438
+
439
+ success, result = await self.run_agentwire_cmd(args)
440
+ return web.json_response(result, status=200 if success else 400)
441
+
382
442
 
383
443
  def register_projects_routes(server, app):
384
444
  """Wire the projects domain's routes onto ``app``."""
@@ -389,3 +449,5 @@ def register_projects_routes(server, app):
389
449
  app.router.add_get("/api/session/defaults", server.api_session_defaults)
390
450
  app.router.add_get("/api/check-path", server.api_check_path)
391
451
  app.router.add_get("/api/check-branches", server.api_check_branches)
452
+ app.router.add_post("/api/worktree/cleanup", server.api_worktree_cleanup)
453
+ app.router.add_post("/api/worktree/adopt", server.api_worktree_adopt)
@@ -183,10 +183,10 @@ class SessionsAdminRoutesMixin:
183
183
  yaml_config["voice"] = voice
184
184
  await self._write_agentwire_yaml(session_path, yaml_config, machine_id)
185
185
 
186
- # Broadcast session created to dashboard clients
187
- await self.broadcast_dashboard("session_created", {"session": session_name})
188
- sessions_data = await self._get_sessions_data()
189
- await self.broadcast_dashboard("sessions_update", {"sessions": sessions_data})
186
+ # No manual broadcast here (#747): the `agentwire new` subprocess
187
+ # just awaited above already posted the enriched session_created
188
+ # (name/parent/role) + sessions_update to this same portal from
189
+ # inside cmd_new, before returning.
190
190
 
191
191
  # Wait until the tmux pane has actually rendered something. The CLI
192
192
  # returns the moment `tmux send-keys` *queues* the agent command, so
@@ -24,6 +24,7 @@ from datetime import datetime, timezone
24
24
  import yaml
25
25
 
26
26
  from ..core import _atomic_write
27
+ from . import zombie
27
28
  from .dispatch import (
28
29
  _WORKFLOW_STATUS_TO_SCHED,
29
30
  _apply_max_runs,
@@ -110,3 +111,6 @@ from .state import (
110
111
  load_board,
111
112
  save_board,
112
113
  )
114
+ from .zombie import reap as reap_zombie_sessions
115
+ from .zombie import scan as scan_zombie_sessions
116
+ from .zombie import tick as zombie_tick
@@ -0,0 +1,160 @@
1
+ """Reap bare-shell scheduler sessions (#739).
2
+
3
+ ``_dispatch_worktree_task`` names every worktree branch
4
+ ``scheduler-<task>-<ts>``. If the session's launch crashes before the agent
5
+ starts (e.g. the worktree directory went missing between ``agentwire new``
6
+ reporting success and the pane's ``cd``), the tmux session drops to a bare
7
+ shell — which the idle-reaper correctly never touches, since it only reaps a
8
+ *running* agent that goes idle. Nothing else would ever clean that up, so it
9
+ lingers indefinitely. This module finds and kills those sessions.
10
+
11
+ Detected by branch naming rather than ``worktree_registry`` — scheduler
12
+ dispatch goes through ``agentwire new``, which (unlike ``agentwire
13
+ worktree``) never registers there.
14
+ """
15
+
16
+ import subprocess
17
+ import time
18
+
19
+ from ..worktree import parse_session_name
20
+
21
+ BRANCH_PREFIX = "scheduler-"
22
+
23
+ # tmux `session_created` is whole seconds. A healthy launch's pre-agent shell
24
+ # moment lasts well under a second (see `_launch_tmux_session`'s 0.1s
25
+ # settle), but this gives a slow `claude` cold start real headroom before a
26
+ # session still mid-launch could be mistaken for a zombie.
27
+ MIN_AGE_SECONDS = 60
28
+
29
+ _SHELL_COMMANDS = frozenset({"zsh", "bash", "sh", "fish", "tcsh", "csh", "dash"})
30
+
31
+
32
+ def _is_bare_shell(command: str) -> bool:
33
+ """True if *command* (a ``pane_current_command`` value) is a login shell."""
34
+ return command.strip().lstrip("-") in _SHELL_COMMANDS
35
+
36
+
37
+ def scan() -> list[dict]:
38
+ """Live scheduler-dispatched worktree sessions stuck at a bare shell.
39
+
40
+ Each entry: ``session``, ``branch``, ``command``, ``age_seconds``.
41
+ """
42
+ result = subprocess.run(
43
+ ["tmux", "list-sessions", "-F", "#{session_name}\t#{session_created}"],
44
+ capture_output=True, text=True,
45
+ )
46
+ if result.returncode != 0:
47
+ return []
48
+
49
+ now = time.time()
50
+ zombies = []
51
+ for line in result.stdout.strip().splitlines():
52
+ if "\t" not in line:
53
+ continue
54
+ session, created = line.split("\t", 1)
55
+ _, branch, machine = parse_session_name(session)
56
+ if machine or not branch or not branch.startswith(BRANCH_PREFIX):
57
+ continue
58
+ try:
59
+ age = now - float(created)
60
+ except ValueError:
61
+ continue
62
+ if age < MIN_AGE_SECONDS:
63
+ continue
64
+
65
+ panes = subprocess.run(
66
+ ["tmux", "list-panes", "-t", f"={session}", "-F", "#{pane_current_command}"],
67
+ capture_output=True, text=True,
68
+ )
69
+ if panes.returncode != 0:
70
+ continue
71
+ commands = [p for p in panes.stdout.strip().splitlines() if p]
72
+ if len(commands) == 1 and _is_bare_shell(commands[0]):
73
+ zombies.append({
74
+ "session": session, "branch": branch,
75
+ "command": commands[0], "age_seconds": int(age),
76
+ })
77
+ return zombies
78
+
79
+
80
+ def _notify(session: str, branch: str, command: str) -> None:
81
+ """Alert on a reaped zombie session (#739 + #743).
82
+
83
+ Always posts a portal toast, so the reap is visible in-band rather than
84
+ only in an email the human has to notice and forward. When the session
85
+ has a recorded parent (``created_by`` in its metadata — set at
86
+ ``agentwire new`` time, see ``_record_session_creator``), the crash is
87
+ ALSO escalated there via the msg inbox (drained by the same watchdog that
88
+ runs this reap) — a worktree worker's crash reaches its orchestrator, not
89
+ just the owner's inbox. Owner email — the reused Resend wiring, mirrors
90
+ ``dispatch._notify_dispatch_timeout`` — is strictly the fallback for a
91
+ session with no recorded parent (the genuine root/scheduler-dispatch
92
+ case #739 originally covered). Each channel is independently
93
+ best-effort; this must never raise into the caller.
94
+ """
95
+ text = (
96
+ f"agentwire: reaped zombie scheduler session `{session}` (branch "
97
+ f"`{branch}`) — launch crashed at a bare shell (`{command}`) before "
98
+ "the agent started."
99
+ )
100
+
101
+ try:
102
+ from ..core import _post_desktop_notification
103
+ _post_desktop_notification(text, session=session, priority="high")
104
+ except Exception:
105
+ pass
106
+
107
+ parent = None
108
+ try:
109
+ from ..core import load_session_metadata
110
+ parent = load_session_metadata(session).get("created_by") or None
111
+ except Exception:
112
+ parent = None
113
+
114
+ if parent:
115
+ try:
116
+ from ..inbox import enqueue
117
+ enqueue(parent, text, kind="escalation", sender="agentwire")
118
+ except Exception:
119
+ pass
120
+ return
121
+
122
+ try:
123
+ import socket
124
+
125
+ from ..channels.email import send_email
126
+ send_email(
127
+ subject=f"[agentwire] reaped zombie scheduler session: {session}",
128
+ body=(
129
+ f"Scheduler dispatch session `{session}` (branch `{branch}`) "
130
+ f"on `{socket.gethostname()}` never reached its agent — the "
131
+ f"pane was stuck at a bare shell (`{command}`), the #739 "
132
+ "failure mode where the worktree launch crashes before "
133
+ "`claude` starts (e.g. a missing worktree directory). The "
134
+ "watchdog killed the session so it can't linger.\n\n"
135
+ "Check the scheduler events log for the originating "
136
+ "dispatch failure."
137
+ ),
138
+ )
139
+ except Exception:
140
+ pass
141
+
142
+
143
+ def reap() -> dict:
144
+ """Kill every detected zombie session, logging + emailing each one."""
145
+ from agentwire import scheduler as _sched
146
+
147
+ killed = []
148
+ for z in scan():
149
+ _sched._kill_session(z["session"])
150
+ _sched._log_event("zombie_session_reaped", session=z["session"],
151
+ branch=z["branch"], command=z["command"],
152
+ age_seconds=z["age_seconds"])
153
+ _notify(z["session"], z["branch"], z["command"])
154
+ killed.append(z["session"])
155
+ return {"killed": killed}
156
+
157
+
158
+ def tick() -> dict:
159
+ """Watchdog stage entry point — same ``{"killed": [...]}`` shape as ``reap()``."""
160
+ return reap()