agentwire-dev 1.54.0__tar.gz → 1.56.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 (476) hide show
  1. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/PKG-INFO +1 -1
  2. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/__init__.py +1 -1
  3. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/__main__.py +35 -0
  4. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/channels_cli.py +11 -0
  5. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/config.py +13 -2
  6. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/council/cli.py +126 -8
  7. agentwire_dev-1.56.0/agentwire/council/minutes.py +174 -0
  8. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/inbox.py +59 -7
  9. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/mcp_council.py +51 -4
  10. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/mcp_msg.py +20 -6
  11. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/mcp_worktree.py +33 -7
  12. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/msg_cli.py +35 -8
  13. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/pane_manager.py +8 -1
  14. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/project_config.py +51 -0
  15. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/prompt_router.py +13 -7
  16. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/roles/council-orchestrator.md +8 -0
  17. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/routes/artifacts.py +42 -0
  18. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/scheduler/schedule.py +12 -2
  19. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/session_cli.py +106 -51
  20. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/session_ready.py +239 -94
  21. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/static/css/desktop.css +23 -0
  22. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/static/js/artifact-window.js +61 -0
  23. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/static/js/desktop.js +22 -29
  24. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/static/js/shortcuts.js +1 -1
  25. agentwire_dev-1.56.0/agentwire/templates/council/minutes.html.j2 +193 -0
  26. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/worktree.py +0 -17
  27. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/worktree_registry.py +1 -1
  28. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/docs/wiki/council.md +32 -2
  29. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/docs/wiki/sessions/messaging.md +66 -24
  30. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/docs/wiki/sessions/worktree-sessions.md +21 -5
  31. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/tests/conftest.py +16 -0
  32. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/tests/integration/test_send_verified_tmux.py +89 -28
  33. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/tests/integration/test_worktree_cmd.py +166 -7
  34. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/tests/unit/test_cli_commands.py +78 -0
  35. agentwire_dev-1.56.0/tests/unit/test_council_minutes.py +305 -0
  36. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/tests/unit/test_inbox.py +96 -0
  37. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/tests/unit/test_mcp_tools_args.py +63 -0
  38. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/tests/unit/test_msg_cli.py +96 -2
  39. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/tests/unit/test_portal_api.py +62 -0
  40. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/tests/unit/test_project_config.py +59 -0
  41. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/tests/unit/test_prompt_router.py +34 -5
  42. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/tests/unit/test_routes_snapshot.py +2 -0
  43. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/tests/unit/test_scheduler.py +15 -0
  44. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/tests/unit/test_session_ready.py +306 -60
  45. agentwire_dev-1.56.0/tests/unit/test_window_cycling_binding.py +65 -0
  46. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/tests/unit/test_worktree.py +0 -26
  47. agentwire_dev-1.56.0/tests/unit/test_worktree_layout.py +89 -0
  48. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/.agentwire.yml.example +0 -0
  49. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/.claude/commands/handoff.md +0 -0
  50. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/.claude/skills/wiki/SKILL.md +0 -0
  51. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/.github/FUNDING.yml +0 -0
  52. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
  53. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
  54. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/.github/ISSUE_TEMPLATE/question.md +0 -0
  55. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
  56. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/.github/workflows/pytest.yml +0 -0
  57. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/.github/workflows/ruff.yml +0 -0
  58. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/.github/workflows/security.yml +0 -0
  59. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/.github/workflows/tts-smoke.yml +0 -0
  60. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/.gitignore +0 -0
  61. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/AGENTS.md +0 -0
  62. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/CODE_OF_CONDUCT.md +0 -0
  63. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/CONTRIBUTING.md +0 -0
  64. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/Dockerfile.local +0 -0
  65. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/LICENSE +0 -0
  66. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/README.md +0 -0
  67. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/RELEASING.md +0 -0
  68. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/SECURITY.md +0 -0
  69. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/SPONSORS.md +0 -0
  70. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/agents/__init__.py +0 -0
  71. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/agents/base.py +0 -0
  72. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/agents/tmux.py +0 -0
  73. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/cached_status.py +0 -0
  74. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/channels/__init__.py +0 -0
  75. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/channels/base.py +0 -0
  76. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/channels/email.py +0 -0
  77. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/channels/push.py +0 -0
  78. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/channels/quo.py +0 -0
  79. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/completion.py +0 -0
  80. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/config_cli.py +0 -0
  81. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/core.py +0 -0
  82. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/council/__init__.py +0 -0
  83. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/council/inbox.py +0 -0
  84. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/council/state.py +0 -0
  85. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/council/view.py +0 -0
  86. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/devices.py +0 -0
  87. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/diff_cli.py +0 -0
  88. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/doctor_cli.py +0 -0
  89. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/doctor_voice.py +0 -0
  90. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/ensure_cli.py +0 -0
  91. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/fetch.py +0 -0
  92. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/handoff/__init__.py +0 -0
  93. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/handoff/git_state.py +0 -0
  94. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/handoff/instructions.py +0 -0
  95. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/handoff/parser.py +0 -0
  96. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/handoff/renderer.py +0 -0
  97. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/handoff/schema.py +0 -0
  98. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/handoff_cli.py +0 -0
  99. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/history.py +0 -0
  100. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/history_cli.py +0 -0
  101. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/hooks/__init__.py +0 -0
  102. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/hooks/agentwire-permission.sh +0 -0
  103. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/hooks/damage-control/__init__.py +0 -0
  104. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/hooks/damage-control/audit_logger.py +0 -0
  105. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/hooks/damage-control/bash-tool-damage-control.py +0 -0
  106. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/hooks/damage-control/edit-tool-damage-control.py +0 -0
  107. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/hooks/damage-control/mcp-tool-damage-control.py +0 -0
  108. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/hooks/damage-control/read-tool-damage-control.py +0 -0
  109. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/hooks/damage-control/rules/agentwire.yaml +0 -0
  110. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/hooks/damage-control/rules/aws.yaml +0 -0
  111. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/hooks/damage-control/rules/cloud-hosting.yaml +0 -0
  112. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/hooks/damage-control/rules/containers.yaml +0 -0
  113. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/hooks/damage-control/rules/control-plane.yaml +0 -0
  114. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/hooks/damage-control/rules/core.yaml +0 -0
  115. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/hooks/damage-control/rules/databases.yaml +0 -0
  116. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/hooks/damage-control/rules/firebase.yaml +0 -0
  117. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/hooks/damage-control/rules/gcp.yaml +0 -0
  118. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/hooks/damage-control/rules/git.yaml +0 -0
  119. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/hooks/damage-control/rules/gws.yaml +0 -0
  120. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/hooks/damage-control/rules/infrastructure.yaml +0 -0
  121. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/hooks/damage-control/rules/outbound.yaml +0 -0
  122. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/hooks/damage-control/rules/publish.yaml +0 -0
  123. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/hooks/damage-control/rules/remote.yaml +0 -0
  124. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/hooks/damage-control/write-tool-damage-control.py +0 -0
  125. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/hooks/idle-handler.sh +0 -0
  126. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/hooks/queue-processor.sh +0 -0
  127. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/hooks_cli.py +0 -0
  128. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/limits_cli.py +0 -0
  129. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/listen.py +0 -0
  130. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/locking.py +0 -0
  131. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/machine_cli.py +0 -0
  132. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/mcp_channels.py +0 -0
  133. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/mcp_cli.py +0 -0
  134. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/mcp_core.py +0 -0
  135. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/mcp_desktop.py +0 -0
  136. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/mcp_handoff.py +0 -0
  137. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/mcp_history.py +0 -0
  138. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/mcp_listen.py +0 -0
  139. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/mcp_lock.py +0 -0
  140. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/mcp_machine.py +0 -0
  141. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/mcp_notify.py +0 -0
  142. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/mcp_pane.py +0 -0
  143. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/mcp_projects.py +0 -0
  144. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/mcp_scheduler.py +0 -0
  145. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/mcp_scratchpad.py +0 -0
  146. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/mcp_server.py +0 -0
  147. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/mcp_services.py +0 -0
  148. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/mcp_session.py +0 -0
  149. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/mcp_status.py +0 -0
  150. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/mcp_task.py +0 -0
  151. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/mcp_tunnels.py +0 -0
  152. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/mcp_voice.py +0 -0
  153. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/mcp_voiceclone.py +0 -0
  154. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/mcp_wiki.py +0 -0
  155. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/network.py +0 -0
  156. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/notify_cli.py +0 -0
  157. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/onboarding.py +0 -0
  158. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/palette_cli.py +0 -0
  159. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/pane_cli.py +0 -0
  160. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/portal_cli.py +0 -0
  161. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/projects.py +0 -0
  162. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/prompts_cli.py +0 -0
  163. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/push_cli.py +0 -0
  164. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/push_store.py +0 -0
  165. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/repo_cli.py +0 -0
  166. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/research.py +0 -0
  167. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/roles/__init__.py +0 -0
  168. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/roles/agentwire.md +0 -0
  169. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/roles/anchor.md +0 -0
  170. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/roles/chatbot.md +0 -0
  171. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/roles/contributor.md +0 -0
  172. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/roles/correspondent.md +0 -0
  173. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/roles/council-brain.md +0 -0
  174. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/roles/council-conscience.md +0 -0
  175. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/roles/council-critic.md +0 -0
  176. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/roles/council-devils-advocate.md +0 -0
  177. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/roles/council-gut.md +0 -0
  178. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/roles/council-historian.md +0 -0
  179. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/roles/council-member.md +0 -0
  180. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/roles/init.md +0 -0
  181. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/roles/notifications.md +0 -0
  182. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/roles/orchestrator.md +0 -0
  183. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/roles/soul.md +0 -0
  184. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/roles/task-runner.md +0 -0
  185. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/roles/voice.md +0 -0
  186. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/roles/worker.md +0 -0
  187. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/roles/worktree-session.md +0 -0
  188. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/roles_cli.py +0 -0
  189. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/routes/__init__.py +0 -0
  190. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/routes/config.py +0 -0
  191. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/routes/council.py +0 -0
  192. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/routes/desktop.py +0 -0
  193. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/routes/history.py +0 -0
  194. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/routes/machines.py +0 -0
  195. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/routes/notify.py +0 -0
  196. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/routes/palette.py +0 -0
  197. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/routes/permission.py +0 -0
  198. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/routes/projects.py +0 -0
  199. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/routes/push.py +0 -0
  200. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/routes/safety.py +0 -0
  201. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/routes/scheduler.py +0 -0
  202. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/routes/scratchpad.py +0 -0
  203. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/routes/sessions.py +0 -0
  204. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/routes/sessions_admin.py +0 -0
  205. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/routes/voice.py +0 -0
  206. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/safety/__init__.py +0 -0
  207. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/safety/_core.py +0 -0
  208. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/safety_cli.py +0 -0
  209. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/safety_commands.py +0 -0
  210. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/scheduler/__init__.py +0 -0
  211. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/scheduler/dispatch.py +0 -0
  212. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/scheduler/gates.py +0 -0
  213. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/scheduler/loop.py +0 -0
  214. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/scheduler/models.py +0 -0
  215. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/scheduler/report.py +0 -0
  216. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/scheduler/state.py +0 -0
  217. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/scheduler_cli.py +0 -0
  218. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/scratchpad.py +0 -0
  219. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/security.py +0 -0
  220. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/send_cli.py +0 -0
  221. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/server.py +0 -0
  222. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/services.py +0 -0
  223. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/session_context.py +0 -0
  224. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/ssh.py +0 -0
  225. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/static/agentwire-splash-logo-layers--agentwire-text.png +0 -0
  226. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/static/agentwire-splash-logo-layers--echo-claw-fg.png +0 -0
  227. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/static/agentwire-splash-logo-layers--echo.png +0 -0
  228. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/static/agentwire-splash-logo-layers--telephone.png +0 -0
  229. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/static/agentwire-splash-logo-layers--tree.png +0 -0
  230. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/static/announcements.json +0 -0
  231. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/static/apple-touch-icon.png +0 -0
  232. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/static/css/mobile.css +0 -0
  233. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/static/favicon-32.png +0 -0
  234. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/static/favicon-64.png +0 -0
  235. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/static/icons/sessions/bear.webp +0 -0
  236. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/static/icons/sessions/cat.webp +0 -0
  237. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/static/icons/sessions/crown.webp +0 -0
  238. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/static/icons/sessions/custom/agentwire-portal.webp +0 -0
  239. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/static/icons/sessions/custom/agentwire-tts.webp +0 -0
  240. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/static/icons/sessions/custom/agentwire.webp +0 -0
  241. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/static/icons/sessions/deer.webp +0 -0
  242. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/static/icons/sessions/drone.webp +0 -0
  243. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/static/icons/sessions/eagle.webp +0 -0
  244. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/static/icons/sessions/fox.webp +0 -0
  245. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/static/icons/sessions/hawk.webp +0 -0
  246. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/static/icons/sessions/horse.webp +0 -0
  247. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/static/icons/sessions/lion.webp +0 -0
  248. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/static/icons/sessions/rabbit.webp +0 -0
  249. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/static/icons/sessions/robot.webp +0 -0
  250. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/static/icons/sessions/tiger.webp +0 -0
  251. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/static/icons/sessions/wolf.webp +0 -0
  252. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/static/img/icon-192.png +0 -0
  253. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/static/img/icon-512.png +0 -0
  254. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/static/js/.gitkeep +0 -0
  255. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/static/js/announcement-modal.js +0 -0
  256. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/static/js/api.js +0 -0
  257. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/static/js/collage.js +0 -0
  258. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/static/js/command-palette.js +0 -0
  259. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/static/js/council-window.js +0 -0
  260. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/static/js/dead-key-suppressor.js +0 -0
  261. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/static/js/desktop-manager.js +0 -0
  262. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/static/js/help-modal.js +0 -0
  263. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/static/js/icon-manager.js +0 -0
  264. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/static/js/mobile.js +0 -0
  265. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/static/js/notification-prefs.js +0 -0
  266. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/static/js/notifications-panel.js +0 -0
  267. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/static/js/ptt.js +0 -0
  268. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/static/js/push-client.js +0 -0
  269. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/static/js/review-window.js +0 -0
  270. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/static/js/safety-shared.js +0 -0
  271. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/static/js/safety-window.js +0 -0
  272. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/static/js/scratchpad.js +0 -0
  273. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/static/js/service-classification.js +0 -0
  274. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/static/js/session-id.js +0 -0
  275. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/static/js/session-window.js +0 -0
  276. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/static/js/sidebar/artifacts-section.js +0 -0
  277. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/static/js/sidebar/config-section.js +0 -0
  278. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/static/js/sidebar/council-section.js +0 -0
  279. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/static/js/sidebar/machines-section.js +0 -0
  280. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/static/js/sidebar/projects-section.js +0 -0
  281. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/static/js/sidebar/safety-section.js +0 -0
  282. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/static/js/sidebar/scheduler-section.js +0 -0
  283. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/static/js/sidebar/services-section.js +0 -0
  284. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/static/js/sidebar/sessions-section.js +0 -0
  285. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/static/js/sidebar.js +0 -0
  286. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/static/js/terminal-font-prefs.js +0 -0
  287. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/static/js/tile-manager.js +0 -0
  288. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/static/js/toast.js +0 -0
  289. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/static/js/token-modal.js +0 -0
  290. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/static/js/utils/ansi.js +0 -0
  291. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/static/js/utils/swipe.js +0 -0
  292. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/static/js/voice/autosend-prefs.js +0 -0
  293. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/static/js/voice/browser-stt.js +0 -0
  294. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/static/js/voice/browser-tts.js +0 -0
  295. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/static/js/voice/jargon.js +0 -0
  296. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/static/js/voice/prompt.js +0 -0
  297. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/static/js/winbox.bundle.min.js +0 -0
  298. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/static/manifest.webmanifest +0 -0
  299. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/static/service-worker.js +0 -0
  300. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/stt/__init__.py +0 -0
  301. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/stt/base.py +0 -0
  302. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/stt/cloud.py +0 -0
  303. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/stt/engine.py +0 -0
  304. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/stt/local.py +0 -0
  305. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/stt/server_backend.py +0 -0
  306. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/stt/stt_server.py +0 -0
  307. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/system_cli.py +0 -0
  308. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/tasks.py +0 -0
  309. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/templates/__init__.py +0 -0
  310. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/templates/base.html +0 -0
  311. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/templates/desktop.html +0 -0
  312. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/templates/email_notification.html +0 -0
  313. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/templates/handoff/show-the-story.html.j2 +0 -0
  314. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/templates/handoff/theme.css.j2 +0 -0
  315. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/templates/mobile.html +0 -0
  316. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/templates/pair.html +0 -0
  317. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/templates/tmux.conf +0 -0
  318. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/templating.py +0 -0
  319. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/tooldefs/aws.yaml +0 -0
  320. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/tooldefs/docker.yaml +0 -0
  321. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/tooldefs/gcp.yaml +0 -0
  322. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/tooldefs/gh.yaml +0 -0
  323. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/tooldefs/git.yaml +0 -0
  324. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/tooldefs/gws.yaml +0 -0
  325. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/tooldefs/kubectl.yaml +0 -0
  326. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/tooldefs/npm.yaml +0 -0
  327. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/tooldefs/terraform.yaml +0 -0
  328. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/tooldefs/uv.yaml +0 -0
  329. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/tts/__init__.py +0 -0
  330. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/tts/audio.py +0 -0
  331. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/tts/base.py +0 -0
  332. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/tts/engines/__init__.py +0 -0
  333. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/tts/engines/chatterbox.py +0 -0
  334. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/tts/engines/kokoro.py +0 -0
  335. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/tts/engines/zonos.py +0 -0
  336. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/tts/kokoro_server.py +0 -0
  337. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/tts/local.py +0 -0
  338. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/tts/registry.py +0 -0
  339. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/tts_cli.py +0 -0
  340. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/tts_server.py +0 -0
  341. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/tunnels.py +0 -0
  342. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/tunnels_cli.py +0 -0
  343. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/usage_limit.py +0 -0
  344. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/utils/__init__.py +0 -0
  345. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/utils/chunker.py +0 -0
  346. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/utils/event_log.py +0 -0
  347. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/utils/file_io.py +0 -0
  348. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/utils/paths.py +0 -0
  349. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/utils/speech.py +0 -0
  350. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/utils/subprocess.py +0 -0
  351. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/validation.py +0 -0
  352. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/voice_status.py +0 -0
  353. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/voiceclone.py +0 -0
  354. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/wiki.py +0 -0
  355. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/wiki_audit.py +0 -0
  356. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/agentwire/wiki_cli.py +0 -0
  357. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/docs/decisions/obsidian-second-brain.md +0 -0
  358. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/docs/logo.png +0 -0
  359. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/docs/wiki/INDEX.md +0 -0
  360. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/docs/wiki/architecture.md +0 -0
  361. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/docs/wiki/briefing-mode.md +0 -0
  362. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/docs/wiki/communication/channels.md +0 -0
  363. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/docs/wiki/communication/hammerspoon.md +0 -0
  364. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/docs/wiki/communication/handoff.md +0 -0
  365. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/docs/wiki/concepts.md +0 -0
  366. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/docs/wiki/deployment/remote-access.md +0 -0
  367. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/docs/wiki/deployment/remote-machines.md +0 -0
  368. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/docs/wiki/glossary.md +0 -0
  369. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/docs/wiki/integrations/gws-google-workspace-cli.md +0 -0
  370. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/docs/wiki/internals/damage-control.md +0 -0
  371. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/docs/wiki/internals/parallel-refactor.md +0 -0
  372. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/docs/wiki/internals/portal.md +0 -0
  373. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/docs/wiki/internals/shell-escaping.md +0 -0
  374. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/docs/wiki/internals/troubleshooting.md +0 -0
  375. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/docs/wiki/internals/window-collage.md +0 -0
  376. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/docs/wiki/quickstart.md +0 -0
  377. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/docs/wiki/research/briefing-mode-feasibility.md +0 -0
  378. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/docs/wiki/research/orchestration-transport-alternatives.md +0 -0
  379. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/docs/wiki/scheduling/scheduled-workloads.md +0 -0
  380. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/docs/wiki/security/damage-control-hardening.md +0 -0
  381. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/docs/wiki/security/pip-audit.md +0 -0
  382. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/docs/wiki/security/remote-access-hardening.md +0 -0
  383. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/docs/wiki/security/secrets.md +0 -0
  384. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/docs/wiki/services.md +0 -0
  385. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/docs/wiki/sessions/claude-code-auto-mode.md +0 -0
  386. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/docs/wiki/sessions/pi.md +0 -0
  387. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/docs/wiki/sessions/prompt-routing.md +0 -0
  388. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/docs/wiki/sessions/window-sizing.md +0 -0
  389. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/docs/wiki/usage-limit-recovery.md +0 -0
  390. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/docs/wiki/voice/shim-contract.md +0 -0
  391. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/docs/wiki/voice/stt-cloud.md +0 -0
  392. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/docs/wiki/voice/stt-self-hosted.md +0 -0
  393. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/docs/wiki/voice/tts-self-hosted.md +0 -0
  394. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/pyproject.toml +0 -0
  395. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/tests/e2e/test_portal_ui.py +0 -0
  396. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/tests/fixtures/sample_agentwire.yml +0 -0
  397. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/tests/fixtures/sample_config.yaml +0 -0
  398. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/tests/fixtures/sample_scheduler.yaml +0 -0
  399. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/tests/integration/test_council_portal.py +0 -0
  400. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/tests/integration/test_scheduler_board.py +0 -0
  401. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/tests/integration/test_server_websockets.py +0 -0
  402. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/tests/unit/test_announcements.py +0 -0
  403. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/tests/unit/test_build_agent_command.py +0 -0
  404. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/tests/unit/test_channels.py +0 -0
  405. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/tests/unit/test_cli_output.py +0 -0
  406. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/tests/unit/test_cli_smoke.py +0 -0
  407. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/tests/unit/test_config.py +0 -0
  408. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/tests/unit/test_config_cli.py +0 -0
  409. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/tests/unit/test_control_plane_protection.py +0 -0
  410. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/tests/unit/test_council_cli.py +0 -0
  411. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/tests/unit/test_council_inbox.py +0 -0
  412. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/tests/unit/test_council_state.py +0 -0
  413. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/tests/unit/test_council_view.py +0 -0
  414. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/tests/unit/test_damage_control_bypass.py +0 -0
  415. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/tests/unit/test_damage_control_hooks.py +0 -0
  416. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/tests/unit/test_damage_control_sync.py +0 -0
  417. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/tests/unit/test_devices.py +0 -0
  418. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/tests/unit/test_diff_cli.py +0 -0
  419. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/tests/unit/test_doctor_voice.py +0 -0
  420. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/tests/unit/test_event_log.py +0 -0
  421. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/tests/unit/test_file_io.py +0 -0
  422. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/tests/unit/test_handoff_git_state.py +0 -0
  423. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/tests/unit/test_handoff_instructions.py +0 -0
  424. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/tests/unit/test_handoff_parser.py +0 -0
  425. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/tests/unit/test_handoff_renderer.py +0 -0
  426. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/tests/unit/test_history.py +0 -0
  427. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/tests/unit/test_hooks_install.py +0 -0
  428. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/tests/unit/test_idle_handler.py +0 -0
  429. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/tests/unit/test_idle_nag.py +0 -0
  430. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/tests/unit/test_init_command.py +0 -0
  431. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/tests/unit/test_install_parity.py +0 -0
  432. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/tests/unit/test_limits_tick_isolation.py +0 -0
  433. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/tests/unit/test_locking.py +0 -0
  434. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/tests/unit/test_mcp_server.py +0 -0
  435. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/tests/unit/test_notify_cli.py +0 -0
  436. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/tests/unit/test_onboarding_reinit.py +0 -0
  437. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/tests/unit/test_palette_cli.py +0 -0
  438. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/tests/unit/test_pip_environment.py +0 -0
  439. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/tests/unit/test_push.py +0 -0
  440. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/tests/unit/test_rebuild_guard.py +0 -0
  441. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/tests/unit/test_repo_cli.py +0 -0
  442. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/tests/unit/test_roles.py +0 -0
  443. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/tests/unit/test_safety_commands.py +0 -0
  444. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/tests/unit/test_safety_disabled_rules.py +0 -0
  445. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/tests/unit/test_safety_escape_hatch.py +0 -0
  446. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/tests/unit/test_safety_heal.py +0 -0
  447. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/tests/unit/test_safety_kill_switch.py +0 -0
  448. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/tests/unit/test_scheduler_parsing.py +0 -0
  449. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/tests/unit/test_scratchpad.py +0 -0
  450. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/tests/unit/test_security.py +0 -0
  451. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/tests/unit/test_server_async.py +0 -0
  452. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/tests/unit/test_server_pure.py +0 -0
  453. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/tests/unit/test_services.py +0 -0
  454. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/tests/unit/test_session_context.py +0 -0
  455. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/tests/unit/test_shared_dir_guard.py +0 -0
  456. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/tests/unit/test_skill_install.py +0 -0
  457. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/tests/unit/test_speech_tags.py +0 -0
  458. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/tests/unit/test_ssh.py +0 -0
  459. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/tests/unit/test_stt_backend.py +0 -0
  460. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/tests/unit/test_stt_cloud.py +0 -0
  461. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/tests/unit/test_stt_engine.py +0 -0
  462. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/tests/unit/test_task_cli.py +0 -0
  463. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/tests/unit/test_tasks.py +0 -0
  464. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/tests/unit/test_templating.py +0 -0
  465. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/tests/unit/test_terminal_resize.py +0 -0
  466. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/tests/unit/test_tmux_template.py +0 -0
  467. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/tests/unit/test_tts_engine_resolution.py +0 -0
  468. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/tests/unit/test_tts_local.py +0 -0
  469. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/tests/unit/test_tunnels_probe.py +0 -0
  470. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/tests/unit/test_unattended_env_isolation.py +0 -0
  471. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/tests/unit/test_usage_limit.py +0 -0
  472. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/tests/unit/test_validation.py +0 -0
  473. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/tests/unit/test_voice_status.py +0 -0
  474. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/tests/unit/test_wiki.py +0 -0
  475. {agentwire_dev-1.54.0 → agentwire_dev-1.56.0}/tests/unit/test_wiki_audit.py +0 -0
  476. {agentwire_dev-1.54.0 → agentwire_dev-1.56.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.54.0
3
+ Version: 1.56.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.54.0"
3
+ __version__ = "1.56.0"
@@ -268,6 +268,17 @@ Command Categories:
268
268
  "stop", help="Kill the sitting's sessions (prompt history kept)"
269
269
  )
