agentwire-dev 1.65.3__tar.gz → 1.67.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 (530) hide show
  1. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/PKG-INFO +2 -2
  2. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/__init__.py +1 -1
  3. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/__main__.py +4 -2
  4. agentwire_dev-1.67.0/agentwire/cohort.py +505 -0
  5. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/completion.py +25 -2
  6. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/core.py +306 -43
  7. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/doctor_cli.py +171 -10
  8. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/ensure_cli.py +191 -10
  9. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/history_cli.py +30 -1
  10. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/hooks/idle-handler.sh +21 -0
  11. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/inbox.py +119 -11
  12. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/limits_cli.py +18 -9
  13. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/mcp_core.py +5 -0
  14. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/mcp_session.py +56 -0
  15. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/mcp_task.py +5 -0
  16. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/mcp_worktree.py +27 -4
  17. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/pane_cli.py +38 -14
  18. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/pane_manager.py +31 -41
  19. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/project_config.py +67 -8
  20. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/roles/reviewer-worktree.md +2 -0
  21. agentwire_dev-1.67.0/agentwire/roles/shared-checkout.md +60 -0
  22. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/roles/worker-worktree.md +6 -5
  23. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/routes/scheduler.py +34 -20
  24. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/scheduler/__init__.py +1 -0
  25. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/scheduler/dispatch.py +35 -11
  26. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/scheduler/report.py +83 -1
  27. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/scheduler/zombie.py +39 -8
  28. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/scheduler_cli.py +60 -5
  29. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/send_cli.py +128 -44
  30. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/server.py +33 -3
  31. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/session_cli.py +529 -154
  32. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/session_ready.py +268 -39
  33. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/system_cli.py +3 -0
  34. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/tasks.py +45 -0
  35. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/tasks_cli.py +7 -0
  36. agentwire_dev-1.67.0/agentwire/templates/statusline.sh +121 -0
  37. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/templates/tmux.conf +5 -3
  38. agentwire_dev-1.67.0/agentwire/wait_cli.py +86 -0
  39. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/worktree.py +300 -7
  40. agentwire_dev-1.67.0/agentwire/worktree_cli.py +152 -0
  41. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/worktree_registry.py +29 -4
  42. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/docs/wiki/INDEX.md +4 -1
  43. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/docs/wiki/internals/shell-escaping.md +64 -2
  44. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/docs/wiki/quickstart.md +17 -0
  45. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/docs/wiki/scheduling/scheduled-workloads.md +170 -1
  46. agentwire_dev-1.67.0/docs/wiki/sessions/conversation-identity.md +151 -0
  47. agentwire_dev-1.67.0/docs/wiki/sessions/fan-out-cohorts.md +182 -0
  48. agentwire_dev-1.67.0/docs/wiki/sessions/helper-sessions.md +103 -0
  49. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/docs/wiki/sessions/messaging.md +68 -10
  50. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/docs/wiki/sessions/worktree-sessions.md +20 -2
  51. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/pyproject.toml +6 -1
  52. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/tests/conftest.py +15 -0
  53. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/tests/integration/test_send_verified_tmux.py +194 -5
  54. agentwire_dev-1.67.0/tests/integration/test_tmux_name_rewrite.py +166 -0
  55. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/tests/integration/test_worktree_cmd.py +467 -6
  56. agentwire_dev-1.67.0/tests/unit/test_build_agent_command.py +358 -0
  57. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/tests/unit/test_cli_commands.py +364 -32
  58. agentwire_dev-1.67.0/tests/unit/test_cohort.py +345 -0
  59. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/tests/unit/test_doctor_scheduler_staleness.py +58 -15
  60. agentwire_dev-1.67.0/tests/unit/test_ensure_shared_dir.py +135 -0
  61. agentwire_dev-1.67.0/tests/unit/test_ensure_verified_prompt.py +155 -0
  62. agentwire_dev-1.67.0/tests/unit/test_helper_session.py +225 -0
  63. agentwire_dev-1.67.0/tests/unit/test_history_resume_name.py +126 -0
  64. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/tests/unit/test_idle_handler.py +79 -0
  65. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/tests/unit/test_inbox.py +101 -4
  66. agentwire_dev-1.67.0/tests/unit/test_launch_via_env.py +106 -0
  67. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/tests/unit/test_mcp_server.py +11 -0
  68. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/tests/unit/test_mcp_tools_args.py +15 -0
  69. agentwire_dev-1.67.0/tests/unit/test_pending_message_visibility.py +149 -0
  70. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/tests/unit/test_portal_api.py +28 -0
  71. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/tests/unit/test_project_config.py +99 -0
  72. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/tests/unit/test_prompt_router.py +38 -6
  73. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/tests/unit/test_scheduler.py +2 -2
  74. agentwire_dev-1.67.0/tests/unit/test_scheduler_liveness.py +351 -0
  75. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/tests/unit/test_scheduler_zombie.py +73 -1
  76. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/tests/unit/test_session_ready.py +467 -42
  77. agentwire_dev-1.67.0/tests/unit/test_task_max_duration.py +171 -0
  78. agentwire_dev-1.67.0/tests/unit/test_worktree_dot_project.py +146 -0
  79. agentwire_dev-1.67.0/tests/unit/test_worktree_git_truth.py +314 -0
  80. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/tests/unit/test_worktree_layout.py +29 -12
  81. agentwire_dev-1.65.3/tests/unit/test_build_agent_command.py +0 -163
  82. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/.agentwire.yml.example +0 -0
  83. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/.claude/commands/handoff.md +0 -0
  84. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/.claude/skills/wiki/SKILL.md +0 -0
  85. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/.github/FUNDING.yml +0 -0
  86. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
  87. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
  88. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/.github/ISSUE_TEMPLATE/question.md +0 -0
  89. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
  90. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/.github/workflows/pytest.yml +0 -0
  91. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/.github/workflows/ruff.yml +0 -0
  92. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/.github/workflows/security.yml +0 -0
  93. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/.github/workflows/tts-smoke.yml +0 -0
  94. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/.gitignore +0 -0
  95. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/AGENTS.md +0 -0
  96. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/CODE_OF_CONDUCT.md +0 -0
  97. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/CONTRIBUTING.md +0 -0
  98. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/Dockerfile.local +0 -0
  99. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/LICENSE +0 -0
  100. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/README.md +0 -0
  101. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/RELEASING.md +0 -0
  102. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/SECURITY.md +0 -0
  103. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/SPONSORS.md +0 -0
  104. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/agents/__init__.py +0 -0
  105. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/agents/base.py +0 -0
  106. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/agents/tmux.py +0 -0
  107. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/cached_status.py +0 -0
  108. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/channels/__init__.py +0 -0
  109. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/channels/base.py +0 -0
  110. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/channels/email.py +0 -0
  111. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/channels/push.py +0 -0
  112. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/channels/quo.py +0 -0
  113. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/channels_cli.py +0 -0
  114. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/chrome_tabs.py +0 -0
  115. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/config.py +0 -0
  116. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/config_cli.py +0 -0
  117. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/council/__init__.py +0 -0
  118. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/council/cli.py +0 -0
  119. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/council/inbox.py +0 -0
  120. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/council/minutes.py +0 -0
  121. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/council/state.py +0 -0
  122. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/council/view.py +0 -0
  123. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/devices.py +0 -0
  124. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/diff_cli.py +0 -0
  125. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/doctor_voice.py +0 -0
  126. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/fetch.py +0 -0
  127. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/handoff/__init__.py +0 -0
  128. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/handoff/git_state.py +0 -0
  129. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/handoff/instructions.py +0 -0
  130. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/handoff/parser.py +0 -0
  131. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/handoff/renderer.py +0 -0
  132. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/handoff/schema.py +0 -0
  133. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/handoff_cli.py +0 -0
  134. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/history.py +0 -0
  135. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/hooks/__init__.py +0 -0
  136. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/hooks/agentwire-permission.sh +0 -0
  137. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/hooks/damage-control/__init__.py +0 -0
  138. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/hooks/damage-control/audit_logger.py +0 -0
  139. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/hooks/damage-control/bash-tool-damage-control.py +0 -0
  140. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/hooks/damage-control/edit-tool-damage-control.py +0 -0
  141. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/hooks/damage-control/mcp-tool-damage-control.py +0 -0
  142. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/hooks/damage-control/read-tool-damage-control.py +0 -0
  143. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/hooks/damage-control/rules/agentwire.yaml +0 -0
  144. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/hooks/damage-control/rules/aws.yaml +0 -0
  145. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/hooks/damage-control/rules/cloud-hosting.yaml +0 -0
  146. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/hooks/damage-control/rules/containers.yaml +0 -0
  147. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/hooks/damage-control/rules/control-plane.yaml +0 -0
  148. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/hooks/damage-control/rules/core.yaml +0 -0
  149. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/hooks/damage-control/rules/databases.yaml +0 -0
  150. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/hooks/damage-control/rules/firebase.yaml +0 -0
  151. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/hooks/damage-control/rules/gcp.yaml +0 -0
  152. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/hooks/damage-control/rules/git.yaml +0 -0
  153. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/hooks/damage-control/rules/gws.yaml +0 -0
  154. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/hooks/damage-control/rules/infrastructure.yaml +0 -0
  155. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/hooks/damage-control/rules/outbound.yaml +0 -0
  156. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/hooks/damage-control/rules/publish.yaml +0 -0
  157. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/hooks/damage-control/rules/remote.yaml +0 -0
  158. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/hooks/damage-control/write-tool-damage-control.py +0 -0
  159. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/hooks/queue-processor.sh +0 -0
  160. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/hooks_cli.py +0 -0
  161. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/listen.py +0 -0
  162. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/locking.py +0 -0
  163. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/machine_cli.py +0 -0
  164. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/mcp_channels.py +0 -0
  165. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/mcp_chrome.py +0 -0
  166. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/mcp_cli.py +0 -0
  167. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/mcp_council.py +0 -0
  168. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/mcp_desktop.py +0 -0
  169. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/mcp_handoff.py +0 -0
  170. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/mcp_history.py +0 -0
  171. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/mcp_listen.py +0 -0
  172. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/mcp_lock.py +0 -0
  173. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/mcp_machine.py +0 -0
  174. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/mcp_msg.py +0 -0
  175. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/mcp_notify.py +0 -0
  176. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/mcp_pane.py +0 -0
  177. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/mcp_projects.py +0 -0
  178. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/mcp_scheduler.py +0 -0
  179. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/mcp_scratchpad.py +0 -0
  180. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/mcp_server.py +0 -0
  181. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/mcp_services.py +0 -0
  182. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/mcp_status.py +0 -0
  183. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/mcp_tunnels.py +0 -0
  184. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/mcp_voice.py +0 -0
  185. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/mcp_wiki.py +0 -0
  186. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/msg_cli.py +0 -0
  187. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/network.py +0 -0
  188. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/notify_cli.py +0 -0
  189. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/onboarding.py +0 -0
  190. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/palette_cli.py +0 -0
  191. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/portal_cli.py +0 -0
  192. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/projects.py +0 -0
  193. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/prompt_router.py +0 -0
  194. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/prompts_cli.py +0 -0
  195. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/push_cli.py +0 -0
  196. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/push_store.py +0 -0
  197. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/repo_cli.py +0 -0
  198. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/research.py +0 -0
  199. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/roles/__init__.py +0 -0
  200. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/roles/agentwire.md +0 -0
  201. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/roles/anchor.md +0 -0
  202. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/roles/chatbot.md +0 -0
  203. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/roles/contributor.md +0 -0
  204. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/roles/correspondent.md +0 -0
  205. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/roles/council-brain.md +0 -0
  206. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/roles/council-conscience.md +0 -0
  207. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/roles/council-critic.md +0 -0
  208. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/roles/council-devils-advocate.md +0 -0
  209. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/roles/council-gut.md +0 -0
  210. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/roles/council-historian.md +0 -0
  211. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/roles/council-member.md +0 -0
  212. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/roles/council-orchestrator.md +0 -0
  213. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/roles/init.md +0 -0
  214. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/roles/notifications.md +0 -0
  215. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/roles/orchestrator.md +0 -0
  216. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/roles/reviewer.md +0 -0
  217. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/roles/soul.md +0 -0
  218. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/roles/task-runner.md +0 -0
  219. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/roles/voice.md +0 -0
  220. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/roles/worker.md +0 -0
  221. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/roles_cli.py +0 -0
  222. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/routes/__init__.py +0 -0
  223. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/routes/artifacts.py +0 -0
  224. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/routes/config.py +0 -0
  225. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/routes/council.py +0 -0
  226. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/routes/desktop.py +0 -0
  227. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/routes/history.py +0 -0
  228. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/routes/machines.py +0 -0
  229. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/routes/notify.py +0 -0
  230. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/routes/palette.py +0 -0
  231. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/routes/permission.py +0 -0
  232. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/routes/projects.py +0 -0
  233. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/routes/push.py +0 -0
  234. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/routes/safety.py +0 -0
  235. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/routes/scratchpad.py +0 -0
  236. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/routes/sessions.py +0 -0
  237. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/routes/sessions_admin.py +0 -0
  238. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/routes/voice.py +0 -0
  239. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/safety/__init__.py +0 -0
  240. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/safety/_core.py +0 -0
  241. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/safety_cli.py +0 -0
  242. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/safety_commands.py +0 -0
  243. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/scheduler/gates.py +0 -0
  244. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/scheduler/loop.py +0 -0
  245. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/scheduler/models.py +0 -0
  246. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/scheduler/schedule.py +0 -0
  247. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/scheduler/state.py +0 -0
  248. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/scratchpad.py +0 -0
  249. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/security.py +0 -0
  250. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/services.py +0 -0
  251. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/session_context.py +0 -0
  252. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/ssh.py +0 -0
  253. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/static/agentwire-splash-logo-layers--agentwire-text.png +0 -0
  254. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/static/agentwire-splash-logo-layers--echo-claw-fg.png +0 -0
  255. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/static/agentwire-splash-logo-layers--echo.png +0 -0
  256. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/static/agentwire-splash-logo-layers--telephone.png +0 -0
  257. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/static/agentwire-splash-logo-layers--tree.png +0 -0
  258. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/static/announcements.json +0 -0
  259. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/static/apple-touch-icon.png +0 -0
  260. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/static/css/desktop.css +0 -0
  261. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/static/css/mobile.css +0 -0
  262. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/static/favicon-32.png +0 -0
  263. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/static/favicon-64.png +0 -0
  264. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/static/icons/sessions/bear.webp +0 -0
  265. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/static/icons/sessions/cat.webp +0 -0
  266. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/static/icons/sessions/crown.webp +0 -0
  267. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/static/icons/sessions/custom/agentwire-portal.webp +0 -0
  268. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/static/icons/sessions/custom/agentwire-tts.webp +0 -0
  269. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/static/icons/sessions/custom/agentwire.webp +0 -0
  270. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/static/icons/sessions/deer.webp +0 -0
  271. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/static/icons/sessions/drone.webp +0 -0
  272. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/static/icons/sessions/eagle.webp +0 -0
  273. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/static/icons/sessions/fox.webp +0 -0
  274. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/static/icons/sessions/hawk.webp +0 -0
  275. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/static/icons/sessions/horse.webp +0 -0
  276. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/static/icons/sessions/lion.webp +0 -0
  277. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/static/icons/sessions/rabbit.webp +0 -0
  278. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/static/icons/sessions/robot.webp +0 -0
  279. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/static/icons/sessions/tiger.webp +0 -0
  280. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/static/icons/sessions/wolf.webp +0 -0
  281. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/static/img/icon-192.png +0 -0
  282. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/static/img/icon-512.png +0 -0
  283. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/static/js/.gitkeep +0 -0
  284. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/static/js/announcement-modal.js +0 -0
  285. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/static/js/api.js +0 -0
  286. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/static/js/artifact-window.js +0 -0
  287. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/static/js/card-terminal.js +0 -0
  288. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/static/js/collage.js +0 -0
  289. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/static/js/command-palette.js +0 -0
  290. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/static/js/council-window.js +0 -0
  291. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/static/js/dead-key-suppressor.js +0 -0
  292. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/static/js/desktop-manager.js +0 -0
  293. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/static/js/desktop.js +0 -0
  294. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/static/js/help-modal.js +0 -0
  295. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/static/js/icon-manager.js +0 -0
  296. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/static/js/lineage.js +0 -0
  297. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/static/js/mobile.js +0 -0
  298. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/static/js/notification-prefs.js +0 -0
  299. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/static/js/notifications-panel.js +0 -0
  300. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/static/js/ptt.js +0 -0
  301. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/static/js/push-client.js +0 -0
  302. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/static/js/review-window.js +0 -0
  303. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/static/js/safety-shared.js +0 -0
  304. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/static/js/safety-window.js +0 -0
  305. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/static/js/scratchpad.js +0 -0
  306. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/static/js/service-classification.js +0 -0
  307. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/static/js/session-hud-controller.js +0 -0
  308. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/static/js/session-hud-notices.js +0 -0
  309. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/static/js/session-hud-spawn.js +0 -0
  310. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/static/js/session-hud.js +0 -0
  311. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/static/js/session-id.js +0 -0
  312. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/static/js/session-window.js +0 -0
  313. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/static/js/shortcuts.js +0 -0
  314. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/static/js/sidebar/artifacts-section.js +0 -0
  315. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/static/js/sidebar/config-section.js +0 -0
  316. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/static/js/sidebar/council-section.js +0 -0
  317. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/static/js/sidebar/machines-section.js +0 -0
  318. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/static/js/sidebar/projects-section.js +0 -0
  319. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/static/js/sidebar/safety-section.js +0 -0
  320. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/static/js/sidebar/scheduler-section.js +0 -0
  321. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/static/js/sidebar/services-section.js +0 -0
  322. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/static/js/sidebar/sessions-section.js +0 -0
  323. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/static/js/sidebar.js +0 -0
  324. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/static/js/spawn-ghost.js +0 -0
  325. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/static/js/terminal-font-prefs.js +0 -0
  326. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/static/js/terminal-pane.js +0 -0
  327. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/static/js/tile-manager.js +0 -0
  328. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/static/js/toast.js +0 -0
  329. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/static/js/token-modal.js +0 -0
  330. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/static/js/topology-render.js +0 -0
  331. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/static/js/utils/ansi.js +0 -0
  332. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/static/js/utils/rich-text.js +0 -0
  333. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/static/js/utils/swipe.js +0 -0
  334. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/static/js/voice/autosend-prefs.js +0 -0
  335. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/static/js/voice/browser-stt.js +0 -0
  336. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/static/js/voice/browser-tts.js +0 -0
  337. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/static/js/voice/jargon.js +0 -0
  338. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/static/js/voice/prompt.js +0 -0
  339. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/static/js/winbox.bundle.min.js +0 -0
  340. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/static/js/workspace-window.js +0 -0
  341. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/static/manifest.webmanifest +0 -0
  342. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/static/service-worker.js +0 -0
  343. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/static/topology-harness.html +0 -0
  344. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/stt/__init__.py +0 -0
  345. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/stt/base.py +0 -0
  346. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/stt/cloud.py +0 -0
  347. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/stt/engine.py +0 -0
  348. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/stt/local.py +0 -0
  349. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/stt/server_backend.py +0 -0
  350. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/stt/stt_server.py +0 -0
  351. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/tabs_cli.py +0 -0
  352. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/templates/__init__.py +0 -0
  353. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/templates/base.html +0 -0
  354. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/templates/council/minutes.html.j2 +0 -0
  355. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/templates/desktop.html +0 -0
  356. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/templates/email_notification.html +0 -0
  357. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/templates/handoff/show-the-story.html.j2 +0 -0
  358. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/templates/handoff/theme.css.j2 +0 -0
  359. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/templates/mobile.html +0 -0
  360. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/templates/pair.html +0 -0
  361. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/templating.py +0 -0
  362. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/tooldefs/aws.yaml +0 -0
  363. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/tooldefs/docker.yaml +0 -0
  364. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/tooldefs/gcp.yaml +0 -0
  365. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/tooldefs/gh.yaml +0 -0
  366. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/tooldefs/git.yaml +0 -0
  367. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/tooldefs/gws.yaml +0 -0
  368. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/tooldefs/kubectl.yaml +0 -0
  369. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/tooldefs/npm.yaml +0 -0
  370. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/tooldefs/terraform.yaml +0 -0
  371. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/tooldefs/uv.yaml +0 -0
  372. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/tts/__init__.py +0 -0
  373. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/tts/audio.py +0 -0
  374. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/tts/base.py +0 -0
  375. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/tts/engines/__init__.py +0 -0
  376. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/tts/engines/chatterbox.py +0 -0
  377. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/tts/engines/kokoro.py +0 -0
  378. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/tts/engines/zonos.py +0 -0
  379. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/tts/kokoro_server.py +0 -0
  380. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/tts/local.py +0 -0
  381. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/tts/registry.py +0 -0
  382. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/tts_cli.py +0 -0
  383. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/tts_server.py +0 -0
  384. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/tunnels.py +0 -0
  385. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/tunnels_cli.py +0 -0
  386. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/usage_limit.py +0 -0
  387. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/utils/__init__.py +0 -0
  388. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/utils/chunker.py +0 -0
  389. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/utils/event_log.py +0 -0
  390. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/utils/file_io.py +0 -0
  391. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/utils/paths.py +0 -0
  392. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/utils/speech.py +0 -0
  393. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/utils/subprocess.py +0 -0
  394. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/validation.py +0 -0
  395. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/voice_status.py +0 -0
  396. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/wiki.py +0 -0
  397. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/wiki_audit.py +0 -0
  398. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/agentwire/wiki_cli.py +0 -0
  399. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/docs/decisions/obsidian-second-brain.md +0 -0
  400. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/docs/design/session-card-fields.md +0 -0
  401. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/docs/design/session-card-recommendation.md +0 -0
  402. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/docs/logo.png +0 -0
  403. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/docs/wiki/architecture.md +0 -0
  404. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/docs/wiki/briefing-mode.md +0 -0
  405. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/docs/wiki/communication/channels.md +0 -0
  406. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/docs/wiki/communication/hammerspoon.md +0 -0
  407. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/docs/wiki/communication/handoff.md +0 -0
  408. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/docs/wiki/concepts.md +0 -0
  409. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/docs/wiki/council.md +0 -0
  410. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/docs/wiki/deployment/remote-access.md +0 -0
  411. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/docs/wiki/deployment/remote-machines.md +0 -0
  412. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/docs/wiki/glossary.md +0 -0
  413. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/docs/wiki/integrations/gws-google-workspace-cli.md +0 -0
  414. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/docs/wiki/internals/damage-control.md +0 -0
  415. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/docs/wiki/internals/parallel-refactor.md +0 -0
  416. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/docs/wiki/internals/portal.md +0 -0
  417. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/docs/wiki/internals/session-topology.md +0 -0
  418. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/docs/wiki/internals/troubleshooting.md +0 -0
  419. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/docs/wiki/internals/window-collage.md +0 -0
  420. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/docs/wiki/research/briefing-mode-feasibility.md +0 -0
  421. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/docs/wiki/research/orchestration-transport-alternatives.md +0 -0
  422. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/docs/wiki/security/damage-control-hardening.md +0 -0
  423. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/docs/wiki/security/pip-audit.md +0 -0
  424. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/docs/wiki/security/remote-access-hardening.md +0 -0
  425. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/docs/wiki/security/secrets.md +0 -0
  426. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/docs/wiki/services.md +0 -0
  427. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/docs/wiki/sessions/claude-code-auto-mode.md +0 -0
  428. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/docs/wiki/sessions/prompt-routing.md +0 -0
  429. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/docs/wiki/sessions/window-sizing.md +0 -0
  430. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/docs/wiki/usage-limit-recovery.md +0 -0
  431. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/docs/wiki/voice/shim-contract.md +0 -0
  432. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/docs/wiki/voice/stt-cloud.md +0 -0
  433. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/docs/wiki/voice/stt-self-hosted.md +0 -0
  434. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/docs/wiki/voice/tts-self-hosted.md +0 -0
  435. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/tests/e2e/test_portal_ui.py +0 -0
  436. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/tests/fixtures/sample_agentwire.yml +0 -0
  437. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/tests/fixtures/sample_config.yaml +0 -0
  438. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/tests/fixtures/sample_scheduler.yaml +0 -0
  439. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/tests/integration/test_council_portal.py +0 -0
  440. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/tests/integration/test_scheduler_board.py +0 -0
  441. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/tests/integration/test_server_websockets.py +0 -0
  442. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/tests/unit/test_announcements.py +0 -0
  443. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/tests/unit/test_channels.py +0 -0
  444. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/tests/unit/test_chrome_tabs.py +0 -0
  445. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/tests/unit/test_cli_output.py +0 -0
  446. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/tests/unit/test_cli_smoke.py +0 -0
  447. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/tests/unit/test_config.py +0 -0
  448. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/tests/unit/test_config_cli.py +0 -0
  449. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/tests/unit/test_control_plane_protection.py +0 -0
  450. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/tests/unit/test_core_created_by_rooting.py +0 -0
  451. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/tests/unit/test_council_cli.py +0 -0
  452. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/tests/unit/test_council_inbox.py +0 -0
  453. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/tests/unit/test_council_minutes.py +0 -0
  454. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/tests/unit/test_council_state.py +0 -0
  455. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/tests/unit/test_council_view.py +0 -0
  456. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/tests/unit/test_damage_control_bypass.py +0 -0
  457. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/tests/unit/test_damage_control_hooks.py +0 -0
  458. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/tests/unit/test_damage_control_sync.py +0 -0
  459. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/tests/unit/test_dangling_worktrees.py +0 -0
  460. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/tests/unit/test_devices.py +0 -0
  461. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/tests/unit/test_diff_cli.py +0 -0
  462. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/tests/unit/test_doctor_task_migration.py +0 -0
  463. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/tests/unit/test_doctor_voice.py +0 -0
  464. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/tests/unit/test_event_log.py +0 -0
  465. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/tests/unit/test_file_io.py +0 -0
  466. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/tests/unit/test_guarded_launch_command.py +0 -0
  467. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/tests/unit/test_handoff_git_state.py +0 -0
  468. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/tests/unit/test_handoff_instructions.py +0 -0
  469. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/tests/unit/test_handoff_parser.py +0 -0
  470. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/tests/unit/test_handoff_renderer.py +0 -0
  471. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/tests/unit/test_history.py +0 -0
  472. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/tests/unit/test_hooks_install.py +0 -0
  473. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/tests/unit/test_idle_nag.py +0 -0
  474. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/tests/unit/test_init_command.py +0 -0
  475. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/tests/unit/test_install_parity.py +0 -0
  476. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/tests/unit/test_limits_tick_isolation.py +0 -0
  477. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/tests/unit/test_locking.py +0 -0
  478. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/tests/unit/test_msg_cli.py +0 -0
  479. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/tests/unit/test_notify_cli.py +0 -0
  480. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/tests/unit/test_onboarding_reinit.py +0 -0
  481. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/tests/unit/test_palette_cli.py +0 -0
  482. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/tests/unit/test_pip_environment.py +0 -0
  483. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/tests/unit/test_posture_default.py +0 -0
  484. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/tests/unit/test_projects_registry.py +0 -0
  485. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/tests/unit/test_push.py +0 -0
  486. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/tests/unit/test_rebuild_guard.py +0 -0
  487. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/tests/unit/test_repo_cli.py +0 -0
  488. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/tests/unit/test_rich_text_js.py +0 -0
  489. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/tests/unit/test_roles.py +0 -0
  490. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/tests/unit/test_routes_snapshot.py +0 -0
  491. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/tests/unit/test_safety_commands.py +0 -0
  492. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/tests/unit/test_safety_disabled_rules.py +0 -0
  493. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/tests/unit/test_safety_escape_hatch.py +0 -0
  494. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/tests/unit/test_safety_heal.py +0 -0
  495. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/tests/unit/test_safety_kill_switch.py +0 -0
  496. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/tests/unit/test_scheduler_parsing.py +0 -0
  497. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/tests/unit/test_scratchpad.py +0 -0
  498. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/tests/unit/test_security.py +0 -0
  499. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/tests/unit/test_server_async.py +0 -0
  500. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/tests/unit/test_server_pure.py +0 -0
  501. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/tests/unit/test_services.py +0 -0
  502. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/tests/unit/test_session_context.py +0 -0
  503. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/tests/unit/test_session_created_by_env.py +0 -0
  504. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/tests/unit/test_shared_dir_guard.py +0 -0
  505. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/tests/unit/test_shim_selfheal.py +0 -0
  506. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/tests/unit/test_skill_install.py +0 -0
  507. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/tests/unit/test_speech_tags.py +0 -0
  508. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/tests/unit/test_ssh.py +0 -0
  509. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/tests/unit/test_stt_backend.py +0 -0
  510. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/tests/unit/test_stt_cloud.py +0 -0
  511. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/tests/unit/test_stt_engine.py +0 -0
  512. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/tests/unit/test_task_cli.py +0 -0
  513. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/tests/unit/test_tasks.py +0 -0
  514. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/tests/unit/test_tasks_cli.py +0 -0
  515. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/tests/unit/test_templating.py +0 -0
  516. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/tests/unit/test_terminal_resize.py +0 -0
  517. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/tests/unit/test_tmux_template.py +0 -0
  518. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/tests/unit/test_tts_engine_resolution.py +0 -0
  519. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/tests/unit/test_tts_local.py +0 -0
  520. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/tests/unit/test_tunnels_probe.py +0 -0
  521. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/tests/unit/test_unattended_env_isolation.py +0 -0
  522. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/tests/unit/test_usage_limit.py +0 -0
  523. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/tests/unit/test_validation.py +0 -0
  524. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/tests/unit/test_voice_status.py +0 -0
  525. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/tests/unit/test_wiki.py +0 -0
  526. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/tests/unit/test_wiki_audit.py +0 -0
  527. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/tests/unit/test_window_cycling_binding.py +0 -0
  528. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/tests/unit/test_worktree.py +0 -0
  529. {agentwire_dev-1.65.3 → agentwire_dev-1.67.0}/tests/unit/test_worktree_branch_cleanup.py +0 -0
  530. {agentwire_dev-1.65.3 → agentwire_dev-1.67.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.3
3
+ Version: 1.67.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
@@ -231,7 +231,7 @@ Requires-Dist: fastapi>=0.104.0
231
231
  Requires-Dist: jinja2>=3.1.0
232
232
  Requires-Dist: kokoro-onnx>=0.4.9; python_version < '3.14'
233
233
  Requires-Dist: markdown>=3.5
234
- Requires-Dist: mcp>=1.2.0
234
+ Requires-Dist: mcp<2,>=1.2.0
235
235
  Requires-Dist: pydantic>=2.0.0
236
236
  Requires-Dist: python-dotenv>=1.2.2
237
237
  Requires-Dist: python-multipart>=0.0.6
@@ -1,3 +1,3 @@
1
1
  """AgentWire - Multi-session voice web interface for AI coding agents."""
2
2
 
3
- __version__ = "1.65.3"
3
+ __version__ = "1.67.0"
@@ -37,7 +37,6 @@ from .core import ( # noqa: E402,F401 # E402: must follow load_dotenv(); F401:
37
37
  _parse_session_target,
38
38
  _portal_auth_headers,
39
39
  _post_desktop_notification,
40
- _record_session_creator,
41
40
  _resolve_posture_from_args,
42
41
  _run_remote,
43
42
  _set_session_name_env,
@@ -58,6 +57,7 @@ from .core import ( # noqa: E402,F401 # E402: must follow load_dotenv(); F401:
58
57
  load_config,
59
58
  load_session_metadata,
60
59
  parse_env_args,
60
+ record_session_launch,
61
61
  store_session_metadata,
62
62
  tmux_session_exists,
63
63
  tmux_session_has_agent,
@@ -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()
@@ -187,25 +187,38 @@ def wait_for_completion_signal(
187
187
  session: str,
188
188
  poll_interval: float = 10.0,
189
189
  summary_path: Path | None = None,
190
+ max_duration: int = 0,
190
191
  ) -> dict:
191
192
  """Wait for task completion by polling the summary file directly.
192
193
 
193
194
  Exits when:
194
195
  1. Summary file appears (task completed normally)
195
196
  2. Session dies (agent crashed, tmux killed)
197
+ 3. ``max_duration`` elapses, when the task sets one
196
198
 
197
- There is no wall-clock timeout. Tasks run until one of these conditions.
199
+ Completion is otherwise agent-driven: the idle hook fires, the agent writes
200
+ a summary, and this returns. An agent that never goes idle never produces
201
+ either exit — wedged on an unrecognized dialog, or blocked inside a tool
202
+ call — and before ``max_duration`` existed the wait was unbounded, so that
203
+ read as a silent multi-hour hang whose only visible end was the scheduler's
204
+ 4h process-group watchdog (#867).
205
+
206
+ ``max_duration`` is a per-attempt wall clock, not an idle timer: it can't
207
+ tell a wedged agent from a slow one, so a task that legitimately runs long
208
+ should set it high or leave it at 0 rather than get killed mid-work.
198
209
 
199
210
  Args:
200
211
  session: tmux session name
201
212
  poll_interval: Seconds between checks
202
213
  summary_path: Path to the summary .md file the agent will write
214
+ max_duration: Seconds before giving up (0 = unbounded)
203
215
 
204
216
  Returns:
205
217
  Dict with 'status', 'summary', 'summary_file' keys
206
218
 
207
219
  Raises:
208
- CompletionTimeout: If session dies before task completed
220
+ CompletionTimeout: If the session dies, or max_duration elapses, before
221
+ the task completed. The message names which.
209
222
  """
210
223
  # Build glob pattern for fuzzy summary detection (agents sometimes
211
224
  # invent their own timestamp instead of using the provided filename).
@@ -217,6 +230,8 @@ def wait_for_completion_signal(
217
230
  prefix = stem[:-19] if len(stem) > 19 else stem
218
231
  summary_glob = f"{prefix}*.md"
219
232
 
233
+ started = time.time()
234
+
220
235
  while True:
221
236
  # Primary: check if the agent has written the summary file AND
222
237
  # the hook has deleted the context file (signals cleanup complete).
@@ -274,6 +289,14 @@ def wait_for_completion_signal(
274
289
  f"Session '{session}' died or agent exited before task completed"
275
290
  )
276
291
 
292
+ if max_duration > 0:
293
+ elapsed = time.time() - started
294
+ if elapsed >= max_duration:
295
+ raise CompletionTimeout(
296
+ f"Task exceeded max_duration ({max_duration}s) after "
297
+ f"{int(elapsed)}s — the agent never signalled completion"
298
+ )
299
+
277
300
  time.sleep(poll_interval)
278
301
 
279
302