agentwire-dev 1.43.0__tar.gz → 1.44.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 (410) hide show
  1. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/PKG-INFO +2 -1
  2. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/__init__.py +1 -1
  3. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/__main__.py +325 -70
  4. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/cli_safety.py +225 -55
  5. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/config.py +51 -5
  6. agentwire_dev-1.44.0/agentwire/devices.py +395 -0
  7. agentwire_dev-1.44.0/agentwire/hooks/damage-control/mcp-tool-damage-control.py +972 -0
  8. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/hooks/damage-control/rules/aws.yaml +18 -0
  9. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/hooks/damage-control/rules/cloud-hosting.yaml +46 -0
  10. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/hooks/damage-control/rules/containers.yaml +17 -0
  11. agentwire_dev-1.44.0/agentwire/hooks/damage-control/rules/databases.yaml +147 -0
  12. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/hooks/damage-control/rules/gcp.yaml +15 -0
  13. agentwire_dev-1.44.0/agentwire/hooks/damage-control/rules/infrastructure.yaml +51 -0
  14. agentwire_dev-1.44.0/agentwire/hooks/damage-control/rules/outbound.yaml +65 -0
  15. agentwire_dev-1.44.0/agentwire/hooks/damage-control/rules/publish.yaml +40 -0
  16. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/limits_cli.py +18 -5
  17. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/scheduler.py +180 -20
  18. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/security.py +161 -19
  19. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/server.py +130 -36
  20. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/services.py +6 -2
  21. agentwire_dev-1.44.0/agentwire/session_context.py +420 -0
  22. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/static/css/desktop.css +72 -93
  23. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/static/js/safety-shared.js +3 -67
  24. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/static/js/safety-window.js +10 -27
  25. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/static/js/sidebar/safety-section.js +8 -27
  26. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/static/js/sidebar/sessions-section.js +75 -1
  27. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/static/js/token-modal.js +1 -1
  28. agentwire_dev-1.44.0/agentwire/templates/pair.html +86 -0
  29. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/docs/wiki/INDEX.md +1 -0
  30. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/docs/wiki/deployment/remote-access.md +11 -0
  31. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/docs/wiki/internals/damage-control.md +115 -8
  32. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/docs/wiki/scheduling/scheduled-workloads.md +7 -0
  33. agentwire_dev-1.44.0/docs/wiki/security/remote-access-hardening.md +273 -0
  34. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/pyproject.toml +4 -0
  35. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/tests/conftest.py +16 -0
  36. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/tests/integration/test_scheduler_board.py +172 -0
  37. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/tests/unit/test_damage_control_hooks.py +236 -0
  38. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/tests/unit/test_damage_control_sync.py +1 -0
  39. agentwire_dev-1.44.0/tests/unit/test_devices.py +208 -0
  40. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/tests/unit/test_portal_api.py +149 -0
  41. agentwire_dev-1.44.0/tests/unit/test_rebuild_guard.py +134 -0
  42. agentwire_dev-1.44.0/tests/unit/test_safety_heal.py +158 -0
  43. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/tests/unit/test_security.py +120 -0
  44. agentwire_dev-1.44.0/tests/unit/test_session_context.py +307 -0
  45. agentwire_dev-1.43.0/agentwire/hooks/damage-control/rules/databases.yaml +0 -52
  46. agentwire_dev-1.43.0/agentwire/hooks/damage-control/rules/infrastructure.yaml +0 -21
  47. agentwire_dev-1.43.0/agentwire/session_context.py +0 -196
  48. agentwire_dev-1.43.0/tests/unit/test_session_context.py +0 -96
  49. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/.agents/skills/agentwire-cli/SKILL.md +0 -0
  50. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/.agents/skills/agentwire-config/SKILL.md +0 -0
  51. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/.agents/skills/agentwire-desktop-ui/SKILL.md +0 -0
  52. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/.agents/skills/agentwire-mcp-tools/SKILL.md +0 -0
  53. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/.agents/skills/agentwire-pi/SKILL.md +0 -0
  54. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/.agents/skills/agentwire-project-config/SKILL.md +0 -0
  55. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/.agents/skills/agentwire-scheduler/SKILL.md +0 -0
  56. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/.agents/skills/wiki/SKILL.md +0 -0
  57. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/.github/FUNDING.yml +0 -0
  58. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
  59. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
  60. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/.github/ISSUE_TEMPLATE/question.md +0 -0
  61. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
  62. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/.github/workflows/pytest.yml +0 -0
  63. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/.github/workflows/tts-smoke.yml +0 -0
  64. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/.gitignore +0 -0
  65. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/AGENTS.md +0 -0
  66. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/CLA.md +0 -0
  67. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/CODE_OF_CONDUCT.md +0 -0
  68. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/CONTRIBUTING.md +0 -0
  69. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/Dockerfile.local +0 -0
  70. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/Dockerfile.runpod +0 -0
  71. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/LICENSE +0 -0
  72. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/README.md +0 -0
  73. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/RELEASING.md +0 -0
  74. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/SECURITY.md +0 -0
  75. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/SPONSORS.md +0 -0
  76. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/agents/__init__.py +0 -0
  77. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/agents/base.py +0 -0
  78. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/agents/tmux.py +0 -0
  79. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/cached_status.py +0 -0
  80. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/channels/__init__.py +0 -0
  81. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/channels/base.py +0 -0
  82. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/channels/email.py +0 -0
  83. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/channels/quo.py +0 -0
  84. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/completion.py +0 -0
  85. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/council/__init__.py +0 -0
  86. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/council/cli.py +0 -0
  87. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/council/inbox.py +0 -0
  88. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/council/state.py +0 -0
  89. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/council/view.py +0 -0
  90. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/doctor_voice.py +0 -0
  91. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/fetch.py +0 -0
  92. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/handoff/__init__.py +0 -0
  93. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/handoff/git_state.py +0 -0
  94. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/handoff/instructions.py +0 -0
  95. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/handoff/parser.py +0 -0
  96. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/handoff/renderer.py +0 -0
  97. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/handoff/schema.py +0 -0
  98. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/history.py +0 -0
  99. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/hooks/__init__.py +0 -0
  100. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/hooks/agentwire-permission.sh +0 -0
  101. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/hooks/damage-control/__init__.py +0 -0
  102. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/hooks/damage-control/audit_logger.py +0 -0
  103. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/hooks/damage-control/bash-tool-damage-control.py +0 -0
  104. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/hooks/damage-control/edit-tool-damage-control.py +0 -0
  105. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/hooks/damage-control/rules/agentwire.yaml +0 -0
  106. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/hooks/damage-control/rules/core.yaml +0 -0
  107. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/hooks/damage-control/rules/firebase.yaml +0 -0
  108. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/hooks/damage-control/rules/git.yaml +0 -0
  109. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/hooks/damage-control/rules/gws.yaml +0 -0
  110. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/hooks/damage-control/rules/remote.yaml +0 -0
  111. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/hooks/damage-control/write-tool-damage-control.py +0 -0
  112. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/hooks/idle-handler.sh +0 -0
  113. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/hooks/queue-processor.sh +0 -0
  114. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/inbox.py +0 -0
  115. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/listen.py +0 -0
  116. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/locking.py +0 -0
  117. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/mcp_server.py +0 -0
  118. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/msg_cli.py +0 -0
  119. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/network.py +0 -0
  120. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/onboarding.py +0 -0
  121. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/pane_manager.py +0 -0
  122. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/project_config.py +0 -0
  123. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/projects.py +0 -0
  124. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/prompt_router.py +0 -0
  125. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/prompts/__init__.py +0 -0
  126. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/prompts/init.md +0 -0
  127. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/prompts_cli.py +0 -0
  128. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/research.py +0 -0
  129. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/roles/__init__.py +0 -0
  130. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/roles/agentwire.md +0 -0
  131. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/roles/anchor.md +0 -0
  132. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/roles/chatbot.md +0 -0
  133. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/roles/correspondent.md +0 -0
  134. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/roles/council-brain.md +0 -0
  135. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/roles/council-conscience.md +0 -0
  136. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/roles/council-critic.md +0 -0
  137. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/roles/council-devils-advocate.md +0 -0
  138. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/roles/council-gut.md +0 -0
  139. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/roles/council-historian.md +0 -0
  140. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/roles/council-member.md +0 -0
  141. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/roles/council-orchestrator.md +0 -0
  142. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/roles/init.md +0 -0
  143. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/roles/notifications.md +0 -0
  144. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/roles/orchestrator.md +0 -0
  145. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/roles/soul.md +0 -0
  146. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/roles/task-runner.md +0 -0
  147. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/roles/voice.md +0 -0
  148. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/roles/worker.md +0 -0
  149. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/roles/worktree-session.md +0 -0
  150. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/safety/__init__.py +0 -0
  151. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/safety/_core.py +0 -0
  152. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/scratchpad.py +0 -0
  153. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/session_ready.py +0 -0
  154. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/ssh.py +0 -0
  155. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/static/agentwire-Echo--black.png +0 -0
  156. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/static/agentwire-Echo--transparent.png +0 -0
  157. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/static/agentwire-Echo.png +0 -0
  158. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/static/agentwire-email-banner.png +0 -0
  159. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/static/agentwire-splash-logo-layers--agentwire-text.png +0 -0
  160. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/static/agentwire-splash-logo-layers--echo-claw-fg.png +0 -0
  161. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/static/agentwire-splash-logo-layers--echo.png +0 -0
  162. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/static/agentwire-splash-logo-layers--full--transparent-top.png +0 -0
  163. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/static/agentwire-splash-logo-layers--full-black.png +0 -0
  164. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/static/agentwire-splash-logo-layers--telephone-fg.png +0 -0
  165. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/static/agentwire-splash-logo-layers--telephone.png +0 -0
  166. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/static/agentwire-splash-logo-layers--transparent-top.png +0 -0
  167. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/static/agentwire-splash-logo-layers--transparent.png +0 -0
  168. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/static/agentwire-splash-logo-layers--tree.png +0 -0
  169. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/static/agentwire-splash-logo-layers.png +0 -0
  170. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/static/announcements.json +0 -0
  171. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/static/css/mobile.css +0 -0
  172. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/static/favicon.png +0 -0
  173. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/static/icons/machines/android.jpeg +0 -0
  174. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/static/icons/machines/automaton.jpeg +0 -0
  175. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/static/icons/machines/bot.jpeg +0 -0
  176. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/static/icons/machines/cyborg.jpeg +0 -0
  177. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/static/icons/machines/droid.jpeg +0 -0
  178. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/static/icons/machines/drone.jpeg +0 -0
  179. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/static/icons/machines/guardian.jpeg +0 -0
  180. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/static/icons/machines/mech.jpeg +0 -0
  181. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/static/icons/machines/probe.jpeg +0 -0
  182. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/static/icons/machines/robot.jpeg +0 -0
  183. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/static/icons/machines/sentinel.jpeg +0 -0
  184. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/static/icons/machines/unit.jpeg +0 -0
  185. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/static/icons/projects/blob.jpeg +0 -0
  186. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/static/icons/projects/cloud.jpeg +0 -0
  187. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/static/icons/projects/crystal.jpeg +0 -0
  188. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/static/icons/projects/cyclops.jpeg +0 -0
  189. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/static/icons/projects/flame.jpeg +0 -0
  190. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/static/icons/projects/fuzzy.jpeg +0 -0
  191. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/static/icons/projects/horned.jpeg +0 -0
  192. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/static/icons/projects/moon.jpeg +0 -0
  193. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/static/icons/projects/slime.jpeg +0 -0
  194. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/static/icons/projects/star.jpeg +0 -0
  195. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/static/icons/projects/tentacle.jpeg +0 -0
  196. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/static/icons/projects/winged.jpeg +0 -0
  197. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/static/icons/sessions/bear.jpeg +0 -0
  198. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/static/icons/sessions/cat.jpeg +0 -0
  199. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/static/icons/sessions/crown.jpeg +0 -0
  200. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/static/icons/sessions/custom/agentwire-portal.png +0 -0
  201. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/static/icons/sessions/custom/agentwire-tts.png +0 -0
  202. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/static/icons/sessions/custom/agentwire.png +0 -0
  203. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/static/icons/sessions/deer.jpeg +0 -0
  204. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/static/icons/sessions/drone.jpeg +0 -0
  205. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/static/icons/sessions/eagle.jpeg +0 -0
  206. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/static/icons/sessions/fox.jpeg +0 -0
  207. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/static/icons/sessions/hawk.jpeg +0 -0
  208. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/static/icons/sessions/horse.jpeg +0 -0
  209. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/static/icons/sessions/lion.jpeg +0 -0
  210. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/static/icons/sessions/rabbit.jpeg +0 -0
  211. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/static/icons/sessions/robot.jpeg +0 -0
  212. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/static/icons/sessions/tiger.jpeg +0 -0
  213. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/static/icons/sessions/wolf.jpeg +0 -0
  214. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/static/js/.gitkeep +0 -0
  215. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/static/js/announcement-modal.js +0 -0
  216. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/static/js/api.js +0 -0
  217. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/static/js/artifact-window.js +0 -0
  218. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/static/js/collage.js +0 -0
  219. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/static/js/command-palette.js +0 -0
  220. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/static/js/components/icon-picker.js +0 -0
  221. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/static/js/components/list-card.js +0 -0
  222. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/static/js/components/type-tag.js +0 -0
  223. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/static/js/council-window.js +0 -0
  224. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/static/js/dead-key-suppressor.js +0 -0
  225. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/static/js/desktop-manager.js +0 -0
  226. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/static/js/desktop.js +0 -0
  227. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/static/js/icon-manager.js +0 -0
  228. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/static/js/mobile.js +0 -0
  229. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/static/js/notification-prefs.js +0 -0
  230. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/static/js/notifications-panel.js +0 -0
  231. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/static/js/scratchpad.js +0 -0
  232. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/static/js/service-classification.js +0 -0
  233. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/static/js/session-id.js +0 -0
  234. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/static/js/session-window.js +0 -0
  235. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/static/js/sidebar/artifacts-section.js +0 -0
  236. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/static/js/sidebar/config-section.js +0 -0
  237. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/static/js/sidebar/council-section.js +0 -0
  238. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/static/js/sidebar/machines-section.js +0 -0
  239. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/static/js/sidebar/projects-section.js +0 -0
  240. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/static/js/sidebar/scheduler-section.js +0 -0
  241. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/static/js/sidebar/services-section.js +0 -0
  242. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/static/js/sidebar.js +0 -0
  243. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/static/js/terminal-font-prefs.js +0 -0
  244. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/static/js/tile-manager.js +0 -0
  245. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/static/js/toast.js +0 -0
  246. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/static/js/utils/ansi.js +0 -0
  247. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/static/js/utils/auto-refresh.js +0 -0
  248. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/static/js/utils/swipe.js +0 -0
  249. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/static/js/voice/autosend-prefs.js +0 -0
  250. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/static/js/voice/browser-stt.js +0 -0
  251. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/static/js/voice/browser-tts.js +0 -0
  252. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/static/js/voice/jargon.js +0 -0
  253. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/static/js/voice/prompt.js +0 -0
  254. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/static/js/winbox.bundle.min.js +0 -0
  255. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/stt/__init__.py +0 -0
  256. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/stt/base.py +0 -0
  257. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/stt/cloud.py +0 -0
  258. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/stt/engine.py +0 -0
  259. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/stt/local.py +0 -0
  260. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/stt/server_backend.py +0 -0
  261. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/stt/stt_server.py +0 -0
  262. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/tasks.py +0 -0
  263. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/templates/__init__.py +0 -0
  264. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/templates/base.html +0 -0
  265. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/templates/desktop.html +0 -0
  266. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/templates/email_notification.html +0 -0
  267. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/templates/handoff/show-the-story.html.j2 +0 -0
  268. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/templates/handoff/theme.css.j2 +0 -0
  269. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/templates/mobile.html +0 -0
  270. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/templates/tmux.conf +0 -0
  271. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/templating.py +0 -0
  272. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/tooldefs/aws.yaml +0 -0
  273. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/tooldefs/docker.yaml +0 -0
  274. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/tooldefs/gcp.yaml +0 -0
  275. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/tooldefs/gh.yaml +0 -0
  276. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/tooldefs/git.yaml +0 -0
  277. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/tooldefs/gws.yaml +0 -0
  278. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/tooldefs/kubectl.yaml +0 -0
  279. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/tooldefs/npm.yaml +0 -0
  280. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/tooldefs/terraform.yaml +0 -0
  281. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/tooldefs/uv.yaml +0 -0
  282. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/tts/__init__.py +0 -0
  283. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/tts/audio.py +0 -0
  284. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/tts/base.py +0 -0
  285. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/tts/engines/__init__.py +0 -0
  286. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/tts/engines/chatterbox.py +0 -0
  287. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/tts/engines/kokoro.py +0 -0
  288. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/tts/engines/qwen_base.py +0 -0
  289. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/tts/engines/qwen_custom.py +0 -0
  290. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/tts/engines/qwen_design.py +0 -0
  291. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/tts/engines/zonos.py +0 -0
  292. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/tts/kokoro_server.py +0 -0
  293. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/tts/local.py +0 -0
  294. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/tts/registry.py +0 -0
  295. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/tts_server.py +0 -0
  296. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/tunnels.py +0 -0
  297. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/usage_limit.py +0 -0
  298. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/utils/__init__.py +0 -0
  299. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/utils/chunker.py +0 -0
  300. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/utils/file_io.py +0 -0
  301. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/utils/paths.py +0 -0
  302. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/utils/speech.py +0 -0
  303. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/utils/subprocess.py +0 -0
  304. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/validation.py +0 -0
  305. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/voice_status.py +0 -0
  306. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/voiceclone.py +0 -0
  307. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/voices/darren.wav +0 -0
  308. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/voices/default.wav +0 -0
  309. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/voices/jessica.wav +0 -0
  310. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/voices/lisa.wav +0 -0
  311. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/voices/may.wav +0 -0
  312. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/wiki_audit.py +0 -0
  313. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/worktree.py +0 -0
  314. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/agentwire/worktree_registry.py +0 -0
  315. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/docs/decisions/obsidian-second-brain.md +0 -0
  316. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/docs/logo.png +0 -0
  317. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/docs/wiki/architecture.md +0 -0
  318. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/docs/wiki/briefing-mode.md +0 -0
  319. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/docs/wiki/communication/channels.md +0 -0
  320. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/docs/wiki/communication/hammerspoon.md +0 -0
  321. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/docs/wiki/communication/handoff.md +0 -0
  322. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/docs/wiki/concepts.md +0 -0
  323. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/docs/wiki/council.md +0 -0
  324. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/docs/wiki/deployment/remote-machines.md +0 -0
  325. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/docs/wiki/glossary.md +0 -0
  326. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/docs/wiki/integrations/gws-google-workspace-cli.md +0 -0
  327. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/docs/wiki/internals/portal.md +0 -0
  328. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/docs/wiki/internals/shell-escaping.md +0 -0
  329. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/docs/wiki/internals/troubleshooting.md +0 -0
  330. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/docs/wiki/internals/window-collage.md +0 -0
  331. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/docs/wiki/quickstart.md +0 -0
  332. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/docs/wiki/research/briefing-mode-feasibility.md +0 -0
  333. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/docs/wiki/research/orchestration-transport-alternatives.md +0 -0
  334. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/docs/wiki/security/secrets.md +0 -0
  335. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/docs/wiki/services.md +0 -0
  336. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/docs/wiki/sessions/claude-code-auto-mode.md +0 -0
  337. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/docs/wiki/sessions/messaging.md +0 -0
  338. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/docs/wiki/sessions/pi.md +0 -0
  339. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/docs/wiki/sessions/prompt-routing.md +0 -0
  340. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/docs/wiki/sessions/window-sizing.md +0 -0
  341. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/docs/wiki/sessions/worktree-sessions.md +0 -0
  342. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/docs/wiki/usage-limit-recovery.md +0 -0
  343. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/docs/wiki/voice/shim-contract.md +0 -0
  344. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/docs/wiki/voice/stt-cloud.md +0 -0
  345. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/docs/wiki/voice/stt-self-hosted.md +0 -0
  346. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/docs/wiki/voice/tts-self-hosted.md +0 -0
  347. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/requirements-tts.txt +0 -0
  348. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/tests/e2e/test_portal_ui.py +0 -0
  349. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/tests/fixtures/sample_agentwire.yml +0 -0
  350. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/tests/fixtures/sample_config.yaml +0 -0
  351. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/tests/fixtures/sample_scheduler.yaml +0 -0
  352. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/tests/integration/test_council_portal.py +0 -0
  353. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/tests/integration/test_server_websockets.py +0 -0
  354. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/tests/integration/test_worktree_cmd.py +0 -0
  355. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/tests/unit/test_announcements.py +0 -0
  356. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/tests/unit/test_build_agent_command.py +0 -0
  357. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/tests/unit/test_channels.py +0 -0
  358. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/tests/unit/test_cli_commands.py +0 -0
  359. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/tests/unit/test_cli_output.py +0 -0
  360. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/tests/unit/test_cli_safety.py +0 -0
  361. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/tests/unit/test_config.py +0 -0
  362. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/tests/unit/test_council_cli.py +0 -0
  363. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/tests/unit/test_council_inbox.py +0 -0
  364. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/tests/unit/test_council_state.py +0 -0
  365. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/tests/unit/test_council_view.py +0 -0
  366. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/tests/unit/test_doctor_voice.py +0 -0
  367. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/tests/unit/test_file_io.py +0 -0
  368. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/tests/unit/test_handoff_git_state.py +0 -0
  369. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/tests/unit/test_handoff_instructions.py +0 -0
  370. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/tests/unit/test_handoff_parser.py +0 -0
  371. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/tests/unit/test_handoff_renderer.py +0 -0
  372. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/tests/unit/test_history.py +0 -0
  373. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/tests/unit/test_hooks_install.py +0 -0
  374. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/tests/unit/test_idle_handler.py +0 -0
  375. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/tests/unit/test_inbox.py +0 -0
  376. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/tests/unit/test_locking.py +0 -0
  377. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/tests/unit/test_mcp_server.py +0 -0
  378. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/tests/unit/test_mcp_tools_args.py +0 -0
  379. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/tests/unit/test_msg_cli.py +0 -0
  380. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/tests/unit/test_project_config.py +0 -0
  381. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/tests/unit/test_prompt_router.py +0 -0
  382. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/tests/unit/test_roles.py +0 -0
  383. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/tests/unit/test_safety_disabled_rules.py +0 -0
  384. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/tests/unit/test_safety_escape_hatch.py +0 -0
  385. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/tests/unit/test_safety_kill_switch.py +0 -0
  386. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/tests/unit/test_scheduler.py +0 -0
  387. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/tests/unit/test_scheduler_parsing.py +0 -0
  388. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/tests/unit/test_scratchpad.py +0 -0
  389. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/tests/unit/test_server_async.py +0 -0
  390. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/tests/unit/test_server_pure.py +0 -0
  391. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/tests/unit/test_services.py +0 -0
  392. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/tests/unit/test_session_ready.py +0 -0
  393. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/tests/unit/test_speech_tags.py +0 -0
  394. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/tests/unit/test_ssh.py +0 -0
  395. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/tests/unit/test_stt_backend.py +0 -0
  396. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/tests/unit/test_stt_cloud.py +0 -0
  397. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/tests/unit/test_stt_engine.py +0 -0
  398. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/tests/unit/test_task_cli.py +0 -0
  399. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/tests/unit/test_tasks.py +0 -0
  400. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/tests/unit/test_templating.py +0 -0
  401. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/tests/unit/test_terminal_resize.py +0 -0
  402. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/tests/unit/test_tmux_template.py +0 -0
  403. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/tests/unit/test_tts_engine_resolution.py +0 -0
  404. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/tests/unit/test_tts_local.py +0 -0
  405. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/tests/unit/test_usage_limit.py +0 -0
  406. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/tests/unit/test_validation.py +0 -0
  407. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/tests/unit/test_voice_status.py +0 -0
  408. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/tests/unit/test_wiki_audit.py +0 -0
  409. {agentwire_dev-1.43.0 → agentwire_dev-1.44.0}/tests/unit/test_worktree.py +0 -0
  410. {agentwire_dev-1.43.0 → agentwire_dev-1.44.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.43.0
3
+ Version: 1.44.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
@@ -694,6 +694,7 @@ Requires-Dist: mcp>=1.2.0
694
694
  Requires-Dist: pydantic>=2.0.0
695
695
  Requires-Dist: python-dotenv>=1.0.0
696
696
  Requires-Dist: pyyaml>=6.0
697
+ Requires-Dist: qrcode>=7.4
697
698
  Requires-Dist: requests>=2.28.0
698
699
  Requires-Dist: resend>=2.0.0
699
700
  Requires-Dist: useful-moonshine-onnx>=20250101; python_version < '3.14'
@@ -1,3 +1,3 @@
1
1
  """AgentWire - Multi-session voice web interface for AI coding agents."""
2
2
 
3
- __version__ = "1.43.0"
3
+ __version__ = "1.44.0"
@@ -820,9 +820,6 @@ def _start_portal_local(args, attach: bool = True) -> int:
820
820
  When attach is False (used by `agentwire up`), the portal is started
821
821
  detached and we return without attaching.
822
822
  """
823
- from .network import NetworkContext
824
- from .tunnels import TunnelManager
825
-
826
823
  session_name = get_portal_session_name()
827
824
 
828
825
  if tmux_session_exists(session_name):
@@ -832,31 +829,10 @@ def _start_portal_local(args, attach: bool = True) -> int:
832
829
  subprocess.run(["tmux", "attach-session", "-t", session_name])
833
830
  return 0
834
831
 
835
- # Ensure required tunnels are up before starting portal
836
- ctx = NetworkContext.from_config()
837
- required_tunnels = ctx.get_required_tunnels()
838
-
839
- if required_tunnels:
840
- print("Ensuring tunnels to remote services...")
841
- tm = TunnelManager()
842
-
843
- for spec in required_tunnels:
844
- status = tm.check_tunnel(spec)
845
-
846
- if status.status == "up":
847
- print(f" [ok] {spec.remote_machine}:{spec.remote_port} (already up)")
848
- else:
849
- print(f" [..] Creating tunnel to {spec.remote_machine}:{spec.remote_port}...", end=" ", flush=True)
850
- result = tm.create_tunnel(spec, ctx)
851
-
852
- if result.status == "up":
853
- print("[ok]")
854
- else:
855
- print("[!!]")
856
- print(f" Warning: Could not create tunnel: {result.error}")
857
- print(f" The portal may not be able to reach {spec.remote_machine}.")
858
-
859
- print()
832
+ # No tunnel auto-spawn (#420): agentwire owns only the local portal
833
+ # boundary. Reaching the portal from elsewhere is bring-your-own
834
+ # (cloudflared/tailscale/ssh -L), and `agentwire tunnels *` remains as an
835
+ # opt-in manual helper for the vestigial remote-service-split case.
860
836
 
861
837
  # Build the server command
862
838
  # --dev runs from source with uv run (picks up code changes immediately)
@@ -1224,6 +1200,80 @@ def cmd_portal_token(args) -> int:
1224
1200
  return 0
1225
1201
 
1226
1202
 
1203
+ def cmd_portal_pair(args) -> int:
1204
+ """Create a short-lived pairing code (+ QR) for a new device."""
1205
+ from .devices import PAIRING_TTL_SECONDS, create_pairing
1206
+
1207
+ pairing = create_pairing(name=getattr(args, "name", None) or "device")
1208
+
1209
+ portal_url = _default_portal_url()
1210
+ pair_url = f"{portal_url}/pair?code={pairing.code}"
1211
+ ttl_min = PAIRING_TTL_SECONDS // 60
1212
+
1213
+ print(f"Pairing code: {pairing.code}")
1214
+ print(f" Name: {pairing.name}")
1215
+ print(f" Expires in {ttl_min} minutes.")
1216
+ print()
1217
+ print("On the device, open:")
1218
+ print(f" {pair_url}")
1219
+ print("or visit", f"{portal_url}/pair", "and enter the code.")
1220
+ print()
1221
+
1222
+ try:
1223
+ import qrcode # type: ignore
1224
+
1225
+ qr = qrcode.QRCode(border=1)
1226
+ qr.add_data(pair_url)
1227
+ qr.make()
1228
+ qr.print_ascii(invert=True)
1229
+ except Exception:
1230
+ print("(install `qrcode` to render a scannable QR here)")
1231
+
1232
+ return 0
1233
+
1234
+
1235
+ def cmd_portal_devices(args) -> int:
1236
+ """List paired portal devices."""
1237
+ from .devices import DeviceRegistry
1238
+
1239
+ registry = DeviceRegistry.load()
1240
+ json_mode = getattr(args, "json", False)
1241
+
1242
+ if json_mode:
1243
+ _output_json({"success": True, "devices": [d.public() for d in registry.devices]})
1244
+ return 0
1245
+
1246
+ if not registry.devices:
1247
+ print("No paired devices. The host bootstrap token (agentwire portal token)")
1248
+ print("is the only credential. Add one with: agentwire portal pair")
1249
+ return 0
1250
+
1251
+ print(f"{'ID':<14}{'NAME':<24}{'LAST SEEN':<22}STATUS")
1252
+ for d in registry.devices:
1253
+ status = "revoked" if d.revoked else "active"
1254
+ print(
1255
+ f"{d.id:<14}{(d.name or '')[:23]:<24}"
1256
+ f"{(d.last_seen or 'never'):<22}{status}"
1257
+ )
1258
+ return 0
1259
+
1260
+
1261
+ def cmd_portal_revoke(args) -> int:
1262
+ """Revoke one paired device without affecting the others."""
1263
+ from .devices import DeviceRegistry
1264
+
1265
+ registry = DeviceRegistry.load()
1266
+ if registry.revoke(args.device_id):
1267
+ print(f"Revoked device '{args.device_id}'. It now gets 401 on every route.")
1268
+ return 0
1269
+ print(
1270
+ f"No active device with id '{args.device_id}'. "
1271
+ "List them with: agentwire portal devices",
1272
+ file=sys.stderr,
1273
+ )
1274
+ return 1
1275
+
1276
+
1227
1277
  def cmd_portal_restart(args) -> int:
1228
1278
  """Restart the AgentWire portal (stop + start)."""
1229
1279
  import time
@@ -3005,6 +3055,30 @@ def _record_session_creator(session_name: str, created_by: str | None, via: str)
3005
3055
  store_session_metadata(session_name, metadata)
3006
3056
 
3007
3057
 
3058
+ def _display_parent(session_name: str, path: str = "") -> "str | None":
3059
+ """The session that should visually own this one in the sidebar.
3060
+
3061
+ Display-only relationship (powers sidebar nesting, issue #448) — NOT a
3062
+ lifecycle coupling. Mirrors prompt_router.resolve_parent's precedence for
3063
+ pane-0 sessions, minus the liveness check (the sidebar decides whether to
3064
+ nest based on whether the parent is actually in the list):
3065
+ 1. Creator recorded at `agentwire new` time (session metadata).
3066
+ 2. `.agentwire.yml` `parent:` field (from the session's path).
3067
+ Returns None for top-level sessions (no recorded parent).
3068
+ """
3069
+ bare = session_name.split("@")[0]
3070
+ creator = load_session_metadata(bare).get("created_by")
3071
+ if isinstance(creator, str) and creator and creator != bare:
3072
+ return creator
3073
+ try:
3074
+ parent = get_parent_from_config(Path(path) if path else None)
3075
+ except Exception:
3076
+ parent = None
3077
+ if parent and parent != bare:
3078
+ return parent
3079
+ return None
3080
+
3081
+
3008
3082
  def cmd_notify(args) -> int:
3009
3083
  """Send a notification to the portal about session/pane state changes.
3010
3084
 
@@ -3347,6 +3421,7 @@ def cmd_list(args) -> int:
3347
3421
  "machine": None,
3348
3422
  "type": cfg.get("type"),
3349
3423
  "roles": cfg.get("roles", []),
3424
+ "parent": _display_parent(parts[0], path),
3350
3425
  }
3351
3426
  if usage_limit_parked(parts[0]):
3352
3427
  session_info["usage_limit"] = True
@@ -6248,8 +6323,11 @@ def cmd_machine_add(args) -> int:
6248
6323
  print()
6249
6324
  print("Next steps:")
6250
6325
  print(" 1. Ensure SSH access: ssh", f"{user}@{host}" if user else host)
6251
- print(" 2. Start tunnel: autossh -M 0 -f -N -R 8765:localhost:8765", machine_id)
6252
- print(" 3. Restart portal: agentwire portal stop && agentwire portal start")
6326
+ print(" 2. Restart portal: agentwire portal stop && agentwire portal start")
6327
+ print()
6328
+ print("Remote session management uses plain SSH — no tunnel needed. To reach")
6329
+ print("the portal from another network, bring your own tunnel (cloudflared/")
6330
+ print("tailscale); see docs/wiki/deployment/remote-access.md.")
6253
6331
  print()
6254
6332
  print("For full setup guide, run: /machine-setup in a Claude session")
6255
6333
 
@@ -6287,28 +6365,6 @@ def cmd_machine_remove(args) -> int:
6287
6365
  print(f"Removing machine '{machine_id}' (host: {host})...")
6288
6366
  print()
6289
6367
 
6290
- # Step 2: Kill autossh tunnel
6291
- print("Stopping tunnel...")
6292
- result = subprocess.run(
6293
- ["pkill", "-f", f"autossh.*{machine_id}"],
6294
- capture_output=True,
6295
- )
6296
- if result.returncode == 0:
6297
- print(f" ✓ Killed autossh tunnel for {machine_id}")
6298
- else:
6299
- # Also try by host if different from id
6300
- if host != machine_id:
6301
- result = subprocess.run(
6302
- ["pkill", "-f", f"autossh.*{host}"],
6303
- capture_output=True,
6304
- )
6305
- if result.returncode == 0:
6306
- print(f" ✓ Killed autossh tunnel for {host}")
6307
- else:
6308
- print(" - No tunnel running (or already stopped)")
6309
- else:
6310
- print(" - No tunnel running (or already stopped)")
6311
-
6312
6368
  # Step 3: Remove from machines.json
6313
6369
  print("Updating machines.json...")
6314
6370
  machines_data["machines"] = [m for m in machines if m.get("id") != machine_id]
@@ -6326,21 +6382,17 @@ def cmd_machine_remove(args) -> int:
6326
6382
  print("1. Remove SSH config entry:")
6327
6383
  print(f" Edit ~/.ssh/config and remove the 'Host {machine_id}' block")
6328
6384
  print()
6329
- print("2. Remove from tunnel startup script (if using):")
6330
- print(" Edit ~/.local/bin/agentwire-tunnels")
6331
- print(f" Remove '{machine_id}' from the MACHINES list")
6332
- print()
6333
- print("3. Delete GitHub deploy keys:")
6385
+ print("2. Delete GitHub deploy keys:")
6334
6386
  print(" gh repo deploy-key list --repo <user>/<repo>")
6335
6387
  print(f" # Find keys titled '{machine_id}' and delete them:")
6336
6388
  print(" gh repo deploy-key delete <key-id> --repo <user>/<repo>")
6337
6389
  print()
6338
- print("4. Destroy remote machine:")
6390
+ print("3. Destroy remote machine:")
6339
6391
  print(" Option A: Delete user only")
6340
6392
  print(" ssh root@<ip> 'pkill -u agentwire; userdel -r agentwire'")
6341
6393
  print(" Option B: Destroy the VM entirely via provider console")
6342
6394
  print()
6343
- print("5. Restart portal to pick up changes:")
6395
+ print("4. Restart portal to pick up changes:")
6344
6396
  print(" agentwire portal stop && agentwire portal start")
6345
6397
  print()
6346
6398
 
@@ -7062,7 +7114,7 @@ def cmd_safety_logs(args) -> int:
7062
7114
 
7063
7115
  def cmd_safety_install(args) -> int:
7064
7116
  """CLI command: agentwire safety install"""
7065
- return cli_safety.safety_install_cmd()
7117
+ return cli_safety.safety_install_cmd(assume_yes=getattr(args, "yes", False))
7066
7118
 
7067
7119
 
7068
7120
  def cmd_safety_tooldefs_list(args) -> int:
@@ -7075,6 +7127,79 @@ def cmd_safety_tooldefs_show(args) -> int:
7075
7127
  return cli_safety.safety_tooldefs_show_cmd(args.tool)
7076
7128
 
7077
7129
 
7130
+ def _render_damage_control_section() -> int:
7131
+ """Print the damage-control health block. Returns the count of issues found.
7132
+
7133
+ Covers the four #462 blind spots plus DC hook staleness: the global kill
7134
+ switch (``safety.enabled: false``), installed-rules drift vs the bundled
7135
+ rules, PreToolUse matcher registration, and DC hook-script staleness.
7136
+ """
7137
+ issues = 0
7138
+
7139
+ # Kill switch — config.safety.enabled gates ALL damage control. A silent
7140
+ # `false` is the loudest possible failure, so flag it first and hard.
7141
+ try:
7142
+ from .config import load_config as _load_config_typed
7143
+ safety_enabled = _load_config_typed().safety.enabled
7144
+ except Exception as e:
7145
+ print(f" [..] Could not read safety config: {e}")
7146
+ safety_enabled = True
7147
+ if not safety_enabled:
7148
+ print(" [!!] Damage control is DISABLED (safety.enabled: false)")
7149
+ print(" ALL command/path/outbound gating is off.")
7150
+ print(" Fix: set safety.enabled: true in ~/.agentwire/config.yaml")
7151
+ issues += 1
7152
+ else:
7153
+ print(" [ok] Damage control enabled (safety.enabled: true)")
7154
+
7155
+ try:
7156
+ from . import cli_safety
7157
+ except Exception as e:
7158
+ print(f" [..] Could not load safety module: {e}")
7159
+ return issues
7160
+
7161
+ # DC hook-script staleness (bash/edit/write/mcp-tool + audit_logger).
7162
+ hook_drift = cli_safety.damage_control_hook_drift()
7163
+ stale_hooks = [f for f, s in hook_drift.items() if s == "stale"]
7164
+ missing_hooks = [f for f, s in hook_drift.items() if s == "missing"]
7165
+ if stale_hooks or missing_hooks:
7166
+ if missing_hooks:
7167
+ print(f" [!!] DC hook scripts missing: {', '.join(sorted(missing_hooks))}")
7168
+ if stale_hooks:
7169
+ print(f" [!!] DC hook scripts STALE: {', '.join(sorted(stale_hooks))}")
7170
+ print(" Fix: agentwire safety install --yes")
7171
+ issues += 1
7172
+ else:
7173
+ print(" [ok] DC hook scripts current")
7174
+
7175
+ # Installed-rules drift vs bundled rules (the incident's missing files).
7176
+ rule_drift = cli_safety.rules_drift()
7177
+ missing_rules = [f for f, s in rule_drift.items() if s == "missing"]
7178
+ stale_rules = [f for f, s in rule_drift.items() if s == "stale"]
7179
+ if missing_rules:
7180
+ print(f" [!!] Damage-control rules NOT installed: {', '.join(sorted(missing_rules))}")
7181
+ print(" Fix: agentwire safety install --yes")
7182
+ issues += 1
7183
+ elif stale_rules:
7184
+ # Stale = installed copy differs from bundled. Could be an intentional
7185
+ # customization, so warn (not error) and don't auto-overwrite.
7186
+ print(f" [..] Damage-control rules differ from bundled: {', '.join(sorted(stale_rules))}")
7187
+ print(" (customized? `agentwire safety install --yes` leaves these untouched)")
7188
+ else:
7189
+ print(" [ok] Damage-control rules installed and match bundled")
7190
+
7191
+ # Matcher presence in ~/.claude/settings.json.
7192
+ missing_matchers = cli_safety.missing_damage_control_matchers()
7193
+ if missing_matchers:
7194
+ print(f" [!!] PreToolUse matchers not registered: {', '.join(missing_matchers)}")
7195
+ print(" Fix: agentwire safety install --yes")
7196
+ issues += 1
7197
+ else:
7198
+ print(" [ok] PreToolUse damage-control matchers registered")
7199
+
7200
+ return issues
7201
+
7202
+
7078
7203
  def _render_voice_loop_section(config, ctx) -> int:
7079
7204
  """Print the voice-loop (push-to-talk) preflight. Returns failures found.
7080
7205
 
@@ -7256,6 +7381,36 @@ def cmd_doctor(args) -> int:
7256
7381
  print(f" [..] {label}: not found ({why})")
7257
7382
  print(" Run: agentwire hooks install")
7258
7383
 
7384
+ # 4b. Damage control (safety) — the kill switch, install drift, and the
7385
+ # PreToolUse matcher registration. The #462 incident: a global disable and
7386
+ # missing rule files were both invisible to every diagnostic.
7387
+ print("\nChecking damage control (safety)...")
7388
+ issues_found += _render_damage_control_section()
7389
+
7390
+ # 4c. Local checkout vs origin/main — rebuild reinstalls whatever is checked
7391
+ # out, so a never-pulled main silently ships stale code. Today only worktree
7392
+ # creation fetches; surface the drift here too.
7393
+ print("\nChecking source checkout...")
7394
+ src_root = Path(__file__).parent.parent
7395
+ if not (src_root / "pyproject.toml").exists():
7396
+ try:
7397
+ src_root = get_source_dir()
7398
+ except Exception:
7399
+ src_root = None
7400
+ if src_root is None:
7401
+ print(" [..] Could not locate source checkout — skipping git-drift check")
7402
+ else:
7403
+ behind, err = _git_behind_origin(src_root)
7404
+ if err:
7405
+ print(f" [..] Source checkout: skipped git-drift check ({err})")
7406
+ elif behind and behind > 0:
7407
+ print(f" [!!] Local main is {behind} commit(s) behind origin/main")
7408
+ print(f" {src_root}")
7409
+ print(" Fix: git pull --ff-only (then agentwire rebuild)")
7410
+ issues_found += 1
7411
+ else:
7412
+ print(" [ok] Local main up to date with origin/main")
7413
+
7259
7414
  # Check custom services (registry-driven: built-in notifications bridge
7260
7415
  # + user-defined services from services.custom)
7261
7416
  print("\nChecking custom services...")
@@ -7653,15 +7808,70 @@ def cmd_voiceclone_delete(args) -> int:
7653
7808
  UV_CACHE_DIR = Path.home() / ".cache" / "uv"
7654
7809
 
7655
7810
 
7811
+ def _git_behind_origin(repo: Path, base: str = "main", do_fetch: bool = True):
7812
+ """How many commits ``origin/<base>`` is ahead of the checkout's HEAD.
7813
+
7814
+ Returns ``(behind, error)``: ``behind`` is the commit count (0 = up to date),
7815
+ or ``None`` with a human-readable ``error`` string when the comparison can't
7816
+ be made (not a git repo, no remote, offline fetch failure, etc.).
7817
+ """
7818
+ if not (repo / ".git").exists():
7819
+ return None, "not a git checkout"
7820
+ if do_fetch:
7821
+ fetch = subprocess.run(
7822
+ ["git", "fetch", "origin", base],
7823
+ cwd=repo, capture_output=True, text=True,
7824
+ )
7825
+ if fetch.returncode != 0:
7826
+ return None, (fetch.stderr or fetch.stdout or "git fetch failed").strip()
7827
+ count = subprocess.run(
7828
+ ["git", "rev-list", "--count", f"HEAD..origin/{base}"],
7829
+ cwd=repo, capture_output=True, text=True,
7830
+ )
7831
+ if count.returncode != 0:
7832
+ return None, (count.stderr or count.stdout or "git rev-list failed").strip()
7833
+ try:
7834
+ return int(count.stdout.strip()), None
7835
+ except ValueError:
7836
+ return None, f"unexpected rev-list output: {count.stdout.strip()!r}"
7837
+
7838
+
7656
7839
  def cmd_rebuild(args) -> int:
7657
7840
  """Rebuild: clear uv cache, uninstall, reinstall from source.
7658
7841
 
7659
7842
  This is the correct way to pick up source changes when developing.
7660
7843
  `uv tool install . --force` does NOT work - it uses cached wheels.
7661
7844
  """
7845
+ force = getattr(args, "force", False)
7846
+
7662
7847
  print("Rebuilding agentwire-dev...")
7663
7848
  print()
7664
7849
 
7850
+ # Resolve the source checkout up front so the git-drift guard and the
7851
+ # install step agree on which tree they're operating over.
7852
+ project_root = Path(__file__).parent.parent
7853
+ if not (project_root / "pyproject.toml").exists():
7854
+ project_root = get_source_dir()
7855
+
7856
+ # Git-drift guard: rebuild is otherwise git-blind and will happily reinstall
7857
+ # stale code when local main was never pulled after a remote merge. Refuse
7858
+ # (unless --force) so the fix happens before the reinstall, not after.
7859
+ behind, err = _git_behind_origin(project_root)
7860
+ if err:
7861
+ print(f" - Skipping git-drift check ({err})")
7862
+ elif behind and behind > 0:
7863
+ print(f" [!!] Local checkout is {behind} commit(s) behind origin/main.")
7864
+ print(f" {project_root}")
7865
+ print(" Rebuild would reinstall stale code. Run first:")
7866
+ print(" git pull --ff-only")
7867
+ if not force:
7868
+ print(" (or re-run with --force to rebuild anyway)")
7869
+ return 1
7870
+ print(" --force given: rebuilding from the behind checkout anyway.")
7871
+ else:
7872
+ print(" ✓ Checkout up to date with origin/main")
7873
+ print()
7874
+
7665
7875
  # Step 1: Clear uv cache
7666
7876
  if UV_CACHE_DIR.exists():
7667
7877
  print(f"Clearing uv cache ({UV_CACHE_DIR})...")
@@ -7683,13 +7893,7 @@ def cmd_rebuild(args) -> int:
7683
7893
  # Might not be installed, that's fine
7684
7894
  print(" - Not installed (continuing)")
7685
7895
 
7686
- # Step 3: Reinstall from current directory
7687
- # Find the project root (where pyproject.toml is)
7688
- project_root = Path(__file__).parent.parent
7689
- if not (project_root / "pyproject.toml").exists():
7690
- # Fallback to configured source directory
7691
- project_root = get_source_dir()
7692
-
7896
+ # Step 3: Reinstall from the source checkout resolved above.
7693
7897
  print(f"Installing from {project_root}...")
7694
7898
  result = subprocess.run(
7695
7899
  ["uv", "tool", "install", "."],
@@ -8527,6 +8731,17 @@ def install_hooks(force: bool = False, copy: bool = False) -> dict[str, str]:
8527
8731
  if event:
8528
8732
  register_hook_in_settings(event, hook_name)
8529
8733
 
8734
+ # Heal the full damage-control surface (hook scripts + rules + tooldefs +
8735
+ # PreToolUse matchers), not just the settings.json matchers. This closes the
8736
+ # documented post-rebuild gap: CLAUDE.md tells users to re-run `hooks install`
8737
+ # after a rebuild, so it must actually sync the DC files/rules — drift-aware,
8738
+ # never clobbering a customized rule.
8739
+ try:
8740
+ from agentwire.cli_safety import heal_damage_control
8741
+ heal_damage_control(quiet=True)
8742
+ except Exception:
8743
+ pass
8744
+
8530
8745
  return results
8531
8746
 
8532
8747
 
@@ -10258,8 +10473,18 @@ def _set_task_enabled(name: str, enabled: bool) -> int:
10258
10473
 
10259
10474
  tasks[name]["enabled"] = enabled
10260
10475
 
10261
- with open(board_path, "w") as f:
10262
- yaml.dump(raw, f, default_flow_style=False, sort_keys=False)
10476
+ # Atomic + validated write — never leave scheduler.yaml half-written (#449).
10477
+ from .scheduler import _atomic_write
10478
+
10479
+ text = yaml.dump(raw, default_flow_style=False, sort_keys=False)
10480
+
10481
+ def _validate(tmp_path: str) -> None:
10482
+ with open(tmp_path) as f:
10483
+ reparsed = yaml.safe_load(f)
10484
+ if not isinstance(reparsed, dict) or "tasks" not in reparsed:
10485
+ raise ValueError("scheduler board failed re-parse validation")
10486
+
10487
+ _atomic_write(board_path, text, validate=_validate)
10263
10488
 
10264
10489
  action = "Enabled" if enabled else "Disabled"
10265
10490
  print(f"{action}: {name}")
@@ -10929,6 +11154,27 @@ def main() -> int:
10929
11154
  )
10930
11155
  portal_token.set_defaults(func=cmd_portal_token)
10931
11156
 
11157
+ # portal pair — mint a pairing code (+QR) for a new device
11158
+ portal_pair = portal_subparsers.add_parser(
11159
+ "pair", help="Pair a new device (prints a short-lived code + QR)"
11160
+ )
11161
+ portal_pair.add_argument("--name", help="Friendly device name (e.g. 'phone')")
11162
+ portal_pair.set_defaults(func=cmd_portal_pair)
11163
+
11164
+ # portal devices — list paired devices
11165
+ portal_devices = portal_subparsers.add_parser(
11166
+ "devices", help="List paired portal devices"
11167
+ )
11168
+ portal_devices.add_argument("--json", action="store_true", help="Output JSON")
11169
+ portal_devices.set_defaults(func=cmd_portal_devices)
11170
+
11171
+ # portal revoke — revoke one device
11172
+ portal_revoke = portal_subparsers.add_parser(
11173
+ "revoke", help="Revoke one paired device by id"
11174
+ )
11175
+ portal_revoke.add_argument("device_id", help="Device id (see `portal devices`)")
11176
+ portal_revoke.set_defaults(func=cmd_portal_revoke)
11177
+
10932
11178
  # === tts command group ===
10933
11179
  tts_parser = subparsers.add_parser("tts", help="Manage TTS server")
10934
11180
  tts_subparsers = tts_parser.add_subparsers(dest="tts_command")
@@ -11690,7 +11936,12 @@ def main() -> int:
11690
11936
 
11691
11937
  # safety install
11692
11938
  safety_install = safety_subparsers.add_parser(
11693
- "install", help="Install damage control hooks (interactive)"
11939
+ "install", help="Install/heal damage control hooks, rules, and matchers"
11940
+ )
11941
+ safety_install.add_argument(
11942
+ "-y", "--yes", action="store_true",
11943
+ help="Non-interactive, drift-aware heal (install missing + update stale "
11944
+ "owned hooks; never clobbers existing rules)",
11694
11945
  )
11695
11946
  safety_install.set_defaults(func=cmd_safety_install)
11696
11947
 
@@ -11735,6 +11986,10 @@ def main() -> int:
11735
11986
  rebuild_parser = subparsers.add_parser(
11736
11987
  "rebuild", help="Clear uv cache and reinstall from source (for development)"
11737
11988
  )
11989
+ rebuild_parser.add_argument(
11990
+ "--force", action="store_true",
11991
+ help="Rebuild even when the local checkout is behind origin/main",
11992
+ )
11738
11993
  rebuild_parser.set_defaults(func=cmd_rebuild)
11739
11994
 
11740
11995
  # === uninstall command ===