agentwire-dev 1.68.0__tar.gz → 1.70.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 (626) hide show
  1. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/.github/workflows/pytest.yml +13 -4
  2. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/PKG-INFO +2 -2
  3. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/__init__.py +1 -1
  4. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/__main__.py +5 -1
  5. agentwire_dev-1.70.0/agentwire/activity_cli.py +86 -0
  6. agentwire_dev-1.70.0/agentwire/alerts_cli.py +153 -0
  7. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/auth_expired.py +46 -0
  8. agentwire_dev-1.70.0/agentwire/beta.py +193 -0
  9. agentwire_dev-1.70.0/agentwire/buddy_cli.py +456 -0
  10. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/channels_cli.py +36 -1
  11. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/cohort.py +46 -8
  12. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/config.py +134 -7
  13. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/core.py +160 -19
  14. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/doctor_cli.py +190 -43
  15. agentwire_dev-1.70.0/agentwire/fleet_activity.py +563 -0
  16. agentwire_dev-1.70.0/agentwire/fleet_alerts.py +380 -0
  17. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/hooks/damage-control/audit_logger.py +105 -3
  18. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/hooks/damage-control/bash-tool-damage-control.py +1188 -98
  19. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/hooks/damage-control/edit-tool-damage-control.py +1174 -101
  20. agentwire_dev-1.70.0/agentwire/hooks/damage-control/mcp-tool-damage-control.py +4241 -0
  21. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/hooks/damage-control/read-tool-damage-control.py +1166 -96
  22. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/hooks/damage-control/rules/agentwire.yaml +12 -7
  23. agentwire_dev-1.70.0/agentwire/hooks/damage-control/rules/mcp-tools.yaml +84 -0
  24. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/hooks/damage-control/rules/payloads.yaml +16 -0
  25. agentwire_dev-1.70.0/agentwire/hooks/damage-control/rules/remote.yaml +49 -0
  26. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/hooks/damage-control/write-tool-damage-control.py +1166 -96
  27. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/hooks_cli.py +7 -1
  28. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/inbox.py +249 -44
  29. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/limits_cli.py +19 -5
  30. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/mcp_channels.py +1 -1
  31. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/mcp_chrome.py +2 -1
  32. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/mcp_core.py +66 -78
  33. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/mcp_council.py +1 -1
  34. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/mcp_handoff.py +1 -1
  35. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/mcp_history.py +1 -1
  36. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/mcp_listen.py +1 -1
  37. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/mcp_lock.py +1 -1
  38. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/mcp_machine.py +1 -1
  39. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/mcp_msg.py +9 -1
  40. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/mcp_notify.py +16 -8
  41. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/mcp_pane.py +1 -1
  42. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/mcp_projects.py +1 -1
  43. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/mcp_scheduler.py +1 -1
  44. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/mcp_scratchpad.py +1 -1
  45. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/mcp_server.py +2 -1
  46. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/mcp_services.py +5 -3
  47. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/mcp_session.py +6 -1
  48. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/mcp_status.py +1 -1
  49. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/mcp_task.py +1 -1
  50. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/mcp_tunnels.py +1 -1
  51. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/mcp_voice.py +1 -1
  52. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/mcp_worktree.py +1 -1
  53. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/msg_cli.py +40 -7
  54. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/notify_cli.py +68 -5
  55. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/pane_cli.py +26 -3
  56. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/prompt_router.py +78 -0
  57. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/roles/__init__.py +11 -0
  58. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/roles/agentwire.md +5 -1
  59. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/roles/orchestrator.md +12 -0
  60. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/roles/worker-worktree.md +12 -0
  61. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/roles/worker.md +12 -0
  62. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/routes/desktop.py +5 -0
  63. agentwire_dev-1.68.0/agentwire/hooks/damage-control/mcp-tool-damage-control.py → agentwire_dev-1.70.0/agentwire/safety/_core.py +1147 -309
  64. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/safety/lint.py +8 -2
  65. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/safety/rule_baselines.json +9 -2
  66. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/safety_cli.py +18 -0
  67. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/safety_commands.py +140 -30
  68. agentwire_dev-1.70.0/agentwire/safety_notify.py +389 -0
  69. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/scheduler/report.py +27 -1
  70. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/server.py +16 -8
  71. agentwire_dev-1.70.0/agentwire/services.py +696 -0
  72. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/session_cli.py +106 -12
  73. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/static/css/desktop.css +14 -0
  74. agentwire_dev-1.70.0/agentwire/static/js/dead-key-residue.js +63 -0
  75. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/static/js/desktop.js +12 -19
  76. agentwire_dev-1.70.0/agentwire/static/js/hotkeys.js +38 -0
  77. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/static/js/scratchpad.js +4 -14
  78. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/static/js/service-classification.js +1 -0
  79. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/static/js/session-hud-controller.js +6 -4
  80. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/static/js/session-hud.js +4 -14
  81. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/static/js/sidebar.js +4 -15
  82. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/static/js/terminal-pane.js +14 -0
  83. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/static/js/topology-render.js +24 -2
  84. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/system_cli.py +8 -3
  85. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/tooldefs/git.yaml +14 -2
  86. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/usage_limit.py +49 -1
  87. agentwire_dev-1.70.0/agentwire/voice_layer/__init__.py +29 -0
  88. agentwire_dev-1.70.0/agentwire/voice_layer/client.py +2204 -0
  89. agentwire_dev-1.70.0/agentwire/voice_layer/confirm.py +2545 -0
  90. agentwire_dev-1.70.0/agentwire/voice_layer/delivery.py +262 -0
  91. agentwire_dev-1.70.0/agentwire/voice_layer/identity.py +307 -0
  92. agentwire_dev-1.70.0/agentwire/voice_layer/instructions.py +346 -0
  93. agentwire_dev-1.70.0/agentwire/voice_layer/outbox.py +188 -0
  94. agentwire_dev-1.70.0/agentwire/voice_layer/realtime.py +263 -0
  95. agentwire_dev-1.70.0/agentwire/voice_layer/relay.py +192 -0
  96. agentwire_dev-1.70.0/agentwire/voice_layer/server.py +521 -0
  97. agentwire_dev-1.70.0/agentwire/voice_layer/surface.py +370 -0
  98. agentwire_dev-1.70.0/agentwire/voice_layer/tools.py +1080 -0
  99. agentwire_dev-1.70.0/agentwire/voice_layer/transcript.py +441 -0
  100. agentwire_dev-1.70.0/agentwire/voice_layer/write_tools.py +399 -0
  101. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/wait_cli.py +12 -1
  102. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/docs/wiki/INDEX.md +1 -0
  103. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/docs/wiki/internals/damage-control.md +99 -31
  104. agentwire_dev-1.70.0/docs/wiki/services.md +140 -0
  105. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/docs/wiki/sessions/fan-out-cohorts.md +10 -1
  106. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/docs/wiki/sessions/messaging.md +228 -5
  107. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/docs/wiki/sessions/worktree-sessions.md +10 -1
  108. agentwire_dev-1.70.0/docs/wiki/voice-layer.md +2801 -0
  109. agentwire_dev-1.70.0/scratch-remove-docker-daemons.sh +12 -0
  110. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/tests/conftest.py +42 -0
  111. agentwire_dev-1.70.0/tests/fixtures/hotkeys_harness.mjs +123 -0
  112. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/tests/integration/test_send_verified_tmux.py +4 -3
  113. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/tests/integration/test_tmux_name_rewrite.py +18 -0
  114. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/tests/integration/test_worktree_cmd.py +3 -0
  115. agentwire_dev-1.70.0/tests/page_slice.py +40 -0
  116. agentwire_dev-1.70.0/tests/unit/test_audit_attribution.py +266 -0
  117. agentwire_dev-1.70.0/tests/unit/test_beta_flag.py +684 -0
  118. agentwire_dev-1.70.0/tests/unit/test_buddy_restart.py +370 -0
  119. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/tests/unit/test_cli_smoke.py +15 -12
  120. agentwire_dev-1.70.0/tests/unit/test_cli_stderr_clean.py +232 -0
  121. agentwire_dev-1.70.0/tests/unit/test_client_wires.py +302 -0
  122. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/tests/unit/test_cohort.py +72 -1
  123. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/tests/unit/test_damage_control_hooks.py +85 -63
  124. agentwire_dev-1.70.0/tests/unit/test_damage_control_inert_view.py +136 -0
  125. agentwire_dev-1.70.0/tests/unit/test_damage_control_operation_pinning.py +297 -0
  126. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/tests/unit/test_damage_control_payload_anchoring.py +260 -183
  127. agentwire_dev-1.70.0/tests/unit/test_fleet_activity.py +750 -0
  128. agentwire_dev-1.70.0/tests/unit/test_fleet_alerts.py +804 -0
  129. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/tests/unit/test_hooks_install.py +14 -0
  130. agentwire_dev-1.70.0/tests/unit/test_hotkeys_js.py +37 -0
  131. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/tests/unit/test_inbox.py +91 -0
  132. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/tests/unit/test_limits_tick_isolation.py +24 -0
  133. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/tests/unit/test_mcp_server.py +63 -13
  134. agentwire_dev-1.70.0/tests/unit/test_mcp_tool_policy.py +230 -0
  135. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/tests/unit/test_mcp_tools_args.py +26 -9
  136. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/tests/unit/test_msg_cli.py +58 -0
  137. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/tests/unit/test_notify_cli.py +36 -0
  138. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/tests/unit/test_pip_audit_report.py +0 -23
  139. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/tests/unit/test_portal_api.py +24 -5
  140. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/tests/unit/test_prompt_router.py +0 -21
  141. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/tests/unit/test_restart_cli.py +0 -5
  142. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/tests/unit/test_safety_commands.py +23 -3
  143. agentwire_dev-1.70.0/tests/unit/test_safety_coverage_wave.py +466 -0
  144. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/tests/unit/test_safety_deployment.py +6 -3
  145. agentwire_dev-1.70.0/tests/unit/test_safety_notify.py +459 -0
  146. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/tests/unit/test_services.py +60 -1
  147. agentwire_dev-1.70.0/tests/unit/test_services_command.py +919 -0
  148. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/tests/unit/test_session_metadata_ssot.py +5 -0
  149. agentwire_dev-1.70.0/tests/unit/test_tmux_template.py +26 -0
  150. agentwire_dev-1.70.0/tests/unit/test_unattended_allow.py +388 -0
  151. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/tests/unit/test_unattended_scoped_allow.py +181 -2
  152. agentwire_dev-1.70.0/tests/unit/test_voice_announcer.py +2829 -0
  153. agentwire_dev-1.70.0/tests/unit/test_voice_body_delivery.py +337 -0
  154. agentwire_dev-1.70.0/tests/unit/test_voice_bridge_host.py +343 -0
  155. agentwire_dev-1.70.0/tests/unit/test_voice_confirm.py +3894 -0
  156. agentwire_dev-1.70.0/tests/unit/test_voice_epoch.py +396 -0
  157. agentwire_dev-1.70.0/tests/unit/test_voice_fleet_alerts.py +156 -0
  158. agentwire_dev-1.70.0/tests/unit/test_voice_kind.py +347 -0
  159. agentwire_dev-1.70.0/tests/unit/test_voice_layer.py +829 -0
  160. agentwire_dev-1.70.0/tests/unit/test_voice_outbox.py +460 -0
  161. agentwire_dev-1.70.0/tests/unit/test_voice_persona.py +364 -0
  162. agentwire_dev-1.70.0/tests/unit/test_voice_picker.py +553 -0
  163. agentwire_dev-1.70.0/tests/unit/test_voice_relay_full_text.py +472 -0
  164. agentwire_dev-1.70.0/tests/unit/test_voice_surface.py +1178 -0
  165. agentwire_dev-1.70.0/tests/unit/test_voice_ux_1048.py +561 -0
  166. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/tests/unit/test_window_cycling_binding.py +4 -1
  167. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/tests/unit/test_worktree_dot_project.py +14 -14
  168. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/tests/unit/test_worktree_git_truth.py +147 -0
  169. agentwire_dev-1.70.0/tools/nonce_stt_probe.py +125 -0
  170. agentwire_dev-1.70.0/tools/voice_dc_probe.py +254 -0
  171. agentwire_dev-1.70.0/tools/voice_heal_probe.py +317 -0
  172. agentwire_dev-1.68.0/agentwire/hooks/damage-control/rules/remote.yaml +0 -81
  173. agentwire_dev-1.68.0/agentwire/safety/_core.py +0 -2821
  174. agentwire_dev-1.68.0/agentwire/services.py +0 -325
  175. agentwire_dev-1.68.0/agentwire/static/js/dead-key-suppressor.js +0 -53
  176. agentwire_dev-1.68.0/docs/wiki/services.md +0 -74
  177. agentwire_dev-1.68.0/tests/unit/test_tmux_template.py +0 -73
  178. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/.agentwire.yml.example +0 -0
  179. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/.claude/commands/handoff.md +0 -0
  180. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/.claude/skills/wiki/SKILL.md +0 -0
  181. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/.github/FUNDING.yml +0 -0
  182. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
  183. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
  184. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/.github/ISSUE_TEMPLATE/question.md +0 -0
  185. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
  186. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/.github/workflows/ruff.yml +0 -0
  187. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/.github/workflows/security.yml +0 -0
  188. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/.github/workflows/tts-smoke.yml +0 -0
  189. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/.gitignore +0 -0
  190. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/AGENTS.md +0 -0
  191. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/CODE_OF_CONDUCT.md +0 -0
  192. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/CONTRIBUTING.md +0 -0
  193. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/Dockerfile.local +0 -0
  194. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/LICENSE +0 -0
  195. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/README.md +0 -0
  196. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/RELEASING.md +0 -0
  197. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/SECURITY.md +0 -0
  198. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/SPONSORS.md +0 -0
  199. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/agents/__init__.py +0 -0
  200. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/agents/base.py +0 -0
  201. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/agents/tmux.py +0 -0
  202. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/cached_status.py +0 -0
  203. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/channels/__init__.py +0 -0
  204. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/channels/base.py +0 -0
  205. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/channels/email.py +0 -0
  206. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/channels/push.py +0 -0
  207. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/channels/quo.py +0 -0
  208. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/chrome_tabs.py +0 -0
  209. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/completion.py +0 -0
  210. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/config_cli.py +0 -0
  211. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/council/__init__.py +0 -0
  212. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/council/cli.py +0 -0
  213. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/council/inbox.py +0 -0
  214. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/council/minutes.py +0 -0
  215. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/council/state.py +0 -0
  216. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/council/view.py +0 -0
  217. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/devices.py +0 -0
  218. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/diff_cli.py +0 -0
  219. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/doctor_voice.py +0 -0
  220. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/ensure_cli.py +0 -0
  221. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/fetch.py +0 -0
  222. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/handoff/__init__.py +0 -0
  223. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/handoff/git_state.py +0 -0
  224. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/handoff/instructions.py +0 -0
  225. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/handoff/parser.py +0 -0
  226. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/handoff/renderer.py +0 -0
  227. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/handoff/schema.py +0 -0
  228. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/handoff_cli.py +0 -0
  229. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/history.py +0 -0
  230. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/history_cli.py +0 -0
  231. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/history_migrate.py +0 -0
  232. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/hooks/__init__.py +0 -0
  233. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/hooks/agentwire-permission.sh +0 -0
  234. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/hooks/damage-control/__init__.py +0 -0
  235. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/hooks/damage-control/rules/aws.yaml +0 -0
  236. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/hooks/damage-control/rules/cloud-hosting.yaml +0 -0
  237. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/hooks/damage-control/rules/containers.yaml +0 -0
  238. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/hooks/damage-control/rules/control-plane.yaml +0 -0
  239. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/hooks/damage-control/rules/core.yaml +0 -0
  240. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/hooks/damage-control/rules/databases.yaml +0 -0
  241. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/hooks/damage-control/rules/firebase.yaml +0 -0
  242. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/hooks/damage-control/rules/gcp.yaml +0 -0
  243. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/hooks/damage-control/rules/git.yaml +0 -0
  244. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/hooks/damage-control/rules/gws.yaml +0 -0
  245. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/hooks/damage-control/rules/infrastructure.yaml +0 -0
  246. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/hooks/damage-control/rules/outbound.yaml +0 -0
  247. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/hooks/damage-control/rules/publish.yaml +0 -0
  248. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/hooks/idle-handler.sh +0 -0
  249. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/hooks/queue-processor.sh +0 -0
  250. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/listen.py +0 -0
  251. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/locking.py +0 -0
  252. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/machine_cli.py +0 -0
  253. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/mcp_cli.py +0 -0
  254. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/mcp_desktop.py +0 -0
  255. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/mcp_wiki.py +0 -0
  256. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/network.py +0 -0
  257. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/onboarding.py +0 -0
  258. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/palette_cli.py +0 -0
  259. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/pane_manager.py +0 -0
  260. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/portal_cli.py +0 -0
  261. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/project_config.py +0 -0
  262. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/projects.py +0 -0
  263. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/prompts_cli.py +0 -0
  264. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/push_cli.py +0 -0
  265. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/push_store.py +0 -0
  266. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/repo_cli.py +0 -0
  267. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/research.py +0 -0
  268. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/restart_cli.py +0 -0
  269. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/role_prompts.py +0 -0
  270. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/roles/anchor.md +0 -0
  271. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/roles/chatbot.md +0 -0
  272. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/roles/contributor.md +0 -0
  273. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/roles/correspondent.md +0 -0
  274. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/roles/council-brain.md +0 -0
  275. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/roles/council-conscience.md +0 -0
  276. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/roles/council-critic.md +0 -0
  277. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/roles/council-devils-advocate.md +0 -0
  278. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/roles/council-gut.md +0 -0
  279. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/roles/council-historian.md +0 -0
  280. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/roles/council-member.md +0 -0
  281. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/roles/council-orchestrator.md +0 -0
  282. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/roles/init.md +0 -0
  283. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/roles/notifications.md +0 -0
  284. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/roles/reviewer-worktree.md +0 -0
  285. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/roles/reviewer.md +0 -0
  286. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/roles/shared-checkout.md +0 -0
  287. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/roles/soul.md +0 -0
  288. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/roles/task-runner.md +0 -0
  289. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/roles/voice.md +0 -0
  290. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/roles_cli.py +0 -0
  291. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/routes/__init__.py +0 -0
  292. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/routes/artifacts.py +0 -0
  293. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/routes/config.py +0 -0
  294. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/routes/council.py +0 -0
  295. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/routes/history.py +0 -0
  296. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/routes/machines.py +0 -0
  297. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/routes/notify.py +0 -0
  298. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/routes/palette.py +0 -0
  299. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/routes/permission.py +0 -0
  300. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/routes/projects.py +0 -0
  301. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/routes/push.py +0 -0
  302. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/routes/safety.py +0 -0
  303. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/routes/scheduler.py +0 -0
  304. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/routes/scratchpad.py +0 -0
  305. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/routes/sessions.py +0 -0
  306. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/routes/sessions_admin.py +0 -0
  307. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/routes/voice.py +0 -0
  308. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/safety/__init__.py +0 -0
  309. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/safety/provenance.py +0 -0
  310. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/scheduler/__init__.py +0 -0
  311. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/scheduler/dispatch.py +0 -0
  312. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/scheduler/gates.py +0 -0
  313. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/scheduler/loop.py +0 -0
  314. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/scheduler/models.py +0 -0
  315. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/scheduler/schedule.py +0 -0
  316. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/scheduler/state.py +0 -0
  317. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/scheduler/zombie.py +0 -0
  318. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/scheduler_cli.py +0 -0
  319. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/scratchpad.py +0 -0
  320. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/security.py +0 -0
  321. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/send_cli.py +0 -0
  322. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/session_context.py +0 -0
  323. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/session_ready.py +0 -0
  324. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/ssh.py +0 -0
  325. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/static/agentwire-splash-logo-layers--agentwire-text.png +0 -0
  326. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/static/agentwire-splash-logo-layers--echo-claw-fg.png +0 -0
  327. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/static/agentwire-splash-logo-layers--echo.png +0 -0
  328. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/static/agentwire-splash-logo-layers--telephone.png +0 -0
  329. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/static/agentwire-splash-logo-layers--tree.png +0 -0
  330. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/static/announcements.json +0 -0
  331. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/static/apple-touch-icon.png +0 -0
  332. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/static/css/mobile.css +0 -0
  333. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/static/favicon-32.png +0 -0
  334. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/static/favicon-64.png +0 -0
  335. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/static/icons/sessions/bear.webp +0 -0
  336. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/static/icons/sessions/cat.webp +0 -0
  337. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/static/icons/sessions/crown.webp +0 -0
  338. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/static/icons/sessions/custom/agentwire-portal.webp +0 -0
  339. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/static/icons/sessions/custom/agentwire-tts.webp +0 -0
  340. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/static/icons/sessions/custom/agentwire.webp +0 -0
  341. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/static/icons/sessions/deer.webp +0 -0
  342. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/static/icons/sessions/drone.webp +0 -0
  343. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/static/icons/sessions/eagle.webp +0 -0
  344. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/static/icons/sessions/fox.webp +0 -0
  345. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/static/icons/sessions/hawk.webp +0 -0
  346. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/static/icons/sessions/horse.webp +0 -0
  347. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/static/icons/sessions/lion.webp +0 -0
  348. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/static/icons/sessions/rabbit.webp +0 -0
  349. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/static/icons/sessions/robot.webp +0 -0
  350. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/static/icons/sessions/tiger.webp +0 -0
  351. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/static/icons/sessions/wolf.webp +0 -0
  352. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/static/img/icon-192.png +0 -0
  353. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/static/img/icon-512.png +0 -0
  354. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/static/js/.gitkeep +0 -0
  355. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/static/js/announcement-modal.js +0 -0
  356. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/static/js/api.js +0 -0
  357. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/static/js/artifact-window.js +0 -0
  358. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/static/js/card-terminal.js +0 -0
  359. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/static/js/collage.js +0 -0
  360. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/static/js/command-palette.js +0 -0
  361. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/static/js/council-window.js +0 -0
  362. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/static/js/desktop-manager.js +0 -0
  363. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/static/js/help-modal.js +0 -0
  364. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/static/js/icon-manager.js +0 -0
  365. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/static/js/lineage.js +0 -0
  366. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/static/js/mobile.js +0 -0
  367. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/static/js/notification-prefs.js +0 -0
  368. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/static/js/notifications-panel.js +0 -0
  369. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/static/js/ptt.js +0 -0
  370. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/static/js/push-client.js +0 -0
  371. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/static/js/review-window.js +0 -0
  372. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/static/js/safety-shared.js +0 -0
  373. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/static/js/safety-window.js +0 -0
  374. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/static/js/session-hud-notices.js +0 -0
  375. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/static/js/session-hud-spawn.js +0 -0
  376. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/static/js/session-id.js +0 -0
  377. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/static/js/session-window.js +0 -0
  378. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/static/js/shortcuts.js +0 -0
  379. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/static/js/sidebar/artifacts-section.js +0 -0
  380. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/static/js/sidebar/config-section.js +0 -0
  381. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/static/js/sidebar/council-section.js +0 -0
  382. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/static/js/sidebar/machines-section.js +0 -0
  383. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/static/js/sidebar/projects-section.js +0 -0
  384. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/static/js/sidebar/safety-section.js +0 -0
  385. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/static/js/sidebar/scheduler-section.js +0 -0
  386. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/static/js/sidebar/services-section.js +0 -0
  387. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/static/js/sidebar/sessions-section.js +0 -0
  388. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/static/js/spawn-ghost.js +0 -0
  389. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/static/js/terminal-font-prefs.js +0 -0
  390. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/static/js/tile-manager.js +0 -0
  391. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/static/js/toast.js +0 -0
  392. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/static/js/token-modal.js +0 -0
  393. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/static/js/utils/ansi.js +0 -0
  394. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/static/js/utils/rich-text.js +0 -0
  395. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/static/js/utils/swipe.js +0 -0
  396. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/static/js/voice/autosend-prefs.js +0 -0
  397. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/static/js/voice/browser-stt.js +0 -0
  398. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/static/js/voice/browser-tts.js +0 -0
  399. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/static/js/voice/jargon.js +0 -0
  400. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/static/js/voice/prompt.js +0 -0
  401. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/static/js/winbox.bundle.min.js +0 -0
  402. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/static/js/workspace-window.js +0 -0
  403. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/static/manifest.webmanifest +0 -0
  404. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/static/service-worker.js +0 -0
  405. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/static/topology-harness.html +0 -0
  406. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/stt/__init__.py +0 -0
  407. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/stt/base.py +0 -0
  408. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/stt/cloud.py +0 -0
  409. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/stt/engine.py +0 -0
  410. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/stt/local.py +0 -0
  411. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/stt/server_backend.py +0 -0
  412. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/stt/stt_server.py +0 -0
  413. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/tabs_cli.py +0 -0
  414. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/tasks.py +0 -0
  415. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/tasks_cli.py +0 -0
  416. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/templates/__init__.py +0 -0
  417. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/templates/base.html +0 -0
  418. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/templates/council/minutes.html.j2 +0 -0
  419. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/templates/desktop.html +0 -0
  420. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/templates/email_notification.html +0 -0
  421. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/templates/handoff/show-the-story.html.j2 +0 -0
  422. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/templates/handoff/theme.css.j2 +0 -0
  423. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/templates/mobile.html +0 -0
  424. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/templates/pair.html +0 -0
  425. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/templates/statusline.sh +0 -0
  426. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/templates/tmux.conf +0 -0
  427. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/templating.py +0 -0
  428. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/tooldefs/aws.yaml +0 -0
  429. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/tooldefs/docker.yaml +0 -0
  430. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/tooldefs/gcp.yaml +0 -0
  431. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/tooldefs/gh.yaml +0 -0
  432. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/tooldefs/gws.yaml +0 -0
  433. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/tooldefs/kubectl.yaml +0 -0
  434. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/tooldefs/npm.yaml +0 -0
  435. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/tooldefs/terraform.yaml +0 -0
  436. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/tooldefs/uv.yaml +0 -0
  437. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/tts/__init__.py +0 -0
  438. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/tts/audio.py +0 -0
  439. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/tts/base.py +0 -0
  440. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/tts/engines/__init__.py +0 -0
  441. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/tts/engines/chatterbox.py +0 -0
  442. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/tts/engines/kokoro.py +0 -0
  443. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/tts/engines/zonos.py +0 -0
  444. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/tts/kokoro_server.py +0 -0
  445. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/tts/local.py +0 -0
  446. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/tts/registry.py +0 -0
  447. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/tts_cli.py +0 -0
  448. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/tts_server.py +0 -0
  449. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/tunnels.py +0 -0
  450. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/tunnels_cli.py +0 -0
  451. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/utils/__init__.py +0 -0
  452. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/utils/chunker.py +0 -0
  453. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/utils/event_log.py +0 -0
  454. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/utils/file_io.py +0 -0
  455. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/utils/paths.py +0 -0
  456. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/utils/speech.py +0 -0
  457. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/utils/subprocess.py +0 -0
  458. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/validation.py +0 -0
  459. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/voice_status.py +0 -0
  460. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/wiki.py +0 -0
  461. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/wiki_audit.py +0 -0
  462. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/wiki_cli.py +0 -0
  463. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/worktree.py +0 -0
  464. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/worktree_cli.py +0 -0
  465. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/agentwire/worktree_registry.py +0 -0
  466. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/docs/decisions/obsidian-second-brain.md +0 -0
  467. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/docs/design/session-card-fields.md +0 -0
  468. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/docs/design/session-card-recommendation.md +0 -0
  469. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/docs/logo.png +0 -0
  470. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/docs/wiki/architecture.md +0 -0
  471. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/docs/wiki/auth-expired.md +0 -0
  472. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/docs/wiki/briefing-mode.md +0 -0
  473. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/docs/wiki/communication/channels.md +0 -0
  474. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/docs/wiki/communication/hammerspoon.md +0 -0
  475. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/docs/wiki/communication/handoff.md +0 -0
  476. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/docs/wiki/concepts.md +0 -0
  477. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/docs/wiki/council.md +0 -0
  478. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/docs/wiki/deployment/remote-access.md +0 -0
  479. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/docs/wiki/deployment/remote-machines.md +0 -0
  480. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/docs/wiki/glossary.md +0 -0
  481. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/docs/wiki/integrations/gws-google-workspace-cli.md +0 -0
  482. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/docs/wiki/internals/parallel-refactor.md +0 -0
  483. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/docs/wiki/internals/portal.md +0 -0
  484. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/docs/wiki/internals/session-topology.md +0 -0
  485. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/docs/wiki/internals/shell-escaping.md +0 -0
  486. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/docs/wiki/internals/troubleshooting.md +0 -0
  487. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/docs/wiki/internals/window-collage.md +0 -0
  488. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/docs/wiki/quickstart.md +0 -0
  489. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/docs/wiki/research/briefing-mode-feasibility.md +0 -0
  490. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/docs/wiki/research/orchestration-transport-alternatives.md +0 -0
  491. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/docs/wiki/scheduling/scheduled-workloads.md +0 -0
  492. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/docs/wiki/security/damage-control-hardening.md +0 -0
  493. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/docs/wiki/security/pip-audit.md +0 -0
  494. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/docs/wiki/security/remote-access-hardening.md +0 -0
  495. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/docs/wiki/security/secrets.md +0 -0
  496. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/docs/wiki/sessions/claude-code-auto-mode.md +0 -0
  497. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/docs/wiki/sessions/conversation-identity.md +0 -0
  498. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/docs/wiki/sessions/heal-line-count-cliff.md +0 -0
  499. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/docs/wiki/sessions/helper-sessions.md +0 -0
  500. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/docs/wiki/sessions/prompt-routing.md +0 -0
  501. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/docs/wiki/sessions/window-sizing.md +0 -0
  502. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/docs/wiki/usage-limit-recovery.md +0 -0
  503. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/docs/wiki/voice/shim-contract.md +0 -0
  504. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/docs/wiki/voice/stt-cloud.md +0 -0
  505. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/docs/wiki/voice/stt-self-hosted.md +0 -0
  506. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/docs/wiki/voice/tts-self-hosted.md +0 -0
  507. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/pyproject.toml +0 -0
  508. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/tests/e2e/test_portal_ui.py +0 -0
  509. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/tests/fixtures/sample_agentwire.yml +0 -0
  510. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/tests/fixtures/sample_config.yaml +0 -0
  511. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/tests/fixtures/sample_scheduler.yaml +0 -0
  512. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/tests/home_guard.py +0 -0
  513. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/tests/integration/test_council_portal.py +0 -0
  514. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/tests/integration/test_scheduler_board.py +0 -0
  515. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/tests/integration/test_server_websockets.py +0 -0
  516. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/tests/unit/test_announcements.py +0 -0
  517. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/tests/unit/test_auth_expired.py +0 -0
  518. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/tests/unit/test_auth_expired_dispatch.py +0 -0
  519. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/tests/unit/test_build_agent_command.py +0 -0
  520. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/tests/unit/test_channels.py +0 -0
  521. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/tests/unit/test_chrome_tabs.py +0 -0
  522. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/tests/unit/test_cli_commands.py +0 -0
  523. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/tests/unit/test_cli_output.py +0 -0
  524. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/tests/unit/test_config.py +0 -0
  525. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/tests/unit/test_config_cli.py +0 -0
  526. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/tests/unit/test_control_plane_protection.py +0 -0
  527. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/tests/unit/test_core_created_by_rooting.py +0 -0
  528. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/tests/unit/test_council_cli.py +0 -0
  529. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/tests/unit/test_council_inbox.py +0 -0
  530. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/tests/unit/test_council_minutes.py +0 -0
  531. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/tests/unit/test_council_state.py +0 -0
  532. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/tests/unit/test_council_view.py +0 -0
  533. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/tests/unit/test_damage_control_bypass.py +0 -0
  534. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/tests/unit/test_damage_control_sync.py +0 -0
  535. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/tests/unit/test_dangling_worktrees.py +0 -0
  536. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/tests/unit/test_devices.py +0 -0
  537. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/tests/unit/test_diff_cli.py +0 -0
  538. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/tests/unit/test_doctor_orphaned_history.py +0 -0
  539. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/tests/unit/test_doctor_scheduler_staleness.py +0 -0
  540. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/tests/unit/test_doctor_secrets_perms.py +0 -0
  541. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/tests/unit/test_doctor_task_migration.py +0 -0
  542. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/tests/unit/test_doctor_voice.py +0 -0
  543. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/tests/unit/test_ensure_shared_dir.py +0 -0
  544. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/tests/unit/test_ensure_verified_prompt.py +0 -0
  545. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/tests/unit/test_event_log.py +0 -0
  546. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/tests/unit/test_file_io.py +0 -0
  547. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/tests/unit/test_guarded_launch_command.py +0 -0
  548. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/tests/unit/test_handoff_git_state.py +0 -0
  549. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/tests/unit/test_handoff_instructions.py +0 -0
  550. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/tests/unit/test_handoff_parser.py +0 -0
  551. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/tests/unit/test_handoff_renderer.py +0 -0
  552. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/tests/unit/test_helper_session.py +0 -0
  553. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/tests/unit/test_history.py +0 -0
  554. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/tests/unit/test_history_migrate.py +0 -0
  555. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/tests/unit/test_history_migrate_cli.py +0 -0
  556. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/tests/unit/test_history_resume_name.py +0 -0
  557. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/tests/unit/test_home_isolation.py +0 -0
  558. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/tests/unit/test_idle_handler.py +0 -0
  559. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/tests/unit/test_idle_nag.py +0 -0
  560. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/tests/unit/test_init_command.py +0 -0
  561. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/tests/unit/test_install_parity.py +0 -0
  562. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/tests/unit/test_launch_line_reentry.py +0 -0
  563. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/tests/unit/test_launch_via_env.py +0 -0
  564. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/tests/unit/test_locking.py +0 -0
  565. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/tests/unit/test_onboarding_reinit.py +0 -0
  566. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/tests/unit/test_owner_only_writes.py +0 -0
  567. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/tests/unit/test_palette_cli.py +0 -0
  568. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/tests/unit/test_pending_message_visibility.py +0 -0
  569. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/tests/unit/test_pip_environment.py +0 -0
  570. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/tests/unit/test_posture_default.py +0 -0
  571. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/tests/unit/test_project_config.py +0 -0
  572. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/tests/unit/test_projects_registry.py +0 -0
  573. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/tests/unit/test_prompt_router_resume.py +0 -0
  574. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/tests/unit/test_push.py +0 -0
  575. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/tests/unit/test_rebuild_guard.py +0 -0
  576. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/tests/unit/test_remote_session_record.py +0 -0
  577. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/tests/unit/test_repo_cli.py +0 -0
  578. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/tests/unit/test_rich_text_js.py +0 -0
  579. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/tests/unit/test_role_prompt_retention.py +0 -0
  580. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/tests/unit/test_role_prompt_sweep_wiring.py +0 -0
  581. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/tests/unit/test_roles.py +0 -0
  582. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/tests/unit/test_routes_snapshot.py +0 -0
  583. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/tests/unit/test_safety_disabled_rules.py +0 -0
  584. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/tests/unit/test_safety_escape_hatch.py +0 -0
  585. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/tests/unit/test_safety_heal.py +0 -0
  586. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/tests/unit/test_safety_kill_switch.py +0 -0
  587. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/tests/unit/test_scheduler.py +0 -0
  588. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/tests/unit/test_scheduler_liveness.py +0 -0
  589. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/tests/unit/test_scheduler_parsing.py +0 -0
  590. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/tests/unit/test_scheduler_zombie.py +0 -0
  591. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/tests/unit/test_scratchpad.py +0 -0
  592. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/tests/unit/test_security.py +0 -0
  593. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/tests/unit/test_server_async.py +0 -0
  594. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/tests/unit/test_server_pure.py +0 -0
  595. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/tests/unit/test_session_context.py +0 -0
  596. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/tests/unit/test_session_created_by_env.py +0 -0
  597. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/tests/unit/test_session_metadata_write.py +0 -0
  598. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/tests/unit/test_session_ready.py +0 -0
  599. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/tests/unit/test_shared_dir_guard.py +0 -0
  600. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/tests/unit/test_shim_selfheal.py +0 -0
  601. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/tests/unit/test_skill_install.py +0 -0
  602. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/tests/unit/test_speech_tags.py +0 -0
  603. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/tests/unit/test_ssh.py +0 -0
  604. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/tests/unit/test_stt_backend.py +0 -0
  605. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/tests/unit/test_stt_cloud.py +0 -0
  606. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/tests/unit/test_stt_engine.py +0 -0
  607. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/tests/unit/test_task_cli.py +0 -0
  608. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/tests/unit/test_task_max_duration.py +0 -0
  609. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/tests/unit/test_tasks.py +0 -0
  610. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/tests/unit/test_tasks_cli.py +0 -0
  611. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/tests/unit/test_templating.py +0 -0
  612. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/tests/unit/test_terminal_resize.py +0 -0
  613. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/tests/unit/test_tmux_session_cwd.py +0 -0
  614. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/tests/unit/test_tts_engine_resolution.py +0 -0
  615. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/tests/unit/test_tts_local.py +0 -0
  616. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/tests/unit/test_tunnels_probe.py +0 -0
  617. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/tests/unit/test_unattended_env_isolation.py +0 -0
  618. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/tests/unit/test_usage_limit.py +0 -0
  619. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/tests/unit/test_validation.py +0 -0
  620. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/tests/unit/test_voice_status.py +0 -0
  621. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/tests/unit/test_wiki.py +0 -0
  622. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/tests/unit/test_wiki_audit.py +0 -0
  623. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/tests/unit/test_worktree.py +0 -0
  624. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/tests/unit/test_worktree_branch_cleanup.py +0 -0
  625. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/tests/unit/test_worktree_layout.py +0 -0
  626. {agentwire_dev-1.68.0 → agentwire_dev-1.70.0}/tests/unit/test_worktree_registry.py +0 -0
