agentwire-dev 1.55.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.55.0 → agentwire_dev-1.56.0}/PKG-INFO +1 -1
  2. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/__init__.py +1 -1
  3. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/__main__.py +35 -0
  4. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/channels_cli.py +11 -0
  5. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/config.py +13 -2
  6. {agentwire_dev-1.55.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.55.0 → agentwire_dev-1.56.0}/agentwire/mcp_council.py +51 -4
  9. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/mcp_worktree.py +3 -3
  10. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/project_config.py +51 -0
  11. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/roles/council-orchestrator.md +8 -0
  12. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/routes/artifacts.py +42 -0
  13. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/session_cli.py +69 -42
  14. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/static/css/desktop.css +23 -0
  15. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/static/js/artifact-window.js +61 -0
  16. agentwire_dev-1.56.0/agentwire/templates/council/minutes.html.j2 +193 -0
  17. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/worktree.py +0 -17
  18. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/worktree_registry.py +1 -1
  19. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/docs/wiki/council.md +32 -2
  20. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/docs/wiki/sessions/worktree-sessions.md +21 -5
  21. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/tests/integration/test_worktree_cmd.py +166 -7
  22. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/tests/unit/test_cli_commands.py +1 -0
  23. agentwire_dev-1.56.0/tests/unit/test_council_minutes.py +305 -0
  24. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/tests/unit/test_portal_api.py +62 -0
  25. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/tests/unit/test_project_config.py +59 -0
  26. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/tests/unit/test_routes_snapshot.py +2 -0
  27. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/tests/unit/test_worktree.py +0 -26
  28. agentwire_dev-1.56.0/tests/unit/test_worktree_layout.py +89 -0
  29. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/.agentwire.yml.example +0 -0
  30. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/.claude/commands/handoff.md +0 -0
  31. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/.claude/skills/wiki/SKILL.md +0 -0
  32. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/.github/FUNDING.yml +0 -0
  33. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
  34. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
  35. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/.github/ISSUE_TEMPLATE/question.md +0 -0
  36. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
  37. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/.github/workflows/pytest.yml +0 -0
  38. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/.github/workflows/ruff.yml +0 -0
  39. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/.github/workflows/security.yml +0 -0
  40. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/.github/workflows/tts-smoke.yml +0 -0
  41. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/.gitignore +0 -0
  42. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/AGENTS.md +0 -0
  43. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/CODE_OF_CONDUCT.md +0 -0
  44. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/CONTRIBUTING.md +0 -0
  45. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/Dockerfile.local +0 -0
  46. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/LICENSE +0 -0
  47. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/README.md +0 -0
  48. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/RELEASING.md +0 -0
  49. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/SECURITY.md +0 -0
  50. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/SPONSORS.md +0 -0
  51. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/agents/__init__.py +0 -0
  52. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/agents/base.py +0 -0
  53. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/agents/tmux.py +0 -0
  54. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/cached_status.py +0 -0
  55. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/channels/__init__.py +0 -0
  56. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/channels/base.py +0 -0
  57. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/channels/email.py +0 -0
  58. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/channels/push.py +0 -0
  59. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/channels/quo.py +0 -0
  60. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/completion.py +0 -0
  61. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/config_cli.py +0 -0
  62. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/core.py +0 -0
  63. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/council/__init__.py +0 -0
  64. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/council/inbox.py +0 -0
  65. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/council/state.py +0 -0
  66. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/council/view.py +0 -0
  67. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/devices.py +0 -0
  68. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/diff_cli.py +0 -0
  69. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/doctor_cli.py +0 -0
  70. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/doctor_voice.py +0 -0
  71. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/ensure_cli.py +0 -0
  72. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/fetch.py +0 -0
  73. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/handoff/__init__.py +0 -0
  74. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/handoff/git_state.py +0 -0
  75. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/handoff/instructions.py +0 -0
  76. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/handoff/parser.py +0 -0
  77. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/handoff/renderer.py +0 -0
  78. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/handoff/schema.py +0 -0
  79. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/handoff_cli.py +0 -0
  80. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/history.py +0 -0
  81. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/history_cli.py +0 -0
  82. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/hooks/__init__.py +0 -0
  83. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/hooks/agentwire-permission.sh +0 -0
  84. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/hooks/damage-control/__init__.py +0 -0
  85. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/hooks/damage-control/audit_logger.py +0 -0
  86. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/hooks/damage-control/bash-tool-damage-control.py +0 -0
  87. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/hooks/damage-control/edit-tool-damage-control.py +0 -0
  88. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/hooks/damage-control/mcp-tool-damage-control.py +0 -0
  89. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/hooks/damage-control/read-tool-damage-control.py +0 -0
  90. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/hooks/damage-control/rules/agentwire.yaml +0 -0
  91. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/hooks/damage-control/rules/aws.yaml +0 -0
  92. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/hooks/damage-control/rules/cloud-hosting.yaml +0 -0
  93. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/hooks/damage-control/rules/containers.yaml +0 -0
  94. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/hooks/damage-control/rules/control-plane.yaml +0 -0
  95. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/hooks/damage-control/rules/core.yaml +0 -0
  96. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/hooks/damage-control/rules/databases.yaml +0 -0
  97. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/hooks/damage-control/rules/firebase.yaml +0 -0
  98. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/hooks/damage-control/rules/gcp.yaml +0 -0
  99. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/hooks/damage-control/rules/git.yaml +0 -0
  100. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/hooks/damage-control/rules/gws.yaml +0 -0
  101. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/hooks/damage-control/rules/infrastructure.yaml +0 -0
  102. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/hooks/damage-control/rules/outbound.yaml +0 -0
  103. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/hooks/damage-control/rules/publish.yaml +0 -0
  104. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/hooks/damage-control/rules/remote.yaml +0 -0
  105. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/hooks/damage-control/write-tool-damage-control.py +0 -0
  106. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/hooks/idle-handler.sh +0 -0
  107. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/hooks/queue-processor.sh +0 -0
  108. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/hooks_cli.py +0 -0
  109. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/inbox.py +0 -0
  110. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/limits_cli.py +0 -0
  111. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/listen.py +0 -0
  112. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/locking.py +0 -0
  113. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/machine_cli.py +0 -0
  114. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/mcp_channels.py +0 -0
  115. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/mcp_cli.py +0 -0
  116. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/mcp_core.py +0 -0
  117. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/mcp_desktop.py +0 -0
  118. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/mcp_handoff.py +0 -0
  119. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/mcp_history.py +0 -0
  120. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/mcp_listen.py +0 -0
  121. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/mcp_lock.py +0 -0
  122. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/mcp_machine.py +0 -0
  123. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/mcp_msg.py +0 -0
  124. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/mcp_notify.py +0 -0
  125. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/mcp_pane.py +0 -0
  126. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/mcp_projects.py +0 -0
  127. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/mcp_scheduler.py +0 -0
  128. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/mcp_scratchpad.py +0 -0
  129. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/mcp_server.py +0 -0
  130. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/mcp_services.py +0 -0
  131. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/mcp_session.py +0 -0
  132. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/mcp_status.py +0 -0
  133. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/mcp_task.py +0 -0
  134. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/mcp_tunnels.py +0 -0
  135. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/mcp_voice.py +0 -0
  136. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/mcp_voiceclone.py +0 -0
  137. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/mcp_wiki.py +0 -0
  138. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/msg_cli.py +0 -0
  139. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/network.py +0 -0
  140. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/notify_cli.py +0 -0
  141. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/onboarding.py +0 -0
  142. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/palette_cli.py +0 -0
  143. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/pane_cli.py +0 -0
  144. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/pane_manager.py +0 -0
  145. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/portal_cli.py +0 -0
  146. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/projects.py +0 -0
  147. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/prompt_router.py +0 -0
  148. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/prompts_cli.py +0 -0
  149. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/push_cli.py +0 -0
  150. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/push_store.py +0 -0
  151. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/repo_cli.py +0 -0
  152. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/research.py +0 -0
  153. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/roles/__init__.py +0 -0
  154. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/roles/agentwire.md +0 -0
  155. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/roles/anchor.md +0 -0
  156. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/roles/chatbot.md +0 -0
  157. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/roles/contributor.md +0 -0
  158. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/roles/correspondent.md +0 -0
  159. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/roles/council-brain.md +0 -0
  160. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/roles/council-conscience.md +0 -0
  161. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/roles/council-critic.md +0 -0
  162. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/roles/council-devils-advocate.md +0 -0
  163. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/roles/council-gut.md +0 -0
  164. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/roles/council-historian.md +0 -0
  165. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/roles/council-member.md +0 -0
  166. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/roles/init.md +0 -0
  167. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/roles/notifications.md +0 -0
  168. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/roles/orchestrator.md +0 -0
  169. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/roles/soul.md +0 -0
  170. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/roles/task-runner.md +0 -0
  171. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/roles/voice.md +0 -0
  172. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/roles/worker.md +0 -0
  173. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/roles/worktree-session.md +0 -0
  174. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/roles_cli.py +0 -0
  175. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/routes/__init__.py +0 -0
  176. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/routes/config.py +0 -0
  177. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/routes/council.py +0 -0
  178. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/routes/desktop.py +0 -0
  179. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/routes/history.py +0 -0
  180. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/routes/machines.py +0 -0
  181. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/routes/notify.py +0 -0
  182. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/routes/palette.py +0 -0
  183. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/routes/permission.py +0 -0
  184. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/routes/projects.py +0 -0
  185. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/routes/push.py +0 -0
  186. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/routes/safety.py +0 -0
  187. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/routes/scheduler.py +0 -0
  188. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/routes/scratchpad.py +0 -0
  189. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/routes/sessions.py +0 -0
  190. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/routes/sessions_admin.py +0 -0
  191. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/routes/voice.py +0 -0
  192. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/safety/__init__.py +0 -0
  193. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/safety/_core.py +0 -0
  194. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/safety_cli.py +0 -0
  195. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/safety_commands.py +0 -0
  196. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/scheduler/__init__.py +0 -0
  197. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/scheduler/dispatch.py +0 -0
  198. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/scheduler/gates.py +0 -0
  199. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/scheduler/loop.py +0 -0
  200. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/scheduler/models.py +0 -0
  201. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/scheduler/report.py +0 -0
  202. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/scheduler/schedule.py +0 -0
  203. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/scheduler/state.py +0 -0
  204. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/scheduler_cli.py +0 -0
  205. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/scratchpad.py +0 -0
  206. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/security.py +0 -0
  207. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/send_cli.py +0 -0
  208. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/server.py +0 -0
  209. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/services.py +0 -0
  210. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/session_context.py +0 -0
  211. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/session_ready.py +0 -0
  212. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/ssh.py +0 -0
  213. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/static/agentwire-splash-logo-layers--agentwire-text.png +0 -0
  214. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/static/agentwire-splash-logo-layers--echo-claw-fg.png +0 -0
  215. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/static/agentwire-splash-logo-layers--echo.png +0 -0
  216. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/static/agentwire-splash-logo-layers--telephone.png +0 -0
  217. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/static/agentwire-splash-logo-layers--tree.png +0 -0
  218. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/static/announcements.json +0 -0
  219. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/static/apple-touch-icon.png +0 -0
  220. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/static/css/mobile.css +0 -0
  221. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/static/favicon-32.png +0 -0
  222. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/static/favicon-64.png +0 -0
  223. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/static/icons/sessions/bear.webp +0 -0
  224. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/static/icons/sessions/cat.webp +0 -0
  225. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/static/icons/sessions/crown.webp +0 -0
  226. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/static/icons/sessions/custom/agentwire-portal.webp +0 -0
  227. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/static/icons/sessions/custom/agentwire-tts.webp +0 -0
  228. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/static/icons/sessions/custom/agentwire.webp +0 -0
  229. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/static/icons/sessions/deer.webp +0 -0
  230. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/static/icons/sessions/drone.webp +0 -0
  231. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/static/icons/sessions/eagle.webp +0 -0
  232. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/static/icons/sessions/fox.webp +0 -0
  233. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/static/icons/sessions/hawk.webp +0 -0
  234. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/static/icons/sessions/horse.webp +0 -0
  235. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/static/icons/sessions/lion.webp +0 -0
  236. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/static/icons/sessions/rabbit.webp +0 -0
  237. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/static/icons/sessions/robot.webp +0 -0
  238. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/static/icons/sessions/tiger.webp +0 -0
  239. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/static/icons/sessions/wolf.webp +0 -0
  240. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/static/img/icon-192.png +0 -0
  241. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/static/img/icon-512.png +0 -0
  242. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/static/js/.gitkeep +0 -0
  243. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/static/js/announcement-modal.js +0 -0
  244. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/static/js/api.js +0 -0
  245. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/static/js/collage.js +0 -0
  246. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/static/js/command-palette.js +0 -0
  247. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/static/js/council-window.js +0 -0
  248. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/static/js/dead-key-suppressor.js +0 -0
  249. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/static/js/desktop-manager.js +0 -0
  250. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/static/js/desktop.js +0 -0
  251. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/static/js/help-modal.js +0 -0
  252. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/static/js/icon-manager.js +0 -0
  253. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/static/js/mobile.js +0 -0
  254. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/static/js/notification-prefs.js +0 -0
  255. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/static/js/notifications-panel.js +0 -0
  256. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/static/js/ptt.js +0 -0
  257. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/static/js/push-client.js +0 -0
  258. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/static/js/review-window.js +0 -0
  259. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/static/js/safety-shared.js +0 -0
  260. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/static/js/safety-window.js +0 -0
  261. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/static/js/scratchpad.js +0 -0
  262. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/static/js/service-classification.js +0 -0
  263. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/static/js/session-id.js +0 -0
  264. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/static/js/session-window.js +0 -0
  265. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/static/js/shortcuts.js +0 -0
  266. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/static/js/sidebar/artifacts-section.js +0 -0
  267. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/static/js/sidebar/config-section.js +0 -0
  268. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/static/js/sidebar/council-section.js +0 -0
  269. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/static/js/sidebar/machines-section.js +0 -0
  270. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/static/js/sidebar/projects-section.js +0 -0
  271. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/static/js/sidebar/safety-section.js +0 -0
  272. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/static/js/sidebar/scheduler-section.js +0 -0
  273. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/static/js/sidebar/services-section.js +0 -0
  274. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/static/js/sidebar/sessions-section.js +0 -0
  275. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/static/js/sidebar.js +0 -0
  276. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/static/js/terminal-font-prefs.js +0 -0
  277. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/static/js/tile-manager.js +0 -0
  278. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/static/js/toast.js +0 -0
  279. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/static/js/token-modal.js +0 -0
  280. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/static/js/utils/ansi.js +0 -0
  281. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/static/js/utils/swipe.js +0 -0
  282. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/static/js/voice/autosend-prefs.js +0 -0
  283. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/static/js/voice/browser-stt.js +0 -0
  284. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/static/js/voice/browser-tts.js +0 -0
  285. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/static/js/voice/jargon.js +0 -0
  286. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/static/js/voice/prompt.js +0 -0
  287. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/static/js/winbox.bundle.min.js +0 -0
  288. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/static/manifest.webmanifest +0 -0
  289. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/static/service-worker.js +0 -0
  290. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/stt/__init__.py +0 -0
  291. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/stt/base.py +0 -0
  292. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/stt/cloud.py +0 -0
  293. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/stt/engine.py +0 -0
  294. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/stt/local.py +0 -0
  295. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/stt/server_backend.py +0 -0
  296. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/stt/stt_server.py +0 -0
  297. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/system_cli.py +0 -0
  298. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/tasks.py +0 -0
  299. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/templates/__init__.py +0 -0
  300. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/templates/base.html +0 -0
  301. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/templates/desktop.html +0 -0
  302. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/templates/email_notification.html +0 -0
  303. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/templates/handoff/show-the-story.html.j2 +0 -0
  304. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/templates/handoff/theme.css.j2 +0 -0
  305. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/templates/mobile.html +0 -0
  306. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/templates/pair.html +0 -0
  307. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/templates/tmux.conf +0 -0
  308. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/templating.py +0 -0
  309. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/tooldefs/aws.yaml +0 -0
  310. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/tooldefs/docker.yaml +0 -0
  311. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/tooldefs/gcp.yaml +0 -0
  312. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/tooldefs/gh.yaml +0 -0
  313. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/tooldefs/git.yaml +0 -0
  314. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/tooldefs/gws.yaml +0 -0
  315. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/tooldefs/kubectl.yaml +0 -0
  316. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/tooldefs/npm.yaml +0 -0
  317. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/tooldefs/terraform.yaml +0 -0
  318. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/tooldefs/uv.yaml +0 -0
  319. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/tts/__init__.py +0 -0
  320. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/tts/audio.py +0 -0
  321. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/tts/base.py +0 -0
  322. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/tts/engines/__init__.py +0 -0
  323. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/tts/engines/chatterbox.py +0 -0
  324. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/tts/engines/kokoro.py +0 -0
  325. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/tts/engines/zonos.py +0 -0
  326. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/tts/kokoro_server.py +0 -0
  327. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/tts/local.py +0 -0
  328. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/tts/registry.py +0 -0
  329. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/tts_cli.py +0 -0
  330. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/tts_server.py +0 -0
  331. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/tunnels.py +0 -0
  332. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/tunnels_cli.py +0 -0
  333. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/usage_limit.py +0 -0
  334. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/utils/__init__.py +0 -0
  335. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/utils/chunker.py +0 -0
  336. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/utils/event_log.py +0 -0
  337. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/utils/file_io.py +0 -0
  338. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/utils/paths.py +0 -0
  339. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/utils/speech.py +0 -0
  340. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/utils/subprocess.py +0 -0
  341. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/validation.py +0 -0
  342. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/voice_status.py +0 -0
  343. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/voiceclone.py +0 -0
  344. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/wiki.py +0 -0
  345. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/wiki_audit.py +0 -0
  346. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/agentwire/wiki_cli.py +0 -0
  347. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/docs/decisions/obsidian-second-brain.md +0 -0
  348. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/docs/logo.png +0 -0
  349. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/docs/wiki/INDEX.md +0 -0
  350. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/docs/wiki/architecture.md +0 -0
  351. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/docs/wiki/briefing-mode.md +0 -0
  352. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/docs/wiki/communication/channels.md +0 -0
  353. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/docs/wiki/communication/hammerspoon.md +0 -0
  354. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/docs/wiki/communication/handoff.md +0 -0
  355. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/docs/wiki/concepts.md +0 -0
  356. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/docs/wiki/deployment/remote-access.md +0 -0
  357. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/docs/wiki/deployment/remote-machines.md +0 -0
  358. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/docs/wiki/glossary.md +0 -0
  359. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/docs/wiki/integrations/gws-google-workspace-cli.md +0 -0
  360. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/docs/wiki/internals/damage-control.md +0 -0
  361. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/docs/wiki/internals/parallel-refactor.md +0 -0
  362. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/docs/wiki/internals/portal.md +0 -0
  363. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/docs/wiki/internals/shell-escaping.md +0 -0
  364. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/docs/wiki/internals/troubleshooting.md +0 -0
  365. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/docs/wiki/internals/window-collage.md +0 -0
  366. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/docs/wiki/quickstart.md +0 -0
  367. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/docs/wiki/research/briefing-mode-feasibility.md +0 -0
  368. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/docs/wiki/research/orchestration-transport-alternatives.md +0 -0
  369. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/docs/wiki/scheduling/scheduled-workloads.md +0 -0
  370. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/docs/wiki/security/damage-control-hardening.md +0 -0
  371. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/docs/wiki/security/pip-audit.md +0 -0
  372. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/docs/wiki/security/remote-access-hardening.md +0 -0
  373. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/docs/wiki/security/secrets.md +0 -0
  374. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/docs/wiki/services.md +0 -0
  375. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/docs/wiki/sessions/claude-code-auto-mode.md +0 -0
  376. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/docs/wiki/sessions/messaging.md +0 -0
  377. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/docs/wiki/sessions/pi.md +0 -0
  378. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/docs/wiki/sessions/prompt-routing.md +0 -0
  379. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/docs/wiki/sessions/window-sizing.md +0 -0
  380. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/docs/wiki/usage-limit-recovery.md +0 -0
  381. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/docs/wiki/voice/shim-contract.md +0 -0
  382. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/docs/wiki/voice/stt-cloud.md +0 -0
  383. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/docs/wiki/voice/stt-self-hosted.md +0 -0
  384. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/docs/wiki/voice/tts-self-hosted.md +0 -0
  385. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/pyproject.toml +0 -0
  386. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/tests/conftest.py +0 -0
  387. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/tests/e2e/test_portal_ui.py +0 -0
  388. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/tests/fixtures/sample_agentwire.yml +0 -0
  389. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/tests/fixtures/sample_config.yaml +0 -0
  390. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/tests/fixtures/sample_scheduler.yaml +0 -0
  391. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/tests/integration/test_council_portal.py +0 -0
  392. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/tests/integration/test_scheduler_board.py +0 -0
  393. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/tests/integration/test_send_verified_tmux.py +0 -0
  394. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/tests/integration/test_server_websockets.py +0 -0
  395. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/tests/unit/test_announcements.py +0 -0
  396. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/tests/unit/test_build_agent_command.py +0 -0
  397. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/tests/unit/test_channels.py +0 -0
  398. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/tests/unit/test_cli_output.py +0 -0
  399. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/tests/unit/test_cli_smoke.py +0 -0
  400. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/tests/unit/test_config.py +0 -0
  401. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/tests/unit/test_config_cli.py +0 -0
  402. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/tests/unit/test_control_plane_protection.py +0 -0
  403. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/tests/unit/test_council_cli.py +0 -0
  404. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/tests/unit/test_council_inbox.py +0 -0
  405. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/tests/unit/test_council_state.py +0 -0
  406. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/tests/unit/test_council_view.py +0 -0
  407. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/tests/unit/test_damage_control_bypass.py +0 -0
  408. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/tests/unit/test_damage_control_hooks.py +0 -0
  409. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/tests/unit/test_damage_control_sync.py +0 -0
  410. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/tests/unit/test_devices.py +0 -0
  411. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/tests/unit/test_diff_cli.py +0 -0
  412. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/tests/unit/test_doctor_voice.py +0 -0
  413. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/tests/unit/test_event_log.py +0 -0
  414. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/tests/unit/test_file_io.py +0 -0
  415. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/tests/unit/test_handoff_git_state.py +0 -0
  416. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/tests/unit/test_handoff_instructions.py +0 -0
  417. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/tests/unit/test_handoff_parser.py +0 -0
  418. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/tests/unit/test_handoff_renderer.py +0 -0
  419. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/tests/unit/test_history.py +0 -0
  420. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/tests/unit/test_hooks_install.py +0 -0
  421. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/tests/unit/test_idle_handler.py +0 -0
  422. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/tests/unit/test_idle_nag.py +0 -0
  423. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/tests/unit/test_inbox.py +0 -0
  424. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/tests/unit/test_init_command.py +0 -0
  425. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/tests/unit/test_install_parity.py +0 -0
  426. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/tests/unit/test_limits_tick_isolation.py +0 -0
  427. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/tests/unit/test_locking.py +0 -0
  428. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/tests/unit/test_mcp_server.py +0 -0
  429. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/tests/unit/test_mcp_tools_args.py +0 -0
  430. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/tests/unit/test_msg_cli.py +0 -0
  431. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/tests/unit/test_notify_cli.py +0 -0
  432. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/tests/unit/test_onboarding_reinit.py +0 -0
  433. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/tests/unit/test_palette_cli.py +0 -0
  434. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/tests/unit/test_pip_environment.py +0 -0
  435. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/tests/unit/test_prompt_router.py +0 -0
  436. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/tests/unit/test_push.py +0 -0
  437. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/tests/unit/test_rebuild_guard.py +0 -0
  438. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/tests/unit/test_repo_cli.py +0 -0
  439. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/tests/unit/test_roles.py +0 -0
  440. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/tests/unit/test_safety_commands.py +0 -0
  441. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/tests/unit/test_safety_disabled_rules.py +0 -0
  442. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/tests/unit/test_safety_escape_hatch.py +0 -0
  443. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/tests/unit/test_safety_heal.py +0 -0
  444. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/tests/unit/test_safety_kill_switch.py +0 -0
  445. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/tests/unit/test_scheduler.py +0 -0
  446. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/tests/unit/test_scheduler_parsing.py +0 -0
  447. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/tests/unit/test_scratchpad.py +0 -0
  448. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/tests/unit/test_security.py +0 -0
  449. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/tests/unit/test_server_async.py +0 -0
  450. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/tests/unit/test_server_pure.py +0 -0
  451. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/tests/unit/test_services.py +0 -0
  452. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/tests/unit/test_session_context.py +0 -0
  453. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/tests/unit/test_session_ready.py +0 -0
  454. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/tests/unit/test_shared_dir_guard.py +0 -0
  455. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/tests/unit/test_skill_install.py +0 -0
  456. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/tests/unit/test_speech_tags.py +0 -0
  457. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/tests/unit/test_ssh.py +0 -0
  458. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/tests/unit/test_stt_backend.py +0 -0
  459. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/tests/unit/test_stt_cloud.py +0 -0
  460. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/tests/unit/test_stt_engine.py +0 -0
  461. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/tests/unit/test_task_cli.py +0 -0
  462. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/tests/unit/test_tasks.py +0 -0
  463. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/tests/unit/test_templating.py +0 -0
  464. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/tests/unit/test_terminal_resize.py +0 -0
  465. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/tests/unit/test_tmux_template.py +0 -0
  466. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/tests/unit/test_tts_engine_resolution.py +0 -0
  467. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/tests/unit/test_tts_local.py +0 -0
  468. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/tests/unit/test_tunnels_probe.py +0 -0
  469. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/tests/unit/test_unattended_env_isolation.py +0 -0
  470. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/tests/unit/test_usage_limit.py +0 -0
  471. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/tests/unit/test_validation.py +0 -0
  472. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/tests/unit/test_voice_status.py +0 -0
  473. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/tests/unit/test_wiki.py +0 -0
  474. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/tests/unit/test_wiki_audit.py +0 -0
  475. {agentwire_dev-1.55.0 → agentwire_dev-1.56.0}/tests/unit/test_window_cycling_binding.py +0 -0
  476. {agentwire_dev-1.55.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.55.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.55.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
@@ -52,25 +52,37 @@ def council_start(name: str = "", roster: str = "", model: str = "") -> str:
52
52
 
53
53
 
54
54
  @mcp.tool()
55
- def council_stop(name: str = "") -> str:
55
+ def council_stop(name: str = "", minutes: bool = True, synthesis: str = "") -> str:
56
56
  """Stop a council sitting: kill all soul sessions + the orchestrator.
57
57
 
58
- Prompt history under ``~/.agentwire/council/<name>/prompts/`` is kept.
58
+ Prompt history under ``~/.agentwire/council/<name>/prompts/`` is kept, and
59
+ by default the sitting's minutes artifact is rendered on the way out
60
+ (when any prompt exists) — pass your synthesis so the record includes it.
59
61
 
60
62
  Args:
61
63
  name: Sitting name (empty = cwd-repo-slug / sole live sitting)
64
+ minutes: Render the minutes artifact (default True; skipped anyway
65
+ when the sitting has no prompt history)
66
+ synthesis: Your synthesis for the minutes — text, or a path to a file
62
67
 
63
68
  Returns:
64
- Which sessions were killed.
69
+ Which sessions were killed, plus the minutes path when rendered.
65
70
  """
66
71
  args = ["council", "stop"]
67
72
  if name:
68
73
  args += ["--name", name]
74
+ if not minutes:
75
+ args += ["--no-minutes"]
76
+ if synthesis:
77
+ args += ["--synthesis", synthesis]
69
78
  data = run_agentwire_cmd(args, timeout=60)
70
79
  if not data.get("success"):
71
80
  return f"Failed to stop council: {data.get('error', 'Unknown error')}"
72
81
  killed = data.get("killed") or []
73
- return f"{_council_tag(data)}Council stopped. Killed: {', '.join(killed) or '(none)'}"
82
+ out = f"{_council_tag(data)}Council stopped. Killed: {', '.join(killed) or '(none)'}"
83
+ if data.get("minutes"):
84
+ out += f"\nMinutes: {data['minutes']}"
85
+ return out
74
86
 
75
87
 
76
88
  @mcp.tool()
@@ -191,3 +203,38 @@ def council_collect(prompt_id: int = 0, timeout: int = 120, name: str = "") -> s
191
203
  for r in data.get("replies") or []:
192
204
  lines.append(f"\n--- {r['soul']} ({r['kind']}) ---\n{r['text']}")
193
205
  return "\n".join(lines)
206
+
207
+
208
+ @mcp.tool()
209
+ def council_minutes(name: str = "", prompt: str = "", synthesis: str = "") -> str:
210
+ """Render a sitting's minutes: question, synthesis, verbatim takes → HTML.
211
+
212
+ Deterministically renders the sitting's persisted prompt history
213
+ (question + attributed take/ack/pass replies) plus your optional
214
+ synthesis into a self-contained HTML artifact at
215
+ ``~/.agentwire/artifacts/council-<name>-minutes/index.html``, and opens
216
+ it as a portal artifact window when the portal is up. Works for live and
217
+ dismissed sittings alike — prompt history survives ``council_stop``.
218
+
219
+ Args:
220
+ prompt: Prompt id to render, or 'all' (empty = all)
221
+ synthesis: Your synthesis of the takes — text, or a path to a file
222
+ name: Sitting name (empty = cwd-repo-slug / sole live sitting)
223
+
224
+ Returns:
225
+ The rendered artifact's path, and whether a portal window opened.
226
+ """
227
+ args = ["council", "minutes"]
228
+ if name:
229
+ args += ["--name", name]
230
+ if prompt:
231
+ args += ["--prompt", prompt]
232
+ if synthesis:
233
+ args += ["--synthesis", synthesis]
234
+ data = run_agentwire_cmd(args, timeout=60)
235
+ if not data.get("success"):
236
+ return f"Failed to render minutes: {data.get('error') or data}"
237
+ out = f"{_council_tag(data)}Minutes: {data.get('path')}"
238
+ if data.get("opened"):
239
+ out += "\nOpened as a portal artifact window."
240
+ return out
@@ -19,9 +19,9 @@ def worktree_create(
19
19
 
20
20
  The spawn half of the worktree lifecycle (paired with worktree_status /
21
21
  worktree_list / worktree_remove). Creates a branch off origin/<base>, a
22
- worktree under ~/worktrees/, and a tmux session running an agent with the
23
- worktree-session safety etiquette auto-injected. This is how a Briefing Mode
24
- anchor fans out correspondents.
22
+ worktree at ~/worktrees/<project>/<name>/, and a tmux session running an
23
+ agent with the worktree-session safety etiquette auto-injected. This is how
24
+ a Briefing Mode anchor fans out correspondents.
25
25
 
26
26
  Args:
27
27
  name: Worktree/branch name (becomes the branch + session suffix).
@@ -5,6 +5,7 @@ This file lives in project directories and is the source of truth for session co
5
5
  """
6
6
 
7
7
  import subprocess
8
+ import sys
8
9
  from dataclasses import dataclass, field
9
10
  from enum import Enum
10
11
  from pathlib import Path
@@ -138,6 +139,47 @@ def compose_session_type(harness: str, posture: str) -> str:
138
139
  return harness
139
140
 
140
141
 
142
+ @dataclass
143
+ class WorktreeOverrides:
144
+ """Per-project overrides for `agentwire worktree` (the `worktree:` block).
145
+
146
+ Sits between per-invocation flags and the global config in the
147
+ precedence chain (#705): CLI/MCP flag → this block → global `worktree:`
148
+ in config.yaml → built-ins. ``dir`` only moves the root — the nesting
149
+ shape is unchanged: ``<dir>/<project>/<name>/``.
150
+ """
151
+ dir: Optional[Path] = None # overrides worktree.worktree_dir for this project
152
+ base: Optional[str] = None # overrides worktree.default_base for this project
153
+
154
+
155
+ _WORKTREE_OVERRIDE_KEYS = {"dir", "base"}
156
+
157
+
158
+ def _parse_worktree_overrides(data: Any) -> WorktreeOverrides:
159
+ """Parse the optional ``worktree:`` block. Unknown keys warn, never fail."""
160
+ if not isinstance(data, dict):
161
+ if data is not None:
162
+ print(
163
+ f"Warning: .agentwire.yml `worktree:` should be a mapping "
164
+ f"with dir/base keys, got {type(data).__name__} — ignoring",
165
+ file=sys.stderr,
166
+ )
167
+ return WorktreeOverrides()
168
+ unknown = sorted(set(data) - _WORKTREE_OVERRIDE_KEYS)
169
+ if unknown:
170
+ print(
171
+ f"Warning: unknown key(s) in .agentwire.yml `worktree:` block: "
172
+ f"{', '.join(unknown)} (expected: dir, base)",
173
+ file=sys.stderr,
174
+ )
175
+ dir_val = data.get("dir")
176
+ base_val = data.get("base")
177
+ return WorktreeOverrides(
178
+ dir=Path(str(dir_val)).expanduser() if dir_val else None,
179
+ base=str(base_val) if base_val else None,
180
+ )
181
+
182
+
141
183
  @dataclass
142
184
  class ProjectConfig:
143
185
  """Project-level configuration for a project directory.
@@ -154,6 +196,7 @@ class ProjectConfig:
154
196
  parent: Optional[str] = None # Parent session for hierarchical notifications
155
197
  shell: Optional[str] = None # Default shell for task commands (default: /bin/sh)
156
198
  tasks: dict[str, Any] = field(default_factory=dict) # Task definitions (raw dict, parsed by tasks.py)
199
+ worktree: WorktreeOverrides = field(default_factory=WorktreeOverrides) # `agentwire worktree` overrides (#705)
157
200
 
158
201
  def to_dict(self) -> dict:
159
202
  """Convert to dictionary for YAML serialization."""
@@ -170,6 +213,13 @@ class ProjectConfig:
170
213
  d["shell"] = self.shell
171
214
  if self.tasks:
172
215
  d["tasks"] = self.tasks
216
+ if self.worktree.dir or self.worktree.base:
217
+ wt: dict[str, Any] = {}
218
+ if self.worktree.dir:
219
+ wt["dir"] = str(self.worktree.dir)
220
+ if self.worktree.base:
221
+ wt["base"] = self.worktree.base
222
+ d["worktree"] = wt
173
223
  return d
174
224
 
175
225
  @classmethod
@@ -189,6 +239,7 @@ class ProjectConfig:
189
239
  parent=parent,
190
240
  shell=shell,
191
241
  tasks=tasks if isinstance(tasks, dict) else {},
242
+ worktree=_parse_worktree_overrides(data.get("worktree")),
192
243
  )
193
244
 
194
245
 
@@ -32,3 +32,11 @@ user's prompts out to them, collect their takes, and synthesize.
32
32
  - `council_status` shows roster health if something seems stuck.
33
33
  - Don't editorialize the lenses away. If Critic and Gut disagree, the
34
34
  disagreement *is* the product — surface it.
35
+
36
+ ## Closing the sitting
37
+
38
+ When the user wraps up, stop with your synthesis so the minutes artifact
39
+ carries it: `council_stop(synthesis="<your synthesis>")`. Stop renders the
40
+ minutes (question + verbatim attributed takes + your synthesis) automatically
41
+ whenever any prompt was asked. To (re)render the record at any other moment —
42
+ including for a past sitting — use `council_minutes(synthesis=...)`.