270
270
  c_stop.add_argument("--name", help=_name_help)
271
+ c_stop.add_argument(
272
+ "--minutes", dest="minutes", action="store_true", default=None,
273
+ help="Render the minutes artifact (default: render when any prompt exists)",
274
+ )
275
+ c_stop.add_argument(
276
+ "--no-minutes", dest="minutes", action="store_false",
277
+ help="Skip the minutes artifact",
278
+ )
279
+ c_stop.add_argument(
280
+ "--synthesis", help="Synthesis for the minutes: text, or a path to a file"
281
+ )
271
282
  c_stop.add_argument("--json", action="store_true", help="Output JSON")
272
283
  c_stop.set_defaults(func=council_cli.cmd_council_stop)
273
284
 
@@ -332,6 +343,30 @@ Command Categories:
332
343
  c_reply.add_argument("--json", action="store_true", help="Output JSON")
333
344
  c_reply.set_defaults(func=council_cli.cmd_council_reply)
334
345
 
346
+ # council minutes
347
+ c_minutes = council_subparsers.add_parser(
348
+ "minutes",
349
+ help="Render a sitting's minutes artifact (question + takes + synthesis)",
350
+ description=(
351
+ "Deterministically renders the sitting's persisted prompt history "
352
+ "(question + attributed verbatim take/ack/pass replies) plus an "
353
+ "optional orchestrator-supplied synthesis into a self-contained "
354
+ "HTML artifact at ~/.agentwire/artifacts/council-<name>-minutes/, "
355
+ "and opens it as a portal artifact window when the portal is up. "
356
+ "Works for live and dismissed sittings (prompt history is kept "
357
+ "on stop)."
358
+ ),
359
+ )
360
+ c_minutes.add_argument("--name", help=_name_help)
361
+ c_minutes.add_argument(
362
+ "--prompt", help="Prompt id to render, or 'all' (default: all)"
363
+ )
364
+ c_minutes.add_argument(
365
+ "--synthesis", help="Synthesis: text, or a path to a file containing it"
366
+ )
367
+ c_minutes.add_argument("--json", action="store_true", help="Output JSON")
368
+ c_minutes.set_defaults(func=council_cli.cmd_council_minutes)
369
+
335
370
  return parser