@@ -10,7 +10,7 @@
10
10
  # is on PATH. Per the council guardrail we do NOT chase coverage % or block PRs
11
11
  # on flaky/tmux-dependent tests.
12
12
  #
13
- # Coverage is measured and surfaced (term-missing in the log + a table in the
13
+ # On pushes to main, coverage is measured and surfaced (term-missing in the log + a table in the
14
14
  # run's job summary + an uploaded coverage.xml artifact) but is REPORT-ONLY:
15
15
  # there is deliberately no --cov-fail-under, so a low percentage never reds the
16
16
  # build. The point is visibility — letting the maintainer spot untested
@@ -37,13 +37,22 @@ jobs:
37
37
  - name: Sync dependencies
38
38
  run: uv sync --extra dev
39
39
 
40
- - name: Run test suite (tmux-dependent tests deselected) + coverage
40
+ # Pull requests run the FAST set: no coverage tracing (it multiplies
41
+ # runtime on a hosted runner) and no `slow` tests (real git/tmux
42
+ # processes per test). A PR gate that takes 45 minutes gets bypassed.
43
+ - name: Run test suite (fast set)
44
+ if: github.event_name == 'pull_request'
45
+ run: uv run --no-sync pytest -q -m "not requires_tmux and not slow"
46
+
47
+ # Pushes to main run everything hermetic, with the report-only coverage.
48
+ - name: Run test suite (full) + coverage
49
+ if: github.event_name != 'pull_request'
41
50
  run: >
