agentwire-dev 1.65.2__tar.gz → 1.66.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 (522) hide show
  1. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/PKG-INFO +1 -1
  2. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/__init__.py +1 -1
  3. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/__main__.py +3 -1
  4. agentwire_dev-1.66.0/agentwire/cohort.py +505 -0
  5. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/core.py +42 -8
  6. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/doctor_cli.py +57 -0
  7. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/ensure_cli.py +75 -2
  8. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/hooks/idle-handler.sh +21 -0
  9. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/inbox.py +39 -0
  10. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/limits_cli.py +18 -9
  11. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/mcp_core.py +28 -0
  12. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/mcp_session.py +61 -0
  13. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/mcp_worktree.py +27 -4
  14. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/pane_cli.py +38 -14
  15. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/pane_manager.py +31 -41
  16. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/project_config.py +67 -8
  17. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/roles/reviewer-worktree.md +2 -0
  18. agentwire_dev-1.66.0/agentwire/roles/shared-checkout.md +60 -0
  19. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/roles/worker-worktree.md +6 -5
  20. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/scheduler/dispatch.py +35 -11
  21. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/scheduler/zombie.py +38 -7
  22. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/send_cli.py +179 -13
  23. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/server.py +44 -3
  24. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/session_cli.py +489 -134
  25. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/session_ready.py +283 -39
  26. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/tasks.py +9 -0
  27. agentwire_dev-1.66.0/agentwire/templates/statusline.sh +121 -0
  28. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/templates/tmux.conf +5 -3
  29. agentwire_dev-1.66.0/agentwire/wait_cli.py +86 -0
  30. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/worktree.py +284 -7
  31. agentwire_dev-1.66.0/agentwire/worktree_cli.py +152 -0
  32. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/worktree_registry.py +29 -4
  33. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/docs/wiki/INDEX.md +3 -1
  34. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/docs/wiki/internals/shell-escaping.md +64 -2
  35. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/docs/wiki/quickstart.md +17 -0
  36. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/docs/wiki/scheduling/scheduled-workloads.md +25 -0
  37. agentwire_dev-1.66.0/docs/wiki/sessions/fan-out-cohorts.md +182 -0
  38. agentwire_dev-1.66.0/docs/wiki/sessions/helper-sessions.md +103 -0
  39. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/docs/wiki/sessions/messaging.md +36 -1
  40. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/docs/wiki/sessions/worktree-sessions.md +20 -2
  41. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/pyproject.toml +1 -0
  42. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/tests/conftest.py +15 -0
  43. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/tests/integration/test_send_verified_tmux.py +194 -5
  44. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/tests/integration/test_worktree_cmd.py +351 -0
  45. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/tests/unit/test_cli_commands.py +513 -26
  46. agentwire_dev-1.66.0/tests/unit/test_cohort.py +345 -0
  47. agentwire_dev-1.66.0/tests/unit/test_ensure_shared_dir.py +135 -0
  48. agentwire_dev-1.66.0/tests/unit/test_helper_session.py +225 -0
  49. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/tests/unit/test_idle_handler.py +79 -0
  50. agentwire_dev-1.66.0/tests/unit/test_launch_via_env.py +106 -0
  51. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/tests/unit/test_mcp_server.py +62 -0
  52. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/tests/unit/test_mcp_tools_args.py +19 -0
  53. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/tests/unit/test_portal_api.py +92 -0
  54. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/tests/unit/test_project_config.py +99 -0
  55. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/tests/unit/test_prompt_router.py +15 -2
  56. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/tests/unit/test_scheduler.py +2 -2
  57. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/tests/unit/test_scheduler_zombie.py +73 -1
  58. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/tests/unit/test_session_ready.py +488 -42
  59. agentwire_dev-1.66.0/tests/unit/test_worktree_dot_project.py +84 -0
  60. agentwire_dev-1.66.0/tests/unit/test_worktree_git_truth.py +314 -0
  61. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/tests/unit/test_worktree_layout.py +29 -12
  62. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/.agentwire.yml.example +0 -0
  63. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/.claude/commands/handoff.md +0 -0
  64. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/.claude/skills/wiki/SKILL.md +0 -0
  65. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/.github/FUNDING.yml +0 -0
  66. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
  67. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
  68. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/.github/ISSUE_TEMPLATE/question.md +0 -0
  69. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
  70. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/.github/workflows/pytest.yml +0 -0
  71. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/.github/workflows/ruff.yml +0 -0
  72. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/.github/workflows/security.yml +0 -0
  73. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/.github/workflows/tts-smoke.yml +0 -0
  74. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/.gitignore +0 -0
  75. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/AGENTS.md +0 -0
  76. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/CODE_OF_CONDUCT.md +0 -0
  77. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/CONTRIBUTING.md +0 -0
  78. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/Dockerfile.local +0 -0
  79. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/LICENSE +0 -0
  80. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/README.md +0 -0
  81. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/RELEASING.md +0 -0
  82. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/SECURITY.md +0 -0
  83. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/SPONSORS.md +0 -0
  84. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/agents/__init__.py +0 -0
  85. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/agents/base.py +0 -0
  86. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/agents/tmux.py +0 -0
  87. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/cached_status.py +0 -0
  88. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/channels/__init__.py +0 -0
  89. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/channels/base.py +0 -0
  90. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/channels/email.py +0 -0
  91. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/channels/push.py +0 -0
  92. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/channels/quo.py +0 -0
  93. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/channels_cli.py +0 -0
  94. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/chrome_tabs.py +0 -0
  95. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/completion.py +0 -0
  96. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/config.py +0 -0
  97. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/config_cli.py +0 -0
  98. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/council/__init__.py +0 -0
  99. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/council/cli.py +0 -0
  100. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/council/inbox.py +0 -0
  101. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/council/minutes.py +0 -0
  102. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/council/state.py +0 -0
  103. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/council/view.py +0 -0
  104. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/devices.py +0 -0
  105. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/diff_cli.py +0 -0
  106. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/doctor_voice.py +0 -0
  107. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/fetch.py +0 -0
  108. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/handoff/__init__.py +0 -0
  109. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/handoff/git_state.py +0 -0
  110. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/handoff/instructions.py +0 -0
  111. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/handoff/parser.py +0 -0
  112. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/handoff/renderer.py +0 -0
  113. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/handoff/schema.py +0 -0
  114. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/handoff_cli.py +0 -0
  115. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/history.py +0 -0
  116. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/history_cli.py +0 -0
  117. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/hooks/__init__.py +0 -0
  118. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/hooks/agentwire-permission.sh +0 -0
  119. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/hooks/damage-control/__init__.py +0 -0
  120. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/hooks/damage-control/audit_logger.py +0 -0
  121. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/hooks/damage-control/bash-tool-damage-control.py +0 -0
  122. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/hooks/damage-control/edit-tool-damage-control.py +0 -0
  123. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/hooks/damage-control/mcp-tool-damage-control.py +0 -0
  124. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/hooks/damage-control/read-tool-damage-control.py +0 -0
  125. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/hooks/damage-control/rules/agentwire.yaml +0 -0
  126. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/hooks/damage-control/rules/aws.yaml +0 -0
  127. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/hooks/damage-control/rules/cloud-hosting.yaml +0 -0
  128. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/hooks/damage-control/rules/containers.yaml +0 -0
  129. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/hooks/damage-control/rules/control-plane.yaml +0 -0
  130. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/hooks/damage-control/rules/core.yaml +0 -0
  131. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/hooks/damage-control/rules/databases.yaml +0 -0
  132. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/hooks/damage-control/rules/firebase.yaml +0 -0
  133. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/hooks/damage-control/rules/gcp.yaml +0 -0
  134. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/hooks/damage-control/rules/git.yaml +0 -0
  135. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/hooks/damage-control/rules/gws.yaml +0 -0
  136. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/hooks/damage-control/rules/infrastructure.yaml +0 -0
  137. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/hooks/damage-control/rules/outbound.yaml +0 -0
  138. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/hooks/damage-control/rules/publish.yaml +0 -0
  139. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/hooks/damage-control/rules/remote.yaml +0 -0
  140. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/hooks/damage-control/write-tool-damage-control.py +0 -0
  141. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/hooks/queue-processor.sh +0 -0
  142. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/hooks_cli.py +0 -0
  143. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/listen.py +0 -0
  144. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/locking.py +0 -0
  145. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/machine_cli.py +0 -0
  146. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/mcp_channels.py +0 -0
  147. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/mcp_chrome.py +0 -0
  148. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/mcp_cli.py +0 -0
  149. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/mcp_council.py +0 -0
  150. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/mcp_desktop.py +0 -0
  151. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/mcp_handoff.py +0 -0
  152. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/mcp_history.py +0 -0
  153. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/mcp_listen.py +0 -0
  154. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/mcp_lock.py +0 -0
  155. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/mcp_machine.py +0 -0
  156. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/mcp_msg.py +0 -0
  157. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/mcp_notify.py +0 -0
  158. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/mcp_pane.py +0 -0
  159. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/mcp_projects.py +0 -0
  160. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/mcp_scheduler.py +0 -0
  161. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/mcp_scratchpad.py +0 -0
  162. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/mcp_server.py +0 -0
  163. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/mcp_services.py +0 -0
  164. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/mcp_status.py +0 -0
  165. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/mcp_task.py +0 -0
  166. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/mcp_tunnels.py +0 -0
  167. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/mcp_voice.py +0 -0
  168. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/mcp_wiki.py +0 -0
  169. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/msg_cli.py +0 -0
  170. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/network.py +0 -0
  171. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/notify_cli.py +0 -0
  172. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/onboarding.py +0 -0
  173. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/palette_cli.py +0 -0
  174. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/portal_cli.py +0 -0
  175. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/projects.py +0 -0
  176. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/prompt_router.py +0 -0
  177. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/prompts_cli.py +0 -0
  178. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/push_cli.py +0 -0
  179. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/push_store.py +0 -0
  180. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/repo_cli.py +0 -0
  181. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/research.py +0 -0
  182. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/roles/__init__.py +0 -0
  183. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/roles/agentwire.md +0 -0
  184. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/roles/anchor.md +0 -0
  185. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/roles/chatbot.md +0 -0
  186. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/roles/contributor.md +0 -0
  187. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/roles/correspondent.md +0 -0
  188. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/roles/council-brain.md +0 -0
  189. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/roles/council-conscience.md +0 -0
  190. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/roles/council-critic.md +0 -0
  191. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/roles/council-devils-advocate.md +0 -0
  192. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/roles/council-gut.md +0 -0
  193. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/roles/council-historian.md +0 -0
  194. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/roles/council-member.md +0 -0
  195. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/roles/council-orchestrator.md +0 -0
  196. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/roles/init.md +0 -0
  197. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/roles/notifications.md +0 -0
  198. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/roles/orchestrator.md +0 -0
  199. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/roles/reviewer.md +0 -0
  200. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/roles/soul.md +0 -0
  201. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/roles/task-runner.md +0 -0
  202. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/roles/voice.md +0 -0
  203. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/roles/worker.md +0 -0
  204. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/roles_cli.py +0 -0
  205. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/routes/__init__.py +0 -0
  206. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/routes/artifacts.py +0 -0
  207. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/routes/config.py +0 -0
  208. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/routes/council.py +0 -0
  209. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/routes/desktop.py +0 -0
  210. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/routes/history.py +0 -0
  211. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/routes/machines.py +0 -0
  212. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/routes/notify.py +0 -0
  213. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/routes/palette.py +0 -0
  214. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/routes/permission.py +0 -0
  215. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/routes/projects.py +0 -0
  216. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/routes/push.py +0 -0
  217. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/routes/safety.py +0 -0
  218. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/routes/scheduler.py +0 -0
  219. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/routes/scratchpad.py +0 -0
  220. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/routes/sessions.py +0 -0
  221. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/routes/sessions_admin.py +0 -0
  222. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/routes/voice.py +0 -0
  223. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/safety/__init__.py +0 -0
  224. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/safety/_core.py +0 -0
  225. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/safety_cli.py +0 -0
  226. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/safety_commands.py +0 -0
  227. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/scheduler/__init__.py +0 -0
  228. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/scheduler/gates.py +0 -0
  229. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/scheduler/loop.py +0 -0
  230. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/scheduler/models.py +0 -0
  231. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/scheduler/report.py +0 -0
  232. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/scheduler/schedule.py +0 -0
  233. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/scheduler/state.py +0 -0
  234. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/scheduler_cli.py +0 -0
  235. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/scratchpad.py +0 -0
  236. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/security.py +0 -0
  237. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/services.py +0 -0
  238. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/session_context.py +0 -0
  239. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/ssh.py +0 -0
  240. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/static/agentwire-splash-logo-layers--agentwire-text.png +0 -0
  241. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/static/agentwire-splash-logo-layers--echo-claw-fg.png +0 -0
  242. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/static/agentwire-splash-logo-layers--echo.png +0 -0
  243. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/static/agentwire-splash-logo-layers--telephone.png +0 -0
  244. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/static/agentwire-splash-logo-layers--tree.png +0 -0
  245. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/static/announcements.json +0 -0
  246. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/static/apple-touch-icon.png +0 -0
  247. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/static/css/desktop.css +0 -0
  248. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/static/css/mobile.css +0 -0
  249. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/static/favicon-32.png +0 -0
  250. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/static/favicon-64.png +0 -0
  251. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/static/icons/sessions/bear.webp +0 -0
  252. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/static/icons/sessions/cat.webp +0 -0
  253. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/static/icons/sessions/crown.webp +0 -0
  254. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/static/icons/sessions/custom/agentwire-portal.webp +0 -0
  255. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/static/icons/sessions/custom/agentwire-tts.webp +0 -0
  256. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/static/icons/sessions/custom/agentwire.webp +0 -0
  257. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/static/icons/sessions/deer.webp +0 -0
  258. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/static/icons/sessions/drone.webp +0 -0
  259. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/static/icons/sessions/eagle.webp +0 -0
  260. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/static/icons/sessions/fox.webp +0 -0
  261. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/static/icons/sessions/hawk.webp +0 -0
  262. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/static/icons/sessions/horse.webp +0 -0
  263. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/static/icons/sessions/lion.webp +0 -0
  264. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/static/icons/sessions/rabbit.webp +0 -0
  265. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/static/icons/sessions/robot.webp +0 -0
  266. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/static/icons/sessions/tiger.webp +0 -0
  267. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/static/icons/sessions/wolf.webp +0 -0
  268. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/static/img/icon-192.png +0 -0
  269. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/static/img/icon-512.png +0 -0
  270. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/static/js/.gitkeep +0 -0
  271. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/static/js/announcement-modal.js +0 -0
  272. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/static/js/api.js +0 -0
  273. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/static/js/artifact-window.js +0 -0
  274. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/static/js/card-terminal.js +0 -0
  275. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/static/js/collage.js +0 -0
  276. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/static/js/command-palette.js +0 -0
  277. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/static/js/council-window.js +0 -0
  278. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/static/js/dead-key-suppressor.js +0 -0
  279. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/static/js/desktop-manager.js +0 -0
  280. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/static/js/desktop.js +0 -0
  281. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/static/js/help-modal.js +0 -0
  282. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/static/js/icon-manager.js +0 -0
  283. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/static/js/lineage.js +0 -0
  284. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/static/js/mobile.js +0 -0
  285. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/static/js/notification-prefs.js +0 -0
  286. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/static/js/notifications-panel.js +0 -0
  287. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/static/js/ptt.js +0 -0
  288. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/static/js/push-client.js +0 -0
  289. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/static/js/review-window.js +0 -0
  290. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/static/js/safety-shared.js +0 -0
  291. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/static/js/safety-window.js +0 -0
  292. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/static/js/scratchpad.js +0 -0
  293. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/static/js/service-classification.js +0 -0
  294. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/static/js/session-hud-controller.js +0 -0
  295. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/static/js/session-hud-notices.js +0 -0
  296. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/static/js/session-hud-spawn.js +0 -0
  297. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/static/js/session-hud.js +0 -0
  298. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/static/js/session-id.js +0 -0
  299. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/static/js/session-window.js +0 -0
  300. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/static/js/shortcuts.js +0 -0
  301. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/static/js/sidebar/artifacts-section.js +0 -0
  302. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/static/js/sidebar/config-section.js +0 -0
  303. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/static/js/sidebar/council-section.js +0 -0
  304. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/static/js/sidebar/machines-section.js +0 -0
  305. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/static/js/sidebar/projects-section.js +0 -0
  306. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/static/js/sidebar/safety-section.js +0 -0
  307. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/static/js/sidebar/scheduler-section.js +0 -0
  308. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/static/js/sidebar/services-section.js +0 -0
  309. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/static/js/sidebar/sessions-section.js +0 -0
  310. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/static/js/sidebar.js +0 -0
  311. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/static/js/spawn-ghost.js +0 -0
  312. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/static/js/terminal-font-prefs.js +0 -0
  313. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/static/js/terminal-pane.js +0 -0
  314. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/static/js/tile-manager.js +0 -0
  315. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/static/js/toast.js +0 -0
  316. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/static/js/token-modal.js +0 -0
  317. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/static/js/topology-render.js +0 -0
  318. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/static/js/utils/ansi.js +0 -0
  319. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/static/js/utils/rich-text.js +0 -0
  320. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/static/js/utils/swipe.js +0 -0
  321. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/static/js/voice/autosend-prefs.js +0 -0
  322. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/static/js/voice/browser-stt.js +0 -0
  323. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/static/js/voice/browser-tts.js +0 -0
  324. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/static/js/voice/jargon.js +0 -0
  325. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/static/js/voice/prompt.js +0 -0
  326. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/static/js/winbox.bundle.min.js +0 -0
  327. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/static/js/workspace-window.js +0 -0
  328. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/static/manifest.webmanifest +0 -0
  329. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/static/service-worker.js +0 -0
  330. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/static/topology-harness.html +0 -0
  331. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/stt/__init__.py +0 -0
  332. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/stt/base.py +0 -0
  333. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/stt/cloud.py +0 -0
  334. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/stt/engine.py +0 -0
  335. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/stt/local.py +0 -0
  336. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/stt/server_backend.py +0 -0
  337. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/stt/stt_server.py +0 -0
  338. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/system_cli.py +0 -0
  339. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/tabs_cli.py +0 -0
  340. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/tasks_cli.py +0 -0
  341. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/templates/__init__.py +0 -0
  342. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/templates/base.html +0 -0
  343. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/templates/council/minutes.html.j2 +0 -0
  344. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/templates/desktop.html +0 -0
  345. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/templates/email_notification.html +0 -0
  346. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/templates/handoff/show-the-story.html.j2 +0 -0
  347. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/templates/handoff/theme.css.j2 +0 -0
  348. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/templates/mobile.html +0 -0
  349. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/templates/pair.html +0 -0
  350. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/templating.py +0 -0
  351. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/tooldefs/aws.yaml +0 -0
  352. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/tooldefs/docker.yaml +0 -0
  353. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/tooldefs/gcp.yaml +0 -0
  354. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/tooldefs/gh.yaml +0 -0
  355. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/tooldefs/git.yaml +0 -0
  356. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/tooldefs/gws.yaml +0 -0
  357. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/tooldefs/kubectl.yaml +0 -0
  358. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/tooldefs/npm.yaml +0 -0
  359. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/tooldefs/terraform.yaml +0 -0
  360. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/tooldefs/uv.yaml +0 -0
  361. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/tts/__init__.py +0 -0
  362. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/tts/audio.py +0 -0
  363. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/tts/base.py +0 -0
  364. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/tts/engines/__init__.py +0 -0
  365. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/tts/engines/chatterbox.py +0 -0
  366. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/tts/engines/kokoro.py +0 -0
  367. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/tts/engines/zonos.py +0 -0
  368. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/tts/kokoro_server.py +0 -0
  369. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/tts/local.py +0 -0
  370. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/tts/registry.py +0 -0
  371. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/tts_cli.py +0 -0
  372. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/tts_server.py +0 -0
  373. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/tunnels.py +0 -0
  374. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/tunnels_cli.py +0 -0
  375. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/usage_limit.py +0 -0
  376. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/utils/__init__.py +0 -0
  377. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/utils/chunker.py +0 -0
  378. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/utils/event_log.py +0 -0
  379. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/utils/file_io.py +0 -0
  380. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/utils/paths.py +0 -0
  381. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/utils/speech.py +0 -0
  382. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/utils/subprocess.py +0 -0
  383. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/validation.py +0 -0
  384. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/voice_status.py +0 -0
  385. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/wiki.py +0 -0
  386. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/wiki_audit.py +0 -0
  387. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/agentwire/wiki_cli.py +0 -0
  388. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/docs/decisions/obsidian-second-brain.md +0 -0
  389. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/docs/design/session-card-fields.md +0 -0
  390. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/docs/design/session-card-recommendation.md +0 -0
  391. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/docs/logo.png +0 -0
  392. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/docs/wiki/architecture.md +0 -0
  393. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/docs/wiki/briefing-mode.md +0 -0
  394. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/docs/wiki/communication/channels.md +0 -0
  395. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/docs/wiki/communication/hammerspoon.md +0 -0
  396. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/docs/wiki/communication/handoff.md +0 -0
  397. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/docs/wiki/concepts.md +0 -0
  398. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/docs/wiki/council.md +0 -0
  399. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/docs/wiki/deployment/remote-access.md +0 -0
  400. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/docs/wiki/deployment/remote-machines.md +0 -0
  401. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/docs/wiki/glossary.md +0 -0
  402. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/docs/wiki/integrations/gws-google-workspace-cli.md +0 -0
  403. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/docs/wiki/internals/damage-control.md +0 -0
  404. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/docs/wiki/internals/parallel-refactor.md +0 -0
  405. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/docs/wiki/internals/portal.md +0 -0
  406. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/docs/wiki/internals/session-topology.md +0 -0
  407. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/docs/wiki/internals/troubleshooting.md +0 -0
  408. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/docs/wiki/internals/window-collage.md +0 -0
  409. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/docs/wiki/research/briefing-mode-feasibility.md +0 -0
  410. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/docs/wiki/research/orchestration-transport-alternatives.md +0 -0
  411. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/docs/wiki/security/damage-control-hardening.md +0 -0
  412. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/docs/wiki/security/pip-audit.md +0 -0
  413. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/docs/wiki/security/remote-access-hardening.md +0 -0
  414. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/docs/wiki/security/secrets.md +0 -0
  415. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/docs/wiki/services.md +0 -0
  416. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/docs/wiki/sessions/claude-code-auto-mode.md +0 -0
  417. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/docs/wiki/sessions/prompt-routing.md +0 -0
  418. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/docs/wiki/sessions/window-sizing.md +0 -0
  419. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/docs/wiki/usage-limit-recovery.md +0 -0
  420. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/docs/wiki/voice/shim-contract.md +0 -0
  421. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/docs/wiki/voice/stt-cloud.md +0 -0
  422. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/docs/wiki/voice/stt-self-hosted.md +0 -0
  423. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/docs/wiki/voice/tts-self-hosted.md +0 -0
  424. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/tests/e2e/test_portal_ui.py +0 -0
  425. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/tests/fixtures/sample_agentwire.yml +0 -0
  426. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/tests/fixtures/sample_config.yaml +0 -0
  427. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/tests/fixtures/sample_scheduler.yaml +0 -0
  428. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/tests/integration/test_council_portal.py +0 -0
  429. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/tests/integration/test_scheduler_board.py +0 -0
  430. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/tests/integration/test_server_websockets.py +0 -0
  431. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/tests/unit/test_announcements.py +0 -0
  432. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/tests/unit/test_build_agent_command.py +0 -0
  433. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/tests/unit/test_channels.py +0 -0
  434. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/tests/unit/test_chrome_tabs.py +0 -0
  435. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/tests/unit/test_cli_output.py +0 -0
  436. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/tests/unit/test_cli_smoke.py +0 -0
  437. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/tests/unit/test_config.py +0 -0
  438. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/tests/unit/test_config_cli.py +0 -0
  439. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/tests/unit/test_control_plane_protection.py +0 -0
  440. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/tests/unit/test_core_created_by_rooting.py +0 -0
  441. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/tests/unit/test_council_cli.py +0 -0
  442. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/tests/unit/test_council_inbox.py +0 -0
  443. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/tests/unit/test_council_minutes.py +0 -0
  444. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/tests/unit/test_council_state.py +0 -0
  445. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/tests/unit/test_council_view.py +0 -0
  446. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/tests/unit/test_damage_control_bypass.py +0 -0
  447. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/tests/unit/test_damage_control_hooks.py +0 -0
  448. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/tests/unit/test_damage_control_sync.py +0 -0
  449. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/tests/unit/test_dangling_worktrees.py +0 -0
  450. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/tests/unit/test_devices.py +0 -0
  451. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/tests/unit/test_diff_cli.py +0 -0
  452. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/tests/unit/test_doctor_scheduler_staleness.py +0 -0
  453. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/tests/unit/test_doctor_task_migration.py +0 -0
  454. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/tests/unit/test_doctor_voice.py +0 -0
  455. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/tests/unit/test_event_log.py +0 -0
  456. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/tests/unit/test_file_io.py +0 -0
  457. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/tests/unit/test_guarded_launch_command.py +0 -0
  458. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/tests/unit/test_handoff_git_state.py +0 -0
  459. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/tests/unit/test_handoff_instructions.py +0 -0
  460. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/tests/unit/test_handoff_parser.py +0 -0
  461. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/tests/unit/test_handoff_renderer.py +0 -0
  462. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/tests/unit/test_history.py +0 -0
  463. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/tests/unit/test_hooks_install.py +0 -0
  464. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/tests/unit/test_idle_nag.py +0 -0
  465. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/tests/unit/test_inbox.py +0 -0
  466. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/tests/unit/test_init_command.py +0 -0
  467. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/tests/unit/test_install_parity.py +0 -0
  468. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/tests/unit/test_limits_tick_isolation.py +0 -0
  469. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/tests/unit/test_locking.py +0 -0
  470. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/tests/unit/test_msg_cli.py +0 -0
  471. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/tests/unit/test_notify_cli.py +0 -0
  472. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/tests/unit/test_onboarding_reinit.py +0 -0
  473. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/tests/unit/test_palette_cli.py +0 -0
  474. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/tests/unit/test_pip_environment.py +0 -0
  475. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/tests/unit/test_posture_default.py +0 -0
  476. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/tests/unit/test_projects_registry.py +0 -0
  477. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/tests/unit/test_push.py +0 -0
  478. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/tests/unit/test_rebuild_guard.py +0 -0
  479. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/tests/unit/test_repo_cli.py +0 -0
  480. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/tests/unit/test_rich_text_js.py +0 -0
  481. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/tests/unit/test_roles.py +0 -0
  482. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/tests/unit/test_routes_snapshot.py +0 -0
  483. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/tests/unit/test_safety_commands.py +0 -0
  484. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/tests/unit/test_safety_disabled_rules.py +0 -0
  485. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/tests/unit/test_safety_escape_hatch.py +0 -0
  486. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/tests/unit/test_safety_heal.py +0 -0
  487. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/tests/unit/test_safety_kill_switch.py +0 -0
  488. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/tests/unit/test_scheduler_parsing.py +0 -0
  489. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/tests/unit/test_scratchpad.py +0 -0
  490. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/tests/unit/test_security.py +0 -0
  491. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/tests/unit/test_server_async.py +0 -0
  492. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/tests/unit/test_server_pure.py +0 -0
  493. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/tests/unit/test_services.py +0 -0
  494. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/tests/unit/test_session_context.py +0 -0
  495. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/tests/unit/test_session_created_by_env.py +0 -0
  496. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/tests/unit/test_shared_dir_guard.py +0 -0
  497. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/tests/unit/test_shim_selfheal.py +0 -0
  498. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/tests/unit/test_skill_install.py +0 -0
  499. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/tests/unit/test_speech_tags.py +0 -0
  500. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/tests/unit/test_ssh.py +0 -0
  501. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/tests/unit/test_stt_backend.py +0 -0
  502. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/tests/unit/test_stt_cloud.py +0 -0
  503. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/tests/unit/test_stt_engine.py +0 -0
  504. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/tests/unit/test_task_cli.py +0 -0
  505. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/tests/unit/test_tasks.py +0 -0
  506. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/tests/unit/test_tasks_cli.py +0 -0
  507. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/tests/unit/test_templating.py +0 -0
  508. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/tests/unit/test_terminal_resize.py +0 -0
  509. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/tests/unit/test_tmux_template.py +0 -0
  510. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/tests/unit/test_tts_engine_resolution.py +0 -0
  511. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/tests/unit/test_tts_local.py +0 -0
  512. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/tests/unit/test_tunnels_probe.py +0 -0
  513. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/tests/unit/test_unattended_env_isolation.py +0 -0
  514. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/tests/unit/test_usage_limit.py +0 -0
  515. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/tests/unit/test_validation.py +0 -0
  516. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/tests/unit/test_voice_status.py +0 -0
  517. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/tests/unit/test_wiki.py +0 -0
  518. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/tests/unit/test_wiki_audit.py +0 -0
  519. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/tests/unit/test_window_cycling_binding.py +0 -0
  520. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/tests/unit/test_worktree.py +0 -0
  521. {agentwire_dev-1.65.2 → agentwire_dev-1.66.0}/tests/unit/test_worktree_branch_cleanup.py +0 -0
  522. {agentwire_dev-1.65.2 → agentwire_dev-1.66.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.65.2
3
+ Version: 1.66.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.65.2"
3
+ __version__ = "1.66.0"
@@ -190,7 +190,7 @@ Command Categories:
190
190
  from . import doctor_cli, history_cli, machine_cli, safety_cli
191
191
  from . import handoff_cli, hooks_cli, mcp_cli, roles_cli, tunnels_cli
192
192
  from . import notify_cli, palette_cli, push_cli, repo_cli, system_cli, wiki_cli
193
- from . import tabs_cli
193
+ from . import tabs_cli, wait_cli, worktree_cli
194
194
  from .council import cli as council_cli
195
195
 
196
196
  _REGISTRARS = [ # noqa: N806 # registry constant; Phase 1 of #495 appends here
@@ -225,6 +225,8 @@ Command Categories:
225
225
  config_cli.register_config_parser,
226
226
  palette_cli.register_palette_parser,
227
227
  tabs_cli.register_tabs_parser,
228
+ wait_cli.register_wait_parser,
229
+ worktree_cli.register_helper_parser,
228
230
  ]
229
231
  for _reg in _REGISTRARS:
230
232
  _reg(subparsers)
@@ -0,0 +1,505 @@
1
+ """Fan-out cohort ledger — a parent's outstanding children (#852).
2
+
3
+ A scheduled task that fans out child sessions had no way to wait for them.
4
+ The parent went idle while *waiting*, the idle handler read idle as done, and
5
+ the task was reaped — killing the roll-up the parent existed to write and
6
+ orphaning the children's report-backs into dead-letter (which, for
7
+ load-bearing kinds, also emails the owner about work that succeeded). The
8
+ children themselves were full ``agentwire new`` sessions, so nothing reaped
9
+ them either: a nightly fan-out leaked N sessions per run.
10
+
11
+ **idle != done for a session with outstanding children.** This module is the
12
+ one artifact that makes that knowable, with three consumers:
13
+
14
+ 1. ``agentwire wait --children`` (:func:`wait`) — the join primitive. Blocking
15
+ inside a tool call is not idle, so the hook never fires and the agent
16
+ resumes naturally to write its roll-up.
17
+ 2. The idle-handler guard — a file-existence + ``jq`` check in the same shape
18
+ as the usage-limit park guard and the #276 prompt-router guard. It reads
19
+ ``state == "pending"`` and ``deadline`` directly out of the JSON, so those
20
+ two field names are load-bearing across the language boundary.
21
+ 3. The watchdog sweeper (:func:`tick`) — the anti-leak backstop. It reaps a
22
+ cohort whose parent died mid-wait, and reconciles a live parent's ledger so
23
+ the guard self-clears as children exit.
24
+
25
+ **Cohort is not rooting.** ``created_by`` (#715) answers "who has authority /
26
+ where do prompts route", and deliberately returns nothing for a *cross-project*
27
+ spawn. The 2026-08-01 fan-out was three cross-project children and one
28
+ same-project one, so a ``created_by``-derived guard would have protected
29
+ exactly one child and reaped the parent out from under the other three. A
30
+ half-linked fan-out is worse than an unlinked one, so cohort membership is
31
+ keyed off the CALLER, independent of the rooting decision.
32
+
33
+ **Ordering is load-bearing.** ``agentwire kill`` runs ``inbox.gc_sender()``,
34
+ which dead-letters the killed session's still-pending load-bearing outbound
35
+ **and emails the owner**. Kill-before-collect turns every child's ``done``
36
+ report into owner email. So: collect the report, consume it, THEN kill.
37
+
38
+ Everything here fails OPEN: a missing, corrupt, or expired ledger must never be
39
+ able to wedge a task alive forever.
40
+ """
41
+
42
+ from __future__ import annotations
43
+
44
+ import json
45
+ import os
46
+ import subprocess
47
+ import tempfile
48
+ import time
49
+ from contextlib import contextmanager
50
+ from pathlib import Path
51
+
52
+ from .utils.event_log import append_event
53
+
54
+ COHORT_ROOT = Path.home() / ".agentwire" / "cohorts"
55
+ EVENTS_FILE = Path.home() / ".agentwire" / "cohort-events.jsonl"
56
+
57
+ # How long a cohort may suppress its parent's idle handling. Past this the
58
+ # guard stops firing, `wait` stops blocking, and outstanding children are
59
+ # killed and reported as failures — a wedged child must not pin a task forever.
60
+ DEFAULT_TTL = 3600
61
+
62
+ # How long past its deadline a ledger survives when the parent is still alive.
63
+ # Covers a parent that fanned out and never called `wait --children`: the guard
64
+ # has already stopped protecting it, and the children get reaped rather than
65
+ # leaked. Generous, because a parent that IS about to call `wait` should find
66
+ # its ledger intact.
67
+ STALE_GRACE = 3600
68
+
69
+ # Child states. `pending` is read by the idle-handler guard's jq — renaming it
70
+ # silently disarms the guard.
71
+ PENDING = "pending"
72
+ REPORTED = "reported" # report collected, child killed
73
+ TIMEOUT = "timeout" # deadline hit with no report; child killed anyway
74
+ GONE = "gone" # child's session vanished before it reported
75
+
76
+ RESOLVED_STATES = (REPORTED, TIMEOUT, GONE)
77
+
78
+ # Topologies, which decide whether resolving a child also tears its session
79
+ # down. A `main`-topology child (`agentwire new`) is the leak this issue is
80
+ # about: nothing reaps it, so the cohort does. A `worktree` child is NOT torn
81
+ # down — it holds a branch and possibly an open PR, whose teardown must follow
82
+ # merge verification (#756), and its session is where a reviewer sends fix-ups.
83
+ # It is still tracked, still reported, and still surfaced when it goes silent;
84
+ # an abandoned one is what `worktree --dangling` / `--list` already flag.
85
+ MAIN = "main"
86
+ WORKTREE = "worktree"
87
+
88
+ # Kinds a child's report-back can arrive as. `note` is included because a child
89
+ # that fails mid-task may downgrade its report; `ingest` is not, since passive
90
+ # messages are pull-only pointers the parent reads separately.
91
+ REPORT_KINDS = ("done", "request", "escalation", "note")
92
+
93
+ _POLL_INTERVAL = 2.0
94
+
95
+
96
+ # =============================================================================
97
+ # Ledger I/O
98
+ # =============================================================================
99
+
100
+
101
+ def _now() -> int:
102
+ return int(time.time())
103
+
104
+
105
+ def log_event(event: str, **fields) -> None:
106
+ append_event(EVENTS_FILE, {"ts": _now(), "event": event, **fields})
107
+
108
+
109
+ def ledger_path(parent: str) -> Path:
110
+ """Ledger file for *parent*. Worktree names contain ``/`` and nest a dir."""
111
+ if not parent or parent.startswith("/") or ".." in parent.split("/"):
112
+ raise ValueError(f"invalid session name: {parent!r}")
113
+ path = COHORT_ROOT / f"{parent}.json"
114
+ if not path.resolve().is_relative_to(COHORT_ROOT.resolve()):
115
+ raise ValueError(f"invalid session name: {parent!r}")
116
+ return path
117
+
118
+
119
+ def load(parent: str) -> dict | None:
120
+ """The parent's ledger, or None when absent/unreadable/malformed.
121
+
122
+ Fails open on purpose: a corrupt ledger reads as "no cohort", so the guard
123
+ stops suppressing and the parent resumes normal idle handling.
124
+ """
125
+ try:
126
+ data = json.loads(ledger_path(parent).read_text())
127
+ except (OSError, ValueError):
128
+ return None
129
+ if not isinstance(data, dict) or not isinstance(data.get("children"), list):
130
+ return None
131
+ return data
132
+
133
+
134
+ def _save(parent: str, data: dict) -> None:
135
+ path = ledger_path(parent)
136
+ path.parent.mkdir(parents=True, exist_ok=True)
137
+ fd, tmp = tempfile.mkstemp(prefix=path.name + ".", dir=str(path.parent))
138
+ try:
139
+ with os.fdopen(fd, "w") as f:
140
+ json.dump(data, f, indent=2, sort_keys=True)
141
+ os.replace(tmp, path)
142
+ except Exception:
143
+ try:
144
+ os.unlink(tmp)
145
+ except OSError:
146
+ pass
147
+ raise
148
+
149
+
150
+ @contextmanager
151
+ def _locked(parent: str):
152
+ """Serialize a read-modify-write on one parent's ledger.
153
+
154
+ An orchestrator can fire several spawns in a single turn (parallel tool
155
+ calls), and a lost update there means a child is never enrolled — i.e. a
156
+ session that leaks. Same mkdir-based lock the inbox uses; best-effort, so a
157
+ stuck lock degrades to the unsynchronized write rather than blocking a
158
+ spawn.
159
+ """
160
+ lock = ledger_path(parent).with_suffix(".lock")
161
+ held = False
162
+ for _ in range(50):
163
+ try:
164
+ lock.parent.mkdir(parents=True, exist_ok=True)
165
+ os.mkdir(lock)
166
+ held = True
167
+ break
168
+ except FileExistsError:
169
+ time.sleep(0.1)
170
+ except OSError:
171
+ break
172
+ try:
173
+ yield
174
+ finally:
175
+ if held:
176
+ try:
177
+ os.rmdir(lock)
178
+ except OSError:
179
+ pass
180
+
181
+
182
+ def discard(parent: str) -> bool:
183
+ """Delete the parent's ledger. True if one was there."""
184
+ try:
185
+ ledger_path(parent).unlink()
186
+ return True
187
+ except (OSError, ValueError):
188
+ return False
189
+
190
+
191
+ def enroll(parent: str, child: str, task: str | None = None,
192
+ ttl: int = DEFAULT_TTL, topology: str = MAIN) -> bool:
193
+ """Record *child* as an outstanding member of *parent*'s cohort.
194
+
195
+ Called automatically by ``agentwire new`` (and therefore ``worktree``)
196
+ whenever there is a caller, so a fan-out author has no bookkeeping to
197
+ forget. Re-enrolling a session already in the ledger is a no-op; a fresh
198
+ fan-out after the previous cohort resolved extends the deadline so the
199
+ second wave gets its own full TTL.
200
+
201
+ *topology* decides whether resolving this child also tears its session
202
+ down — see :data:`WORKTREE`.
203
+ """
204
+ if not parent or not child or parent == child:
205
+ return False
206
+ try:
207
+ with _locked(parent):
208
+ data = load(parent) or {
209
+ "parent": parent, "task": task, "created_at": _now(), "children": [],
210
+ }
211
+ if any(c.get("session") == child for c in data["children"]):
212
+ return False
213
+ data["children"].append({
214
+ "session": child, "state": PENDING, "report": None,
215
+ "topology": topology, "enrolled_at": _now(),
216
+ })
217
+ data["deadline"] = _now() + ttl
218
+ if task and not data.get("task"):
219
+ data["task"] = task
220
+ _save(parent, data)
221
+ except (OSError, ValueError):
222
+ return False
223
+ log_event("enrolled", parent=parent, child=child, task=task)
224
+ return True
225
+
226
+
227
+ def pending(parent: str) -> list[str]:
228
+ """Sessions in *parent*'s cohort that haven't been resolved yet."""
229
+ data = load(parent)
230
+ if not data:
231
+ return []
232
+ return [c["session"] for c in data["children"]
233
+ if c.get("state") == PENDING and c.get("session")]
234
+
235
+
236
+ def blocking(parent: str, now: int | None = None) -> bool:
237
+ """Should *parent*'s idle handling be suppressed right now?
238
+
239
+ The Python mirror of the idle-handler's jq guard: pending children AND the
240
+ deadline not yet passed. Both halves matter — the deadline is what stops a
241
+ wedged child from pinning a task alive forever.
242
+ """
243
+ data = load(parent)
244
+ if not data:
245
+ return False
246
+ if not any(c.get("state") == PENDING for c in data["children"]):
247
+ return False
248
+ return (now if now is not None else _now()) < int(data.get("deadline") or 0)
249
+
250
+
251
+ def _mark(data: dict, child: str, state: str, report: str | None = None) -> None:
252
+ for entry in data["children"]:
253
+ if entry.get("session") == child:
254
+ entry["state"] = state
255
+ if report is not None:
256
+ entry["report"] = report
257
+
258
+
259
+ # =============================================================================
260
+ # Session liveness / teardown
261
+ # =============================================================================
262
+
263
+
264
+ def session_exists(session: str) -> bool:
265
+ try:
266
+ return subprocess.run(
267
+ ["tmux", "has-session", "-t", f"={session}"],
268
+ capture_output=True, timeout=5,
269
+ ).returncode == 0
270
+ except (OSError, subprocess.SubprocessError):
271
+ return False
272
+
273
+
274
+ def _kill(session: str) -> bool:
275
+ """Tear a child session down through the CLI's own kill path.
276
+
277
+ Never the child's own job (a wedged child never goes idle, so child-side
278
+ teardown structurally can't cover the failure path), and never raw tmux —
279
+ the shared path also drops session metadata and GCs the child's leftover
280
+ outbound.
281
+ """
282
+ try:
283
+ from .pane_cli import kill_local_session
284
+
285
+ return bool(kill_local_session(session).get("success"))
286
+ except Exception:
287
+ return False
288
+
289
+
290
+ # =============================================================================
291
+ # Collection + join
292
+ # =============================================================================
293
+
294
+
295
+ def _harvest(parent: str) -> dict[str, list]:
296
+ """Pending inbox messages to *parent*, grouped by sender.
297
+
298
+ Read straight off disk rather than waiting for the drain to paste them:
299
+ the parent is mid-tool-call, and a paste into its box is exactly what
300
+ #851 makes unreliable for long reports.
301
+ """
302
+ try:
303
+ from . import inbox
304
+
305
+ out: dict[str, list] = {}
306
+ for msg in inbox.list_messages(parent):
307
+ if msg.kind in REPORT_KINDS:
308
+ out.setdefault(msg.sender, []).append(msg)
309
+ return out
310
+ except Exception:
311
+ return {}
312
+
313
+
314
+ def _consume(messages: list) -> str:
315
+ """Take these messages out of the inbox and return their text.
316
+
317
+ Consuming BEFORE the kill is what keeps ``gc_sender`` from dead-lettering
318
+ the report (and emailing the owner) for a child that reported perfectly.
319
+ """
320
+ texts = []
321
+ for msg in messages:
322
+ texts.append(msg.text)
323
+ try:
324
+ if msg.path:
325
+ msg.path.unlink()
326
+ except OSError:
327
+ pass
328
+ return "\n".join(texts)
329
+
330
+
331
+ def collect(parent: str) -> dict | None:
332
+ """One resolution pass over *parent*'s cohort. Returns the ledger, or None.
333
+
334
+ Per pending child: a report waiting in the parent's inbox is consumed and
335
+ the child torn down (collect → consume → kill, in that order); a child
336
+ whose session has already vanished is marked ``gone``. Past the deadline
337
+ every remaining child is torn down and marked ``timeout`` so the parent's
338
+ summary can name it as a failure instead of the run silently leaking a live
339
+ session. Teardown skips worktree children — see :func:`_teardown`.
340
+ """
341
+ data = load(parent)
342
+ if not data:
343
+ return None
344
+ outstanding = [c["session"] for c in data["children"]
345
+ if c.get("state") == PENDING and c.get("session")]
346
+ if not outstanding:
347
+ return data
348
+
349
+ expired = _now() >= int(data.get("deadline") or 0)
350
+ reports = _harvest(parent)
351
+ for child in outstanding:
352
+ msgs = reports.get(child)
353
+ if msgs:
354
+ _mark(data, child, REPORTED, _consume(msgs))
355
+ _teardown(data, child)
356
+ log_event("collected", parent=parent, child=child)
357
+ elif not session_exists(child):
358
+ _mark(data, child, GONE)
359
+ log_event("child_gone", parent=parent, child=child)
360
+ elif expired:
361
+ _mark(data, child, TIMEOUT)
362
+ _teardown(data, child)
363
+ log_event("child_timeout", parent=parent, child=child)
364
+ _save(parent, data)
365
+ return data
366
+
367
+
368
+ def _teardown(data: dict, child: str) -> bool:
369
+ """Kill a resolved child's session — unless it's on worktree topology.
370
+
371
+ The leak #852 is about is a ``main``-topology child: a full session nothing
372
+ reaps. A worktree child is deliberately left running: its branch and any
373
+ open PR are torn down only after merge verification (#756), a reviewer may
374
+ still need to send it fix-ups, and an abandoned one is already surfaced by
375
+ ``worktree --dangling``. Killing it would trade a visible leak for a
376
+ silently destroyed working tree.
377
+ """
378
+ entry = next((c for c in data["children"] if c.get("session") == child), None)
379
+ if entry is not None and entry.get("topology") == WORKTREE:
380
+ entry["torn_down"] = False
381
+ return False
382
+ killed = _kill(child)
383
+ if entry is not None:
384
+ entry["torn_down"] = killed
385
+ return killed
386
+
387
+
388
+ def summarize(data: dict) -> dict:
389
+ """Caller-facing view of a ledger."""
390
+ children = data.get("children") or []
391
+ return {
392
+ "parent": data.get("parent"),
393
+ "task": data.get("task"),
394
+ "deadline": data.get("deadline"),
395
+ "pending": [c["session"] for c in children if c.get("state") == PENDING],
396
+ "reports": [{"session": c["session"], "report": c.get("report")}
397
+ for c in children if c.get("state") == REPORTED],
398
+ "failed": [{"session": c["session"], "state": c.get("state")}
399
+ for c in children if c.get("state") in (TIMEOUT, GONE)],
400
+ # Resolved but deliberately still running: worktree children, whose
401
+ # branch/PR teardown follows merge verification (#756).
402
+ "left_alive": [c["session"] for c in children
403
+ if c.get("state") in (REPORTED, TIMEOUT)
404
+ and c.get("torn_down") is False],
405
+ "children": children,
406
+ }
407
+
408
+
409
+ def wait(parent: str, timeout: float = 600.0,
410
+ poll: float = _POLL_INTERVAL) -> dict:
411
+ """Block until *parent*'s cohort resolves, this call's *timeout* elapses,
412
+ or the cohort deadline passes.
413
+
414
+ Blocking here happens inside a tool call, which is not idle — so the idle
415
+ hook never fires, the parent is never prompted for a roll-up it can't
416
+ write, and it resumes naturally with every child's report in hand.
417
+
418
+ Bounded and re-callable: a fan-out longer than the calling harness's tool
419
+ timeout just loops. The ledger is deleted once nothing is pending, so the
420
+ idle guard stops suppressing the moment the cohort is done.
421
+ """
422
+ data = load(parent)
423
+ if not data:
424
+ return {"parent": parent, "cohort": False, "resolved": True,
425
+ "pending": [], "reports": [], "failed": [], "left_alive": [],
426
+ "children": []}
427
+
428
+ deadline = time.time() + max(timeout, 0)
429
+ while True:
430
+ data = collect(parent) or data
431
+ result = summarize(data)
432
+ if not result["pending"]:
433
+ discard(parent)
434
+ log_event("resolved", parent=parent,
435
+ reported=len(result["reports"]), failed=len(result["failed"]))
436
+ return {**result, "cohort": True, "resolved": True}
437
+ if time.time() >= deadline:
438
+ return {**result, "cohort": True, "resolved": False}
439
+ time.sleep(poll)
440
+
441
+
442
+ # =============================================================================
443
+ # Watchdog sweep
444
+ # =============================================================================
445
+
446
+
447
+ def sweep() -> dict:
448
+ """Reconcile every ledger on disk. The anti-leak backstop.
449
+
450
+ - **Parent gone** → kill whatever is still pending and delete the ledger.
451
+ This is the crash path (usage limit, guard deadline, ``/exit``) that
452
+ leaks children under every other mechanism, including a child-side
453
+ self-kill: a wedged child never goes idle, so it never self-kills.
454
+ - **Parent alive** → mark pending children whose session has vanished, so
455
+ the idle guard self-clears as the cohort empties.
456
+ - **Past deadline + grace** → the parent fanned out and never joined; kill
457
+ the stragglers and drop the ledger rather than leaving it to suppress
458
+ nothing forever.
459
+
460
+ Teardown here is deliberately session-only: killing a tmux session never
461
+ touches a worktree's branch or its open PR, whose removal must follow merge
462
+ verification (#756) and stays with ``worktree --remove``.
463
+ """
464
+ reaped: list[dict] = []
465
+ swept: list[str] = []
466
+ if not COHORT_ROOT.exists():
467
+ return {"reaped": reaped, "swept": swept}
468
+
469
+ for path in sorted(p for p in COHORT_ROOT.rglob("*.json") if p.is_file()):
470
+ try:
471
+ parent = str(path.relative_to(COHORT_ROOT))[: -len(".json")]
472
+ except ValueError:
473
+ continue
474
+ data = load(parent)
475
+ if not data:
476
+ continue
477
+ outstanding = [c["session"] for c in data["children"]
478
+ if c.get("state") == PENDING and c.get("session")]
479
+ parent_live = session_exists(parent)
480
+ expired = _now() >= int(data.get("deadline") or 0) + STALE_GRACE
481
+
482
+ if parent_live and not expired:
483
+ changed = False
484
+ for child in outstanding:
485
+ if not session_exists(child):
486
+ _mark(data, child, GONE)
487
+ changed = True
488
+ if changed:
489
+ _save(parent, data)
490
+ swept.append(parent)
491
+ continue
492
+
493
+ for child in outstanding:
494
+ if session_exists(child) and _teardown(data, child):
495
+ reaped.append({"parent": parent, "child": child})
496
+ log_event("orphan_reaped", parent=parent, child=child,
497
+ parent_live=parent_live, expired=expired)
498
+ discard(parent)
499
+ swept.append(parent)
500
+ return {"reaped": reaped, "swept": swept}
501
+
502
+
503
+ def tick() -> dict:
504
+ """Watchdog stage entry point — same shape as :func:`sweep`."""
505
+ return sweep()
@@ -740,8 +740,13 @@ def _record_session_creator(session_name: str, created_by: str | None, via: str)
740
740
 
741
741
  The creator becomes the session's parent for prompt routing
742
742
  (prompt_router.resolve_parent), winning over .agentwire.yml `parent:`.
743
+
744
+ ``created_by`` of ``''`` means "explicitly rootless" and must still be
745
+ written — otherwise a re-`new`/`recreate` that forces standalone (e.g.
746
+ `--created-by ''`) leaves a stale parent from a prior creation in place,
747
+ since `not created_by` is also true for `''`.
743
748
  """
744
- if not created_by or created_by == session_name.split("@")[0]:
749
+ if created_by is None or created_by == session_name.split("@")[0]:
745
750
  return
746
751
  metadata = load_session_metadata(session_name)
747
752
  metadata.update({
@@ -963,6 +968,28 @@ def _guarded_launch_command(path_str: str, agent_cmd: str | None) -> str:
963
968
  return f"{guard} && {agent_cmd}" if agent_cmd else guard
964
969
 
965
970
 
971
+ # The pane's launch command travels as an ENV VAR, not as keystrokes (#856).
972
+ #
973
+ # `send-keys` fires 0.1s after `tmux new-session`, before the shell has put
974
+ # its tty into raw mode, so the keystrokes land in the tty's CANONICAL-mode
975
+ # input buffer — which is capped at 1024 bytes per line on macOS
976
+ # (MAX_CANON/`N_TTY_BUF_SIZE`; Linux is 4096). Everything past the cap is
977
+ # discarded SILENTLY, and since the launch line ends in
978
+ # `--append-system-prompt "$(</tmp/…)"`, a truncated one is syntactically
979
+ # incomplete: zsh sits at a continuation prompt forever, `claude` never runs,
980
+ # and the session is a bare shell that `wait_for_session_ready` can only
981
+ # report as "Agent not running". #742/#743 grew `_guarded_launch_command` by
982
+ # ~700 chars, which pushed long-named worktree sessions (the scheduler's
983
+ # `scheduler-<task>-<timestamp>`, whose path is interpolated FOUR times) over
984
+ # the cap — deterministically, since the length is a pure function of the
985
+ # session name.
986
+ #
987
+ # tmux `-e` is not keyboard input, so it has no such cap. Sending a fixed
988
+ # ~70-char `eval` line instead makes the launch length-independent.
989
+ LAUNCH_CMD_ENV = "AGENTWIRE_LAUNCH_CMD"
990
+ _LAUNCH_EVAL = f'eval "${{{LAUNCH_CMD_ENV}:?agentwire: launch command not injected}}"'
991
+
992
+
966
993
  def _launch_tmux_session(
967
994
  session_name: str,
968
995
  session_path,
@@ -975,9 +1002,14 @@ def _launch_tmux_session(
975
1002
  The one launch sequence shared by ``new`` / ``recreate`` / ``fork`` (#630):
976
1003
  `tmux new-session -e K=V` injects *env* into the session environment
977
1004
  BEFORE the initial shell starts (post-hoc `set-environment` never reaches
978
- it), then `send-keys` cd's into place (guarded — see
979
- ``_guarded_launch_command``) and, if *agent_cmd* is non-empty, starts the
980
- agent after a short settle.
1005
+ it), then `send-keys` runs the guarded launch line (see
1006
+ ``_guarded_launch_command``) which cd's into place and, if *agent_cmd* is
1007
+ non-empty, starts the agent after a short settle.
1008
+
1009
+ That launch line rides in as ``AGENTWIRE_LAUNCH_CMD`` and is `eval`'d by
1010
+ the pane, rather than being typed out in full — see
1011
+ :data:`LAUNCH_CMD_ENV` for why typing it is length-limited and fails
1012
+ silently.
981
1013
 
982
1014
  Local (machine_id None): runs subprocess calls with check=True (raises on
983
1015
  tmux failure) and returns None. Remote: runs one composite shell command
@@ -987,23 +1019,25 @@ def _launch_tmux_session(
987
1019
 
988
1020
  path_str = str(session_path)
989
1021
  launch_cmd = _guarded_launch_command(path_str, agent_cmd)
1022
+ # Copy, never mutate: callers reuse `agent.env` after the launch.
1023
+ launch_env = {**env, LAUNCH_CMD_ENV: launch_cmd}
990
1024
  if machine_id:
991
- env_flags = _build_tmux_env_flags_shell(env)
1025
+ env_flags = _build_tmux_env_flags_shell(launch_env)
992
1026
  create_cmd = (
993
1027
  f"tmux new-session -d -s {shlex.quote(session_name)} -c {shlex.quote(path_str)} {env_flags}&& "
994
1028
  f"sleep 0.1 && "
995
- f"tmux send-keys -t {shlex.quote(session_name)} {shlex.quote(launch_cmd)} Enter"
1029
+ f"tmux send-keys -t {shlex.quote(session_name)} {shlex.quote(_LAUNCH_EVAL)} Enter"
996
1030
  )
997
1031
  return _run_remote(machine_id, create_cmd)
998
1032
 
999
1033
  subprocess.run(
1000
1034
  ["tmux", "new-session", "-d", "-s", session_name, "-c", path_str,
1001
- *_build_tmux_env_flags(env)],
1035
+ *_build_tmux_env_flags(launch_env)],
1002
1036
  check=True,
1003
1037
  )
1004
1038
  time.sleep(0.1)
1005
1039
  subprocess.run(
1006
- ["tmux", "send-keys", "-t", session_name, launch_cmd, "Enter"],
1040
+ ["tmux", "send-keys", "-t", session_name, _LAUNCH_EVAL, "Enter"],
1007
1041
  check=True,
1008
1042
  )
1009
1043
  return None