336
371
 
337
372
 
@@ -57,9 +57,11 @@ def _infer_session_from_path() -> str | None:
57
57
 
58
58
  ~/projects/myapp -> myapp
59
59
  ~/projects/myapp-worktrees/feature -> myapp/feature
60
+ ~/worktrees/myapp/fix-bug -> myapp-fix-bug (worktree session)
60
61
  """
61
62
  cwd = Path.cwd()
62
63
  projects_dir = Path.home() / "projects"
64
+ worktrees_dir = Path.home() / "worktrees"
63
65
 
64
66
  try:
65
67
  rel = cwd.relative_to(projects_dir)
@@ -76,6 +78,15 @@ def _infer_session_from_path() -> str | None:
76
78
  except ValueError:
77
79
  pass
78
80
 
81
+ try:
82
+ # Worktree sessions live at ~/worktrees/<project>/<name>/ with a flat
83
+ # tmux session name {project}-{name}.
84
+ parts = cwd.relative_to(worktrees_dir).parts
85
+ if len(parts) >= 2:
86
+ return f"{parts[0]}-{parts[1]}"
87
+ except ValueError:
88
+ pass
89
+
79
90
  return None
80
91
 
81
92
 
@@ -84,7 +84,16 @@ class ServerConfig:
84
84
 
85
85
  @dataclass
86
86
  class WorktreesConfig:
87
- """Git worktrees configuration for parallel sessions."""
87
+ """Git worktrees configuration for `project/branch` sessions.
88
+
89
+ Governs the legacy ``project/branch`` session layout under
90
+ ``~/projects/<project>-worktrees/``. Still ALIVE (#703): the scheduler's
91
+ worktree+PR dispatch creates its sessions via
92
+ ``agentwire new -s <project>/<branch>``, and ``copy_files`` seeds every
93
+ fresh worktree (including scheduler dispatches). Standalone
94
+ ``agentwire worktree`` sessions use :class:`WorktreeConfig` instead
95
+ (``~/worktrees/<project>/<name>/``).
96
+ """
88
97
 
89
98
  enabled: bool = True
90
99
  suffix: str = "-worktrees"
@@ -128,7 +137,9 @@ class WorktreeConfig:
128
137
  default_project: Repo path used when ``--project`` is omitted and
129
138
  cwd is not inside a git repo. ``None`` → infer from cwd's git
130
139
  root, else cwd.
131
- worktree_dir: Where worktrees live (one dir per session).
140
+ worktree_dir: Root under which worktrees are created, nested per
141
+ project — ``<worktree_dir>/<project>/<name>/`` — mirroring
142
+ ``~/projects/<project>/``.
132
143
  naming: Optional branch-name template applied in default (new-branch)
133
144
  mode, e.g. ``"{user}/{slug}"`` or ``"feature-{slug}"``.
134
145
  Placeholders: ``{name}`` (raw), ``{slug}`` (slugified),
@@ -16,12 +16,15 @@ recency) otherwise, and **every command echoes which sitting it acted on**.
16
16
  Subcommands:
17
17
 
18
18
  - ``start`` — spin up the orchestrator + lens soul sessions (a *sitting*)
19
- - ``stop`` — kill the sitting's sessions, clear state (history kept)
19
+ - ``stop`` — kill the sitting's sessions, clear state (history kept);
20
+ renders the minutes artifact by default when any prompt exists (#708)
20
21
  - ``status`` — sitting + per-session liveness + open prompts
21
22
  - ``ask`` — fan a prompt out to every soul (creates the inbox first)
22
23
  - ``collect`` — block until every soul has filed take/ack/pass, or timeout
23
24
  - ``reply`` — file a soul's reply (souls run this via Bash)
24
25
  - ``list`` — every live/known sitting, oldest-first
26
+ - ``minutes`` — render a sitting's persisted record to a standalone HTML
27
+ artifact (question + attributed verbatim takes + optional synthesis)
25
28
  """
26
29
 
27
30
  from __future__ import annotations
@@ -30,9 +33,10 @@ import json
30
33
  import subprocess
31
34
  import sys
32
35
  from datetime import datetime, timezone
36
+ from pathlib import Path
33
37
  from typing import Any
34
38
 
35
- from agentwire.council import inbox, state
39
+ from agentwire.council import inbox, state, view
36
40
 
37
41
  # --- output helpers -----------------------------------------------------------
38
42
 
@@ -160,6 +164,35 @@ def current_session() -> str | None:
160
164
  return pane_manager.get_current_session()
161
165
 
162
166
 
167
+ def open_artifact_window(url: str, title: str) -> bool:
168
+ """Best-effort: open a rendered artifact as a portal window.
169
+
170
+ Returns True only when the portal accepted the open; a down or erroring
171
+ portal returns False — the artifact file exists on disk either way.
172
+ """
173
+ import os
174
+
175
+ from agentwire import core
176
+
177
+ portal = os.environ.get("AGENTWIRE_PORTAL_URL")
178
+ if not portal:
179
+ try:
180
+ portal = (core.load_config().get("portal", {}) or {}).get("url")
181
+ except Exception:
182
+ portal = None
183
+ portal = portal or core._default_portal_url()
184
+ try:
185
+ resp = core.portal_request(
186
+ "POST",
187
+ f"{portal}/api/desktop/window/open",
188
+ json={"type": "artifact", "url": url, "title": title},
189
+ timeout=5,
190
+ )
191
+ return resp.status_code == 200 and bool(resp.json().get("success"))
192
+ except Exception:
193
+ return False
194
+
195
+
163
196
  # --- targeting / resolution -----------------------------------------------------
164
197
 
165
198
 
@@ -322,6 +355,39 @@ def cmd_council_start(args) -> int:
322
355
  return _emit(args, payload, human, exit_code=0 if payload["success"] else 1, council=name)
323
356
 
324
357
 
358
+ def _synthesis_text(value: str | None) -> str:
359
+ """Resolve ``--synthesis <file-or-text>``: an existing file's content,
360
+ else the value verbatim."""
361
+ if not value:
362
+ return ""
363
+ try:
364
+ path = Path(value).expanduser()
365
+ if path.is_file():
366
+ return path.read_text()
367
+ except (OSError, ValueError):
368
+ pass # not a readable path — the value is the synthesis itself
369
+ return value
370
+
371
+
372
+ def _render_minutes(
373
+ name: str, prompt_ids: list[int] | None = None, synthesis: str = ""
374
+ ) -> tuple[str | None, bool | None]:
375
+ """Write the minutes artifact and best-effort open it in the portal.
376
+
377
+ Returns ``(path, opened)`` — both None when the sitting has no matching
378
+ prompt history (nothing rendered, nothing opened).
379
+ """
380
+ from agentwire.council import minutes
381
+
382
+ path = minutes.write_minutes(name, prompt_ids, synthesis=synthesis)
383
+ if path is None:
384
+ return None, None
385
+ opened = open_artifact_window(
386
+ minutes.artifact_url(name), f"Council minutes — {name}"
387
+ )
388
+ return str(path), opened
389
+
390
+
325
391
  def cmd_council_stop(args) -> int:
326
392
  name, err = resolve_name(args)
327
393
  if err:
@@ -330,6 +396,15 @@ def cmd_council_stop(args) -> int:
330
396
  if sitting is None:
331
397
  return _emit_error(args, f"no council sitting '{name}'")
332
398
 
399
+ # Minutes before teardown (#708): tri-state --minutes/--no-minutes,
400
+ # default (None) renders exactly when any prompt history exists.
401
+ minutes_path: str | None = None
402
+ minutes_opened: bool | None = None
403
+ if getattr(args, "minutes", None) is not False:
404
+ minutes_path, minutes_opened = _render_minutes(
405
+ name, synthesis=_synthesis_text(getattr(args, "synthesis", None))
406
+ )
407
+
333
408
  live = list_live_sessions()
334
409
  killed: list[str] = []
335
410
  not_running: list[str] = []
@@ -340,14 +415,57 @@ def cmd_council_stop(args) -> int:
340
415
  not_running.append(session)
341
416
  state.clear_sitting(name)
342
417
 
343
- payload = {"success": True, "killed": killed, "not_running": not_running}
344
- return _emit(
345
- args,
346
- payload,
347
- f"Council '{name}' stopped ({len(killed)} sessions killed). Prompt history kept.",
348
- council=name,
418
+ payload = {
419
+ "success": True,
420
+ "killed": killed,
421
+ "not_running": not_running,
422
+ "minutes": minutes_path,
423
+ "minutes_opened": minutes_opened,
424
+ }
425
+ human = (
426
+ f"Council '{name}' stopped ({len(killed)} sessions killed). "
427
+ "Prompt history kept."
428
+ )
429
+ if minutes_path:
430
+ human += f"\nMinutes: {minutes_path}"
431
+ return _emit(args, payload, human, council=name)
432
+
433
+
434
+ def cmd_council_minutes(args) -> int:
435
+ name, err = resolve_name(args)
436
+ if err:
437
+ return _emit_error(args, err)
438
+
439
+ available = view.available_prompt_ids(name)
440
+ if not available:
441
+ return _emit_error(args, f"council '{name}' has no prompt history to render")
442
+
443
+ prompt_arg = getattr(args, "prompt", None) or "all"
444
+ prompt_ids: list[int] | None = None
445
+ if str(prompt_arg) != "all":
446
+ try:
447
+ prompt_ids = [int(prompt_arg)]
448
+ except (TypeError, ValueError):
449
+ return _emit_error(
450
+ args, f"--prompt must be a prompt id or 'all', got {prompt_arg!r}"
451
+ )
452
+ if prompt_ids[0] not in available:
453
+ return _emit_error(
454
+ args,
455
+ f"no prompt #{prompt_ids[0]} in council '{name}' "
456
+ f"(available: {', '.join(map(str, available))})",
457
+ )
458
+
459
+ path, opened = _render_minutes(
460
+ name, prompt_ids, synthesis=_synthesis_text(getattr(args, "synthesis", None))
349
461
  )
350
462
 
463
+ payload = {"success": True, "path": path, "opened": opened}
464
+ human = f"Minutes: {path}"
465
+ if opened:
466
+ human += "\nOpened as a portal artifact window."
467
+ return _emit(args, payload, human, council=name)
468
+
351
469
 
352
470
  def cmd_council_status(args) -> int:
353
471
  name, err = resolve_name(args)
@@ -0,0 +1,174 @@
1
+ """Council minutes — deterministic HTML render of a sitting's persisted record.
2
+
3
+ Handoff pattern (#708): everything verbatim (the question, the attributed
4
+ take/ack/pass replies) already persists under
5
+ ``~/.agentwire/council/<name>/prompts/NNNN/``, so the renderer is a pure
6
+ function of disk state. The synthesis exists only in the orchestrator's
7
+ context, so it arrives as an *input* — omitted, the minutes render without a
8
+ synthesis section.
9
+
10
+ Output is one fully self-contained HTML file (inline CSS only — the portal's
11
+ artifact CSP blocks external fetches), theme-aware via
12
+ ``prefers-color-scheme``, at::
13
+
14
+ ~/.agentwire/artifacts/council-<name>-minutes/index.html
15
+
16
+ Works for live and dismissed sittings alike — prompt history is disk-derived,
17
+ sitting metadata falls back from ``sitting.json`` to the preserved
18
+ ``archive.json``.
19
+ """
20
+
21
+ from __future__ import annotations
22
+
23
+ from datetime import datetime
24
+ from pathlib import Path
25
+
26
+ import jinja2
27
+
28
+ from agentwire.council import inbox, state, view
29
+
30
+ # --- paths ------------------------------------------------------------------
31
+
32
+
33
+ def artifacts_dir() -> Path:
34
+ """The portal artifacts root (config override honored)."""
35
+ try:
36
+ from agentwire.config import load_config
37
+
38
+ return Path(str(load_config().artifacts.dir)).expanduser()
39
+ except Exception:
40
+ return Path.home() / ".agentwire" / "artifacts"
41
+
42
+
43
+ def minutes_path(name: str) -> Path:
44
+ return artifacts_dir() / f"council-{name}-minutes" / "index.html"
45
+
46
+
47
+ def artifact_url(name: str) -> str:
48
+ """Path relative to the artifacts root — what the portal iframe loads."""
49
+ return f"council-{name}-minutes/index.html"
50
+
51
+
52
+ # --- gather -----------------------------------------------------------------
53
+
54
+
55
+ def _fmt_ts(iso: str) -> str:
56
+ """ISO timestamp → compact display form (``2026-07-04 15:38 UTC``)."""
57
+ if not iso:
58
+ return ""
59
+ try:
60
+ dt = datetime.fromisoformat(iso)
61
+ except (ValueError, TypeError):
62
+ return iso
63
+ suffix = " UTC" if dt.tzinfo is not None else ""
64
+ return dt.strftime("%Y-%m-%d %H:%M") + suffix
65
+
66
+
67
+ def gather(name: str, prompt_ids: list[int] | None = None) -> dict | None:
68
+ """Collect a sitting's persisted record into a render-ready dict.
69
+
70
+ ``prompt_ids`` filters to specific rounds (None = every prompt on disk).
71
+ Returns ``None`` when nothing matches — a sitting that never deliberated
72
+ has no minutes. Reply dicts carry only content (soul, kind, text,
73
+ timestamp), never local filesystem paths: the artifact is built to be
74
+ shared.
75
+ """
76
+ available = view.available_prompt_ids(name)
77
+ selected = (
78
+ available if prompt_ids is None else [p for p in prompt_ids if p in available]
79
+ )
80
+ if not selected:
81
+ return None
82
+
83
+ sitting = state.read_sitting(name)
84
+ archived = sitting is None
85
+ dismissed_at = ""
86
+ if archived:
87
+ raw = state.read_archive_dict(name)
88
+ dismissed_at = (raw or {}).get("dismissed_at", "")
89
+ sitting = (
90
+ state.Sitting.from_dict(raw)
91
+ if raw is not None
92
+ else state.Sitting(
93
+ orchestrator=state.orchestrator_for(name),
94
+ roster=[],
95
+ sessions={},
96
+ started_at="",
97
+ )
98
+ )
99
+
100
+ prompts = []
101
+ for pid in selected:
102
+ meta = inbox.read_meta(name, pid)
103
+ try:
104
+ question = (inbox.prompt_dir(name, pid) / "prompt.md").read_text()
105
+ except OSError:
106
+ question = ""
107
+ replies = [
108
+ {
109
+ "soul": r.soul,
110
+ "kind": r.kind,
111
+ "text": r.text.strip(),
112
+ "written_at": _fmt_ts(r.written_at),
113
+ }
114
+ for r in inbox.list_replies(name, pid)
115
+ ]
116
+ prompts.append(
117
+ {
118
+ "id": pid,
119
+ "question": question.strip(),
120
+ "created_at": _fmt_ts(meta.get("created_at", "")),
121
+ "roster": meta.get("roster") or list(sitting.roster),
122
+ "replies": replies,
123
+ }
124
+ )
125
+
126
+ roster = list(sitting.roster) or prompts[0]["roster"]
127
+ return {
128
+ "name": name,
129
+ "archived": archived,
130
+ "started_at": _fmt_ts(sitting.started_at),
131
+ "dismissed_at": _fmt_ts(dismissed_at),
132
+ "roster": roster,
133
+ "prompts": prompts,
134
+ }
135
+
136
+
137
+ # --- render -----------------------------------------------------------------
138
+
139
+
140
+ def _env() -> jinja2.Environment:
141
+ # autoescape=True explicitly: select_autoescape keys off the *final*
142
+ # extension, and ``.html.j2`` ends in ``.j2`` — verbatim soul takes are
143
+ # untrusted content, so escaping must never silently switch off.
144
+ templates = Path(__file__).resolve().parent.parent / "templates"
145
+ return jinja2.Environment(
146
+ loader=jinja2.FileSystemLoader(str(templates)),
147
+ autoescape=True,
148
+ )
149
+
150
+
151
+ def render_html(record: dict, synthesis: str = "") -> str:
152
+ template = _env().get_template("council/minutes.html.j2")
153
+ return template.render(
154
+ record=record,
155
+ synthesis=(synthesis or "").strip(),
156
+ generated_at=_fmt_ts(state.now_iso()),
157
+ )
158
+
159
+
160
+ def write_minutes(
161
+ name: str, prompt_ids: list[int] | None = None, synthesis: str = ""
162
+ ) -> Path | None:
163
+ """Render and write the minutes artifact; return its path.
164
+
165
+ Returns ``None`` (writes nothing) when the sitting has no matching prompt
166
+ history — a zero-prompt sitting leaves no minutes behind.
167
+ """
168
+ record = gather(name, prompt_ids)
169
+ if record is None:
170
+ return None
171
+ out = minutes_path(name)
172
+ out.parent.mkdir(parents=True, exist_ok=True)
173
+ out.write_text(render_html(record, synthesis), encoding="utf-8")
174
+ return out
@@ -62,6 +62,13 @@ BROADCAST_TOKEN = "@all"
62
62
  # being permanently busy/typed-in).
63
63
  MAX_ATTEMPTS = 40
64
64
 
65
+ # A recipient that positively does not exist gets a much shorter window (#694):
66
+ # a gone session can't clear its box by itself — it only comes back if someone
67
+ # recreates it — so the grace is ~5 watchdog ticks (≈5 min), enough for a
68
+ # restart/recreate to land, not the 40-minute busy cap. Counted separately
69
+ # (``Message.gone_attempts``) so prior busy penalties don't erode the grace.
70
+ GONE_MAX_ATTEMPTS = 5
71
+
65
72
  # Defer reasons that DON'T penalize: the target is legitimately busy — running a
66
73
  # long command (unparseable box → "target_busy") or generating with human-queued
67
74
  # input (the "queued messages" placeholder → "queued_placeholder"), or the box
@@ -106,6 +113,7 @@ class Message:
106
113
  text: str
107
114
  ts: int # epoch ms
108
115
  attempts: int = 0
116
+ gone_attempts: int = 0 # ticks the drain observed the target session gone
109
117
  reason: str = "" # last defer reason (why delivery kept failing)
110
118
  dead_ts: int = 0 # epoch ms when dead-lettered (0 = still live)
111
119
  ref: str = "" # optional machine-readable pointer (e.g. a report path) — for ingest
@@ -120,6 +128,7 @@ class Message:
120
128
  "text": self.text,
121
129
  "ts": self.ts,
122
130
  "attempts": self.attempts,
131
+ "gone_attempts": self.gone_attempts,
123
132
  "reason": self.reason,
124
133
  "dead_ts": self.dead_ts,
125
134
  "ref": self.ref,
@@ -251,6 +260,7 @@ def _read_message(path: Path) -> "Message | None":
251
260
  text=str(data.get("text", "")),
252
261
  ts=int(data.get("ts", 0)),
253
262
  attempts=int(data.get("attempts", 0)),
263
+ gone_attempts=int(data.get("gone_attempts", 0)),
254
264
  reason=str(data.get("reason", "")),
255
265
  dead_ts=int(data.get("dead_ts", 0)),
256
266
  ref=str(data.get("ref", "")),
@@ -484,19 +494,34 @@ def gc_sender(sender: str) -> dict:
484
494
  # =============================================================================
485
495
 
486
496
 
487
- def _live_agent_sessions() -> list[str]:
488
- """Every tmux session whose pane 0 runs an agent (Claude/pi)."""
489
- from . import prompt_router
497
+ def live_sessions() -> "set[str] | None":
498
+ """Every live tmux session name, or None when tmux is unreachable.
499
+
500
+ ``None`` (no server / no tmux) is deliberately distinct from ``set()``:
501
+ the gone fast-path (#694) and the send-time warning only fire on POSITIVE
502
+ knowledge that tmux is reachable but the target isn't there. With the
503
+ server down everything is equally unreachable — that's an outage, not a
504
+ gone recipient, so callers fall back to the ordinary defer path.
505
+ """
490
506
  from .usage_limit import _tmux
491
507
 
492
508
  try:
493
509
  result = _tmux(["list-sessions", "-F", "#{session_name}"])
494
510
  except Exception:
495
- return []
511
+ return None
496
512
  if result.returncode != 0:
513
+ return None
514
+ return {s for s in result.stdout.split("\n") if s.strip()}
515
+
516
+
517
+ def _live_agent_sessions() -> list[str]:
518
+ """Every tmux session whose pane 0 runs an agent (Claude/pi)."""
519
+ from . import prompt_router
520
+
521
+ sessions = live_sessions()
522
+ if not sessions:
497
523
  return []
498
- sessions = [s for s in result.stdout.split("\n") if s.strip()]
499
- return [s for s in sessions if prompt_router.is_agent_pane(s, 0)]
524
+ return [s for s in sorted(sessions) if prompt_router.is_agent_pane(s, 0)]
500
525
 
501
526
 
502
527
  def resolve_targets(to: str, sender: "str | None") -> list[str]:
@@ -639,6 +664,15 @@ def _bump_attempts(messages: list[Message], reason: str = "") -> int:
639
664
  ``reason`` is the defer reason that caused this pass; it's stamped onto the
640
665
  message so a dead-lettered one carries *why* it never got delivered.
641
666
  Returns the number dead-lettered this pass.
667
+
668
+ ``target_gone`` additionally bumps the per-message ``gone_attempts``
669
+ counter and dead-letters at the fast ``GONE_MAX_ATTEMPTS`` cap (#694) — a
670
+ gone session can't un-go by itself, so it gets minutes of grace (enough
671
+ for a recreate to land), not the 40-minute busy window. The counter is
672
+ separate from ``attempts`` so busy penalties accrued while the target
673
+ lived don't erode the grace, and cumulative across gone observations —
674
+ a target that flaps in and out without ever accepting delivery still
675
+ burns out on schedule.
642
676
  """
643
677
  dead = 0
644
678
  for msg in messages:
@@ -657,7 +691,9 @@ def _bump_attempts(messages: list[Message], reason: str = "") -> int:
657
691
 
658
692
  msg.attempts += 1
659
693
  msg.reason = reason
660
- if msg.attempts >= MAX_ATTEMPTS:
694
+ if reason == "target_gone":
695
+ msg.gone_attempts += 1
696
+ if msg.attempts >= MAX_ATTEMPTS or msg.gone_attempts >= GONE_MAX_ATTEMPTS:
661
697
  msg.dead_ts = _now_ms()
662
698
  target = dead_dir(msg.to or "unknown") / msg.path.name
663
699
  try:
@@ -737,6 +773,22 @@ def flush_session(session: str, force: bool = False) -> dict:
737
773
  if not messages:
738
774
  return {"session": session, "delivered": 0, "deferred": False, "reason": "empty"}
739
775
 
776
+ # Gone gate FIRST (#694): a recipient that positively doesn't exist can
777
+ # never clear a box, and the ordinary gates misread it — capturing a
778
+ # gone session parses as "no box" → target_busy, a NO-penalty defer, so
779
+ # a done to a stale parent once sat queued ~24h instead of burning out.
780
+ # Gone is its own penalized reason with the fast GONE_MAX_ATTEMPTS cap.
781
+ # Only positive knowledge counts: with tmux unreachable live_sessions()
782
+ # is None and the ordinary defer path applies.
783
+ live = live_sessions()
784
+ if live is not None and session not in live:
785
+ dead = _bump_attempts(messages, "target_gone")
786
+ _log_event("deferred", to=session, count=len(messages), reason="target_gone")
787
+ return {
788
+ "session": session, "delivered": 0, "deferred": True,
789
+ "reason": "target_gone", "dead": dead,
790
+ }
791
+
740
792
  pre_consumed = 0
741
793
  if not force:
742
794
  # Collision guard FIRST (cheap, and refuses dialogs/busy too via None).