42
51
  uv run --no-sync pytest -q -m "not requires_tmux"
43
52
  --cov=agentwire --cov-report=term-missing --cov-report=xml
44
53
 
45
54
  - name: Publish coverage summary (report-only)
46
- if: always()
55
+ if: github.event_name != 'pull_request' && always()
47
56
  run: |
48
57
  {
49
58
  echo '## Coverage (report-only — no threshold gate)'
@@ -54,7 +63,7 @@ jobs:
54
63
  } >> "$GITHUB_STEP_SUMMARY"
55
64
 
56
65
  - name: Upload coverage.xml artifact
57
- if: always()
66
+ if: github.event_name != 'pull_request' && always()
58
67
  uses: actions/upload-artifact@v4
59
68
  with:
60
69
  name: coverage-xml
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.4
1
+ Metadata-Version: 2.5
2
2
  Name: agentwire-dev
3
- Version: 1.68.0
3
+ Version: 1.70.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.68.0"
3
+ __version__ = "1.70.0"
@@ -183,7 +183,7 @@ Command Categories:
183
183
  # - diff: structured git diff for the mobile Review window
184
184
  # - prompts: prompt routing (rides the limits watchdog)
185
185
  # - msg: polite agent-to-agent inbox (rides the watchdog)
186
- from . import diff_cli, limits_cli, msg_cli, pane_cli, prompts_cli, send_cli # noqa: I001 # session_cli kept on its own line below to minimize Phase 1 #495 merge conflicts
186
+ from . import activity_cli, alerts_cli, diff_cli, limits_cli, msg_cli, pane_cli, prompts_cli, send_cli # noqa: I001 # session_cli kept on its own line below to minimize Phase 1 #495 merge conflicts
187
187
  from . import session_cli
188
188
  from . import channels_cli, config_cli, portal_cli, tts_cli
189
189
  from . import scheduler_cli, ensure_cli, tasks_cli
@@ -191,12 +191,15 @@ Command Categories:
191
191
  from . import handoff_cli, hooks_cli, mcp_cli, roles_cli, tunnels_cli
192
192
  from . import notify_cli, palette_cli, push_cli, repo_cli, system_cli, wiki_cli
193
193
  from . import restart_cli, tabs_cli, wait_cli, worktree_cli
194
+ from . import buddy_cli # BETA: gated on beta.voice_layer (default off)
194
195
  from .council import cli as council_cli
195
196
 
196
197
  _REGISTRARS = [ # noqa: N806 # registry constant; Phase 1 of #495 appends here
197
198
  diff_cli.register_diff_parser,
198
199
  prompts_cli.register_prompts_parser,
199
200
  msg_cli.register_msg_parser,
201
+ alerts_cli.register_alerts_parser,
202
+ activity_cli.register_activity_parser,
200
203
  limits_cli.register_limits_parser,
201
204
  pane_cli.register_pane_parser,
202
205
  send_cli.register_send_parser,
@@ -228,6 +231,7 @@ Command Categories:
228
231
  tabs_cli.register_tabs_parser,
229
232
  wait_cli.register_wait_parser,
230
233
  worktree_cli.register_helper_parser,
234
+ buddy_cli.register_buddy_parser,
231
235
  ]
232
236
  for _reg in _REGISTRARS:
233
237
  _reg(subparsers)
@@ -0,0 +1,86 @@
1
+ """``agentwire activity`` — what the fleet has been doing (#1016).
2
+
3
+ The read side of :mod:`~agentwire.fleet_activity`. It exists as a CLI verb for
4
+ two reasons, and the second is the load-bearing one:
5
+
6
+ 1. "CLI is the single source of truth" — a store readable only from inside the
7
+ process tree that writes it is exactly the shape that rule exists to prevent.
8
+ 2. The voice layer dispatches **only** through the CLI (see
9
+ ``voice_layer/tools.py``), so without this verb the buddy could not read the
10
+ ledger that was built for it.
11
+
12
+ Read-only, by construction: nothing here writes. Producers record from inside
13
+ the surfaces that generate the events (idle, say, toast, scheduled run), never
14
+ from a verb an agent could be talked into calling.
15
+ """
16
+
17
+ from __future__ import annotations
18
+
19
+ import json
20
+ from datetime import timedelta
21
+
22
+ from . import fleet_activity
23
+
24
+ #: Widest window the verb will look back over. The ledger is capped at
25
+ #: ``MAX_ENTRIES`` anyway, so this bounds the ANSWER rather than the read: a
26
+ #: request for a week of awareness is a request for history, and
27
+ #: ``agentwire scheduler history`` / the event logs are where history lives.
28
+ MAX_HOURS = 72
29
+
30
+
31
+ def cmd_activity_list(args) -> int:
32
+ json_mode = getattr(args, "json", False)
33
+ hours = max(1, min(MAX_HOURS, int(getattr(args, "hours", 12) or 12)))
34
+ entries = fleet_activity.recent(
35
+ limit=max(1, int(getattr(args, "limit", 50) or 50)),
36
+ event=getattr(args, "event", "") or "",
37
+ session=getattr(args, "session", "") or "",
38
+ window=timedelta(hours=hours),
39
+ )
40
+ if json_mode:
41
+ print(json.dumps({
42
+ "success": True,
43
+ "count": len(entries),
44
+ "window_hours": hours,
45
+ "ledger": str(fleet_activity.ledger_path()),
46
+ "activity": entries,
47
+ }, indent=2))
48
+ return 0
49
+ if not entries:
50
+ print(f"No fleet activity recorded in the last {hours}h.")
51
+ return 0
52
+ for entry in entries:
53
+ # The announced flag is shown, not hidden: "recorded" and "said out
54
+ # loud" are different facts, and an operator debugging a chatty or a
55
+ # silent buddy needs to see which one an entry was.
56
+ mark = "*" if entry.get("announced") else " "
57
+ print(f"{mark} {entry.get('ts', '')} {entry.get('event', ''):<16} "
58
+ f"{entry.get('text', '')}")
59
+ print()
60
+ print("* = also queued to fleet-alert subscribers (spoken by the voice buddy at a gap)")
61
+ return 0
62
+
63
+
64
+ def register_activity_parser(subparsers) -> None:
65
+ parser = subparsers.add_parser(
66
+ "activity",
67
+ help="What the fleet has been doing (idle, tasks, toasts, speech)",
68
+ description=(
69
+ "The fleet's activity ledger: sessions going idle, scheduled tasks "
70
+ "finishing, toasts shown to the owner, and everything spoken aloud "
71
+ "through fleet TTS. This is AWARENESS — a record something can read "
72
+ "when asked. Only a short, ruled subset is also queued to "
73
+ "fleet-alert subscribers (see `agentwire alerts`); the rest waits "
74
+ "here to be looked up."
75
+ ),
76
+ )
77
+ sub = parser.add_subparsers(dest="activity_command", required=True)
78
+
79
+ p = sub.add_parser("list", help="Recent activity, newest first")
80
+ p.add_argument("--limit", type=int, default=50, help="Max entries (default: 50)")
81
+ p.add_argument("--hours", type=int, default=12,
82
+ help=f"How far back to look (1-{MAX_HOURS}, default: 12)")
83
+ p.add_argument("--event", choices=fleet_activity.EVENTS, help="Only this event type")
84
+ p.add_argument("-s", "--session", help="Only this session (exact name)")
85
+ p.add_argument("--json", action="store_true", help="Output JSON")
86
+ p.set_defaults(func=cmd_activity_list)
@@ -0,0 +1,153 @@
1
+ """``agentwire alerts`` — who hears the machine's own detectors (#982).
2
+
3
+ Fleet detectors (expired login, usage-limit park, dead-lettered report-backs, a
4
+ root pane blocked with nowhere to route) have always been able to email the
5
+ OWNER. ``fleet_alerts`` lets them address a SESSION as typed mail instead, and
6
+ this is the surface that turns that on: without a CLI verb the subscription API
7
+ would be reachable only from inside the tree that calls it, which is precisely
8
+ the shape "CLI is the single source of truth" exists to prevent.
9
+
10
+ Subscription is a renewable **lease**, so ``list`` reports the expiry rather
11
+ than a boolean: a subscriber that stopped renewing has silently stopped
12
+ hearing anything, and that is a state an operator has to be able to see.
13
+ """
14
+
15
+ from __future__ import annotations
16
+
17
+ import json
18
+
19
+ from . import fleet_alerts
20
+
21
+
22
+ def _emit(payload: dict, json_mode: bool, lines: "list[str] | None" = None) -> int:
23
+ if json_mode:
24
+ print(json.dumps(payload, indent=2))
25
+ else:
26
+ for line in lines or []:
27
+ print(line)
28
+ return 0 if payload.get("success", True) else 1
29
+
30
+
31
+ def cmd_alerts_subscribe(args) -> int:
32
+ json_mode = getattr(args, "json", False)
33
+ try:
34
+ lease = fleet_alerts.subscribe(args.session)
35
+ except Exception as exc:
36
+ return _emit(
37
+ {"success": False, "error": str(exc)}, json_mode, [f"error: {exc}"]
38
+ )
39
+ return _emit(
40
+ {"success": True, "session": args.session, "lease": lease},
41
+ json_mode,
42
+ [
43
+ f"'{args.session}' now receives fleet alerts.",
44
+ f" lease expires: {lease['expires_at']}",
45
+ " Renew before then — an expired lease goes quiet, it does not warn.",
46
+ ],
47
+ )
48
+
49
+
50
+ def cmd_alerts_unsubscribe(args) -> int:
51
+ json_mode = getattr(args, "json", False)
52
+ dropped = fleet_alerts.unsubscribe(args.session)
53
+ if not dropped:
54
+ return _emit(
55
+ {"success": False, "error": f"'{args.session}' was not subscribed"},
56
+ json_mode,
57
+ [f"'{args.session}' was not subscribed."],
58
+ )
59
+ return _emit(
60
+ {"success": True, "session": args.session},
61
+ json_mode,
62
+ [f"'{args.session}' no longer receives fleet alerts."],
63
+ )
64
+
65
+
66
+ def cmd_alerts_list(args) -> int:
67
+ """Who is subscribed — and whether this answer can be trusted.
68
+
69
+ ``list`` reads the same candidate index the emit path does, so a lost index
70
+ makes both of them say "nobody". That would be the worst property this
71
+ command could have: the one surface built to make a silent stop VISIBLE
72
+ would agree with the silent stop. So the index's presence is reported
73
+ alongside the answer, and its absence is not rendered as a confident zero.
74
+ """
75
+ json_mode = getattr(args, "json", False)
76
+ names = fleet_alerts.subscribers()
77
+ index_present = fleet_alerts.subscribers_index_path().exists()
78
+ rows = [{"session": n, "lease": fleet_alerts.subscription(n)} for n in names]
79
+ if names:
80
+ lines = [
81
+ "Sessions receiving fleet alerts:",
82
+ *(f" {r['session']} (lease expires {(r['lease'] or {}).get('expires_at')})"
83
+ for r in rows),
84
+ ]
85
+ elif index_present:
86
+ lines = ["No session is subscribed to fleet alerts."]
87
+ else:
88
+ lines = [
89
+ "No subscriber index — so this is NOT a confident 'nobody subscribed'.",
90
+ "Either nobody ever subscribed, or the index was lost; from here those "
91
+ "look identical, and while it is missing every alert reaches nobody.",
92
+ "Settle it (cheap, and it rebuilds the index either way):",
93
+ " agentwire alerts reindex",
94
+ ]
95
+ return _emit(
96
+ {
97
+ "success": True,
98
+ "subscribers": names,
99
+ "leases": rows,
100
+ "index_present": index_present,
101
+ },
102
+ json_mode,
103
+ lines,
104
+ )
105
+
106
+
107
+ def cmd_alerts_reindex(args) -> int:
108
+ """Rebuild the candidate index from the session records.
109
+
110
+ The alert path never walks the record store — that cost sits on the
111
+ synchronous permission-hook path — so a lost index means fewer alerts until
112
+ somebody rebuilds it. This is that somebody.
113
+ """
114
+ json_mode = getattr(args, "json", False)
115
+ names = fleet_alerts.reindex()
116
+ return _emit(
117
+ {"success": True, "subscribers": names},
118
+ json_mode,
119
+ [f"Reindexed: {len(names)} live subscriber(s)." , *(f" {n}" for n in names)],
120
+ )
121
+
122
+
123
+ def register_alerts_parser(subparsers) -> None:
124
+ parser = subparsers.add_parser(
125
+ "alerts",
126
+ help="Who hears the machine's own detectors (fleet alerts)",
127
+ description=(
128
+ "Fleet detectors — expired login, usage-limit park, dead-lettered "
129
+ "report-backs, a root pane blocked with nowhere to route — email the "
130
+ "owner. They can also address a SESSION as typed mail: an escalation "
131
+ "for the two conditions only a human can clear, a note or a request "
132
+ "for the rest. A session subscribes here, on a renewable lease."
133
+ ),
134
+ )
135
+ sub = parser.add_subparsers(dest="alerts_command", required=True)
136
+
137
+ p = sub.add_parser("subscribe", help="Lease fleet alerts for a session")
138
+ p.add_argument("session", help="Session name (must have a session record)")
139
+ p.add_argument("--json", action="store_true", help="JSON output")
140
+ p.set_defaults(func=cmd_alerts_subscribe)
141
+
142
+ p = sub.add_parser("unsubscribe", help="Drop a session's fleet-alert lease")
143
+ p.add_argument("session")
144
+ p.add_argument("--json", action="store_true", help="JSON output")
145
+ p.set_defaults(func=cmd_alerts_unsubscribe)
146
+
147
+ p = sub.add_parser("list", help="Sessions with a live lease, and its expiry")
148
+ p.add_argument("--json", action="store_true", help="JSON output")
149
+ p.set_defaults(func=cmd_alerts_list)
150
+
151
+ p = sub.add_parser("reindex", help="Rebuild the subscriber index from records")
152
+ p.add_argument("--json", action="store_true", help="JSON output")
153
+ p.set_defaults(func=cmd_alerts_reindex)
@@ -360,8 +360,10 @@ def record_outage(detail: dict, source: str = "ensure") -> dict:
360
360
  "source": source,
361
361
  "host": socket.gethostname(),
362
362
  "escalated_at": prior.get("escalated_at"),
363
+ "alerted_at": prior.get("alerted_at"),
363
364
  }
364
365
  state["escalated_at"] = _escalate(state, prior)
366
+ state["alerted_at"] = _alert_fleet(state, prior)
365
367
  write_state(state)
366
368
  log_event("outage_detected", session=detail.get("session"),
367
369
  transcript=detail.get("transcript"), source=source)
@@ -421,6 +423,50 @@ def _escalate(state: dict, prior: dict) -> str | None:
421
423
  return previous
422
424
 
423
425
 
426
+ def _alert_fleet(state: dict, prior: dict) -> "str | None":
427
+ """Tell subscribed sessions, on the same clock the owner email rides (#982).
428
+
429
+ Escalation kind, and this is the clearest case for it in the fleet: the
430
+ outage is machine-wide, every subsequent turn is refused, and nothing but a
431
+ human running ``/login`` can clear it. It is bounded to once per
432
+ :data:`ESCALATE_TTL` per outage — machine-wide, not per session and not per
433
+ dispatch — which is what makes an interrupt affordable here.
434
+
435
+ Stamped separately from ``escalated_at`` while sharing that field's state
436
+ record and its TTL. Not a parallel throttle store — the same file, the same
437
+ window — but a separate stamp, because the two channels fail differently:
438
+ the email deliberately retries per detection when the provider is down
439
+ (only a successful send stamps), and an alert inheriting that retry would
440
+ turn a broken Resend key into one interrupt per dispatch. Enqueueing is a
441
+ local write, so this stamp lands whenever the alert actually did.
442
+ """
443
+ previous = prior.get("alerted_at")
444
+ if previous:
445
+ try:
446
+ if _now() - datetime.fromisoformat(previous) < ESCALATE_TTL:
447
+ return previous
448
+ except (TypeError, ValueError):
449
+ pass
450
+ try:
451
+ from . import fleet_alerts
452
+
453
+ sessions = ", ".join(state.get("sessions") or []) or "(none recorded)"
454
+ reached = fleet_alerts.emit_for(
455
+ "auth_expired",
456
+ f"Claude login expired on {state.get('host')} — every turn is being "
457
+ f"refused ({RENDERED}). Sessions hit so far: {sessions}. Scheduled "
458
+ f"dispatch is gated until someone runs /login; nothing recovers on "
459
+ f"its own. First seen {state.get('detected_at')}.",
460
+ )
461
+ except Exception as exc: # alerting is best-effort; never break the gate
462
+ log_event("alert_failed", error=str(exc))
463
+ return previous
464
+ if not reached:
465
+ return previous
466
+ log_event("alerted", sessions=state.get("sessions"), to=reached)
467
+ return _now().isoformat()
468
+
469
+
424
470
  def check_and_flag(
425
471
  session: str, project_path=None, since: float | None = None, source: str = "ensure"
426
472
  ) -> dict | None:
@@ -0,0 +1,193 @@
1
+ """``agentwire.beta`` — the one implementation of the beta gate.
2
+
3
+ A beta feature ships on ``main`` and stays off until a user asks for it. The
4
+ flag VALUES live in :mod:`agentwire.config` (``BetaConfig``); the MECHANICS of
5
+ hiding gated text live here, because the same mechanism now serves two
6
+ model-facing surfaces and a third would otherwise grow its own copy:
7
+
8
+ - **role prompts** (markdown) — resolved in ``roles.parse_role_file``;
9
+ - **MCP tool descriptions** (docstrings) — resolved by :func:`gated_doc`.
10
+
11
+ Both are text a model reads and a user pays tokens for, which is the property
12
+ that decides what belongs behind a gate. The MCP schema was missed on the first
13
+ pass: ``msg_send``'s description grew ~316 characters of voice-buddy prose that
14
+ loaded into every agent session in every install, ungated, while the commit
15
+ message asserted the role prompts were the only such surface. The lesson is in
16
+ this module's existence — one gate, one place, and a byte-identity proof per
17
+ surface rather than per file.
18
+ """
19
+
20
+ from __future__ import annotations
21
+
22
+ import re
23
+
24
+ #: A gated region:
25
+ #:
26
+ #: <!-- beta:voice_layer -->
27
+ #: ...text that only ships when beta.voice_layer is on...
28
+ #: <!-- /beta:voice_layer -->
29
+ #:
30
+ #: Leading whitespace is allowed on both markers (a docstring cannot put them in
31
+ #: column 0) and the close tag may end the string with no trailing newline. Both
32
+ #: shapes previously failed OPEN — the region simply did not match, and its text
33
+ #: shipped ungated, which is the one failure direction a gate may not have.
34
+ #:
35
+ #: The backreference means open and close must name the SAME flag, so a mistyped
36
+ #: close tag matches nothing. That case still fails open — it cannot be resolved
37
+ #: without guessing where the region ends — and is caught instead by the audit
38
+ #: in ``tests/unit/test_beta_flag.py``, which asserts no marker-shaped text
39
+ #: survives :func:`apply_beta_blocks` in any shipped role file.
40
+ BETA_BLOCK_RE = re.compile(
41
+ r"^[ \t]*<!-- beta:([a-z0-9_]+) -->[ \t]*\n(.*?)^[ \t]*<!-- /beta:\1 -->[ \t]*(?:\n|\Z)",
42
+ re.MULTILINE | re.DOTALL,
43
+ )
44
+
45
+ #: Anything marker-SHAPED, paired or not. The audit's instrument: what
46
+ #: :data:`BETA_BLOCK_RE` leaves behind is exactly the set of broken markers.
47
+ LOOSE_MARKER_RE = re.compile(r"<!--\s*/?\s*beta:[^>]*-->")
48
+
49
+ #: A stray marker on its own line, removed at render time only — see
50
+ #: :func:`render` for why that is deliberately NOT done in
51
+ #: :func:`apply_beta_blocks`.
52
+ _STRAY_MARKER_LINE_RE = re.compile(
53
+ r"^[ \t]*<!--\s*/?\s*beta:[^>]*-->[ \t]*(?:\n|\Z)", re.MULTILINE
54
+ )
55
+
56
+ _CACHE: "set[str] | None" = None
57
+
58
+
59
+ def flag_names() -> frozenset[str]:
60
+ """The flags a marker may legally name. Owned by :mod:`agentwire.config`."""
61
+ from .config import BETA_FLAG_NAMES
62
+
63
+ return BETA_FLAG_NAMES
64
+
65
+
66
+ def enabled_flags() -> set[str]:
67
+ """Which beta features are on, cached for the life of the process.
68
+
69
+ Cached because the gate sits on a hot path: ``parse_role_file`` runs once
70
+ per role per session launch, and an uncached read cost a full
71
+ ``load_config`` — with its stderr INFO line — each time, taking ``roles
72
+ list`` from 11ms to 242ms and printing 24 log lines, for a feature almost
73
+ nobody has enabled.
74
+
75
+ The consequence is stated rather than hidden: a long-lived process
76
+ observes the flag state it started with, so turning a beta feature on takes
77
+ the restart that ``config.yaml`` changes already take. An import-time
78
+ surface like an MCP tool description is process-lifetime by construction
79
+ anyway. :func:`reset_cache` exists for tests.
80
+
81
+ **The precondition that makes the ON direction safe, written down because
82
+ it is not visible from here.** A cached ``{"voice_layer"}`` outlives a
83
+ config that has since said off — verified: gated prose keeps rendering
84
+ until :func:`reset_cache`. That is unreachable today only because every
85
+ in-process caller of ``load_roles``/``parse_role_file`` is a short-lived
86
+ CLI module, and the surfaces that look long-lived are not: ``role show``
87
+ and ``roles list`` shell out through ``run_agentwire_cmd``, so each render
88
+ happens in a fresh process that re-reads the flag.
89
+
90
+ **A long-lived in-process caller would violate that**, and would do it
91
+ silently — the gate would keep a feature ON for a user who turned it off,
92
+ with no error anywhere. If you add one (a portal route rendering role text
93
+ in-process, a daemon calling ``parse_role_file``), either call
94
+ :func:`reset_cache` at the top of each request or give that caller an
95
+ explicit ``enabled`` set. Do not discover this precondition by tripping it.
96
+ """
97
+ global _CACHE
98
+ if _CACHE is None:
99
+ from .config import enabled_beta_flags
100
+
101
+ _CACHE = enabled_beta_flags()
102
+ return _CACHE
103
+
104
+
105
+ def reset_cache() -> None:
106
+ """Drop the cached flag set (tests; a process that rewrote its own config)."""
107
+ global _CACHE
108
+ _CACHE = None
109
+
110
+
111
+ def apply_beta_blocks(text: str, enabled: set[str]) -> str:
112
+ """Resolve every PAIRED gated region in *text*.
113
+
114
+ Enabled flag → the body ships, with the marker lines removed (they are
115
+ scaffolding, and shipping them would cost the tokens the gate exists to
116
+ save). Disabled — or a flag name nothing knows about — → the whole region
117
+ goes, markers included.
118
+
119
+ **An unknown flag fails CLOSED**, and that direction is chosen rather than
120
+ inherited: text no gate can turn off is precisely the failure this module
121
+ exists to prevent. What makes it safe rather than silent is the paired
122
+ audit — a test fails on any marker naming a flag ``config.BETA_FLAG_NAMES``
123
+ does not know, so a typo is caught before it can delete a section forever.
124
+
125
+ Deliberately does NOT remove unpaired markers: this function's output is
126
+ what the audit measures, and swallowing broken markers here would make that
127
+ audit unable to fail. :func:`render` does that, at the edge.
128
+ """
129
+ known = flag_names()
130
+
131
+ def _resolve(match: "re.Match") -> str:
132
+ flag, body = match.group(1), match.group(2)
133
+ return body if (flag in known and flag in enabled) else ""
134
+
135
+ return BETA_BLOCK_RE.sub(_resolve, text)
136
+
137
+
138
+ def render(text: str, enabled: "set[str] | None" = None) -> str:
139
+ """Resolve gated regions for text about to reach a model.
140
+
141
+ :func:`apply_beta_blocks`, then strip any marker line left over. That second
142
+ step fixes only the smaller half of a broken marker: the region it was meant
143
+ to wrap is still ungated (the audit is what catches that), but the
144
+ scaffolding itself never reaches the model as prose.
145
+ """
146
+ # Text with no marker cannot change, so it must not pay for the flag
147
+ # lookup — that is 20 of the 24 shipped role files and 107 of the 108 MCP
148
+ # tool descriptions, several of which resolve at IMPORT time. Cheap
149
+ # substring scan, and it keys on the same literal the regexes do.
150
+ if enabled is None:
151
+ if "beta:" not in text:
152
+ return text
153
+ enabled = enabled_flags()
154
+ return _STRAY_MARKER_LINE_RE.sub("", apply_beta_blocks(text, enabled))
155
+
156
+
157
+ def gated_doc(fn):
158
+ """Resolve gated regions in a function's docstring, in place.
159
+
160
+ For MCP tools, apply it BELOW ``@mcp.tool()`` so FastMCP reads the resolved
161
+ text::
162
+
163
+ @mcp.tool()
164
+ @gated_doc
165
+ def msg_send(...):
166
+ \"\"\"...\"\"\"
167
+
168
+ Decorators apply bottom-up, so the docstring is already resolved by the time
169
+ the tool is registered — and FastMCP snapshots the docstring AT
170
+ registration, publishing it as the tool description, which is what makes
171
+ this the whole fix.
172
+
173
+ **Inverting the two silently un-gates the tool**, measured rather than
174
+ feared: with ``@gated_doc`` above ``@mcp.tool()`` the raw text publishes,
175
+ markers and all (2165 chars vs 1800). Nothing about the wrong order looks
176
+ wrong, so the property is pinned over the WHOLE registry —
177
+ ``test_no_published_description_carries_a_marker`` fails on any published
178
+ description containing a marker, whatever put it there.
179
+
180
+ The resolution happens ONCE, at import, against whatever flag state the
181
+ process started with — so any later reader that wants to verify the
182
+ resolved text needs to know which flags it was resolved WITH, not which
183
+ flags are on now. ``__beta_enabled__`` records exactly that (and
184
+ ``__beta_raw_doc__`` the pre-resolution text), which is what lets the
185
+ byte-identity tests hold on a machine with a beta flag enabled instead of
186
+ silently asserting the developer's personal config (#1023).
187
+ """
188
+ if fn.__doc__ and "beta:" in fn.__doc__:
189
+ enabled = enabled_flags()
190
+ fn.__beta_raw_doc__ = fn.__doc__
191
+ fn.__beta_enabled__ = frozenset(enabled)
192
+ fn.__doc__ = render(fn.__doc__, enabled=enabled)
193
+ return fn