agentwire-dev 1.65.0__tar.gz → 1.65.1__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.
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/PKG-INFO +1 -1
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/__init__.py +1 -1
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/core.py +12 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/inbox.py +65 -32
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/docs/wiki/sessions/messaging.md +8 -2
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/tests/conftest.py +1 -1
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/tests/unit/test_core_created_by_rooting.py +11 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/tests/unit/test_inbox.py +71 -7
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/.agentwire.yml.example +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/.claude/commands/handoff.md +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/.claude/skills/wiki/SKILL.md +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/.github/FUNDING.yml +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/.github/ISSUE_TEMPLATE/question.md +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/.github/workflows/pytest.yml +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/.github/workflows/ruff.yml +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/.github/workflows/security.yml +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/.github/workflows/tts-smoke.yml +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/.gitignore +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/AGENTS.md +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/CODE_OF_CONDUCT.md +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/CONTRIBUTING.md +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/Dockerfile.local +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/LICENSE +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/README.md +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/RELEASING.md +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/SECURITY.md +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/SPONSORS.md +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/__main__.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/agents/__init__.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/agents/base.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/agents/tmux.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/cached_status.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/channels/__init__.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/channels/base.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/channels/email.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/channels/push.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/channels/quo.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/channels_cli.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/chrome_tabs.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/completion.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/config.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/config_cli.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/council/__init__.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/council/cli.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/council/inbox.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/council/minutes.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/council/state.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/council/view.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/devices.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/diff_cli.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/doctor_cli.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/doctor_voice.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/ensure_cli.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/fetch.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/handoff/__init__.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/handoff/git_state.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/handoff/instructions.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/handoff/parser.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/handoff/renderer.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/handoff/schema.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/handoff_cli.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/history.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/history_cli.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/hooks/__init__.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/hooks/agentwire-permission.sh +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/hooks/damage-control/__init__.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/hooks/damage-control/audit_logger.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/hooks/damage-control/bash-tool-damage-control.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/hooks/damage-control/edit-tool-damage-control.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/hooks/damage-control/mcp-tool-damage-control.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/hooks/damage-control/read-tool-damage-control.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/hooks/damage-control/rules/agentwire.yaml +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/hooks/damage-control/rules/aws.yaml +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/hooks/damage-control/rules/cloud-hosting.yaml +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/hooks/damage-control/rules/containers.yaml +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/hooks/damage-control/rules/control-plane.yaml +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/hooks/damage-control/rules/core.yaml +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/hooks/damage-control/rules/databases.yaml +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/hooks/damage-control/rules/firebase.yaml +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/hooks/damage-control/rules/gcp.yaml +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/hooks/damage-control/rules/git.yaml +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/hooks/damage-control/rules/gws.yaml +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/hooks/damage-control/rules/infrastructure.yaml +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/hooks/damage-control/rules/outbound.yaml +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/hooks/damage-control/rules/publish.yaml +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/hooks/damage-control/rules/remote.yaml +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/hooks/damage-control/write-tool-damage-control.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/hooks/idle-handler.sh +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/hooks/queue-processor.sh +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/hooks_cli.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/limits_cli.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/listen.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/locking.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/machine_cli.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/mcp_channels.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/mcp_chrome.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/mcp_cli.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/mcp_core.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/mcp_council.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/mcp_desktop.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/mcp_handoff.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/mcp_history.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/mcp_listen.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/mcp_lock.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/mcp_machine.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/mcp_msg.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/mcp_notify.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/mcp_pane.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/mcp_projects.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/mcp_scheduler.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/mcp_scratchpad.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/mcp_server.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/mcp_services.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/mcp_session.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/mcp_status.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/mcp_task.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/mcp_tunnels.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/mcp_voice.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/mcp_wiki.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/mcp_worktree.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/msg_cli.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/network.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/notify_cli.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/onboarding.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/palette_cli.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/pane_cli.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/pane_manager.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/portal_cli.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/project_config.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/projects.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/prompt_router.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/prompts_cli.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/push_cli.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/push_store.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/repo_cli.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/research.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/roles/__init__.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/roles/agentwire.md +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/roles/anchor.md +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/roles/chatbot.md +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/roles/contributor.md +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/roles/correspondent.md +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/roles/council-brain.md +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/roles/council-conscience.md +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/roles/council-critic.md +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/roles/council-devils-advocate.md +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/roles/council-gut.md +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/roles/council-historian.md +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/roles/council-member.md +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/roles/council-orchestrator.md +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/roles/init.md +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/roles/notifications.md +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/roles/orchestrator.md +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/roles/reviewer-worktree.md +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/roles/reviewer.md +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/roles/soul.md +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/roles/task-runner.md +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/roles/voice.md +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/roles/worker-worktree.md +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/roles/worker.md +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/roles_cli.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/routes/__init__.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/routes/artifacts.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/routes/config.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/routes/council.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/routes/desktop.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/routes/history.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/routes/machines.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/routes/notify.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/routes/palette.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/routes/permission.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/routes/projects.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/routes/push.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/routes/safety.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/routes/scheduler.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/routes/scratchpad.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/routes/sessions.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/routes/sessions_admin.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/routes/voice.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/safety/__init__.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/safety/_core.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/safety_cli.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/safety_commands.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/scheduler/__init__.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/scheduler/dispatch.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/scheduler/gates.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/scheduler/loop.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/scheduler/models.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/scheduler/report.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/scheduler/schedule.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/scheduler/state.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/scheduler/zombie.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/scheduler_cli.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/scratchpad.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/security.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/send_cli.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/server.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/services.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/session_cli.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/session_context.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/session_ready.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/ssh.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/static/agentwire-splash-logo-layers--agentwire-text.png +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/static/agentwire-splash-logo-layers--echo-claw-fg.png +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/static/agentwire-splash-logo-layers--echo.png +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/static/agentwire-splash-logo-layers--telephone.png +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/static/agentwire-splash-logo-layers--tree.png +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/static/announcements.json +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/static/apple-touch-icon.png +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/static/css/desktop.css +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/static/css/mobile.css +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/static/favicon-32.png +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/static/favicon-64.png +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/static/icons/sessions/bear.webp +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/static/icons/sessions/cat.webp +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/static/icons/sessions/crown.webp +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/static/icons/sessions/custom/agentwire-portal.webp +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/static/icons/sessions/custom/agentwire-tts.webp +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/static/icons/sessions/custom/agentwire.webp +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/static/icons/sessions/deer.webp +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/static/icons/sessions/drone.webp +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/static/icons/sessions/eagle.webp +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/static/icons/sessions/fox.webp +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/static/icons/sessions/hawk.webp +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/static/icons/sessions/horse.webp +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/static/icons/sessions/lion.webp +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/static/icons/sessions/rabbit.webp +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/static/icons/sessions/robot.webp +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/static/icons/sessions/tiger.webp +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/static/icons/sessions/wolf.webp +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/static/img/icon-192.png +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/static/img/icon-512.png +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/static/js/.gitkeep +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/static/js/announcement-modal.js +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/static/js/api.js +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/static/js/artifact-window.js +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/static/js/card-terminal.js +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/static/js/collage.js +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/static/js/command-palette.js +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/static/js/council-window.js +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/static/js/dead-key-suppressor.js +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/static/js/desktop-manager.js +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/static/js/desktop.js +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/static/js/help-modal.js +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/static/js/icon-manager.js +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/static/js/lineage.js +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/static/js/mobile.js +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/static/js/notification-prefs.js +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/static/js/notifications-panel.js +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/static/js/ptt.js +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/static/js/push-client.js +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/static/js/review-window.js +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/static/js/safety-shared.js +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/static/js/safety-window.js +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/static/js/scratchpad.js +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/static/js/service-classification.js +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/static/js/session-hud-controller.js +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/static/js/session-hud-notices.js +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/static/js/session-hud-spawn.js +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/static/js/session-hud.js +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/static/js/session-id.js +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/static/js/session-window.js +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/static/js/shortcuts.js +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/static/js/sidebar/artifacts-section.js +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/static/js/sidebar/config-section.js +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/static/js/sidebar/council-section.js +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/static/js/sidebar/machines-section.js +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/static/js/sidebar/projects-section.js +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/static/js/sidebar/safety-section.js +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/static/js/sidebar/scheduler-section.js +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/static/js/sidebar/services-section.js +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/static/js/sidebar/sessions-section.js +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/static/js/sidebar.js +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/static/js/spawn-ghost.js +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/static/js/terminal-font-prefs.js +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/static/js/terminal-pane.js +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/static/js/tile-manager.js +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/static/js/toast.js +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/static/js/token-modal.js +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/static/js/topology-render.js +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/static/js/utils/ansi.js +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/static/js/utils/rich-text.js +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/static/js/utils/swipe.js +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/static/js/voice/autosend-prefs.js +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/static/js/voice/browser-stt.js +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/static/js/voice/browser-tts.js +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/static/js/voice/jargon.js +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/static/js/voice/prompt.js +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/static/js/winbox.bundle.min.js +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/static/js/workspace-window.js +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/static/manifest.webmanifest +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/static/service-worker.js +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/static/topology-harness.html +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/stt/__init__.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/stt/base.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/stt/cloud.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/stt/engine.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/stt/local.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/stt/server_backend.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/stt/stt_server.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/system_cli.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/tabs_cli.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/tasks.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/tasks_cli.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/templates/__init__.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/templates/base.html +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/templates/council/minutes.html.j2 +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/templates/desktop.html +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/templates/email_notification.html +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/templates/handoff/show-the-story.html.j2 +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/templates/handoff/theme.css.j2 +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/templates/mobile.html +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/templates/pair.html +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/templates/tmux.conf +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/templating.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/tooldefs/aws.yaml +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/tooldefs/docker.yaml +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/tooldefs/gcp.yaml +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/tooldefs/gh.yaml +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/tooldefs/git.yaml +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/tooldefs/gws.yaml +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/tooldefs/kubectl.yaml +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/tooldefs/npm.yaml +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/tooldefs/terraform.yaml +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/tooldefs/uv.yaml +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/tts/__init__.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/tts/audio.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/tts/base.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/tts/engines/__init__.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/tts/engines/chatterbox.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/tts/engines/kokoro.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/tts/engines/zonos.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/tts/kokoro_server.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/tts/local.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/tts/registry.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/tts_cli.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/tts_server.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/tunnels.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/tunnels_cli.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/usage_limit.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/utils/__init__.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/utils/chunker.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/utils/event_log.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/utils/file_io.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/utils/paths.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/utils/speech.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/utils/subprocess.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/validation.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/voice_status.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/wiki.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/wiki_audit.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/wiki_cli.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/worktree.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/worktree_registry.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/docs/decisions/obsidian-second-brain.md +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/docs/design/session-card-fields.md +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/docs/design/session-card-recommendation.md +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/docs/logo.png +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/docs/wiki/INDEX.md +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/docs/wiki/architecture.md +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/docs/wiki/briefing-mode.md +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/docs/wiki/communication/channels.md +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/docs/wiki/communication/hammerspoon.md +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/docs/wiki/communication/handoff.md +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/docs/wiki/concepts.md +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/docs/wiki/council.md +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/docs/wiki/deployment/remote-access.md +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/docs/wiki/deployment/remote-machines.md +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/docs/wiki/glossary.md +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/docs/wiki/integrations/gws-google-workspace-cli.md +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/docs/wiki/internals/damage-control.md +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/docs/wiki/internals/parallel-refactor.md +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/docs/wiki/internals/portal.md +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/docs/wiki/internals/session-topology.md +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/docs/wiki/internals/shell-escaping.md +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/docs/wiki/internals/troubleshooting.md +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/docs/wiki/internals/window-collage.md +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/docs/wiki/quickstart.md +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/docs/wiki/research/briefing-mode-feasibility.md +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/docs/wiki/research/orchestration-transport-alternatives.md +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/docs/wiki/scheduling/scheduled-workloads.md +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/docs/wiki/security/damage-control-hardening.md +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/docs/wiki/security/pip-audit.md +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/docs/wiki/security/remote-access-hardening.md +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/docs/wiki/security/secrets.md +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/docs/wiki/services.md +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/docs/wiki/sessions/claude-code-auto-mode.md +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/docs/wiki/sessions/prompt-routing.md +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/docs/wiki/sessions/window-sizing.md +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/docs/wiki/sessions/worktree-sessions.md +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/docs/wiki/usage-limit-recovery.md +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/docs/wiki/voice/shim-contract.md +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/docs/wiki/voice/stt-cloud.md +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/docs/wiki/voice/stt-self-hosted.md +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/docs/wiki/voice/tts-self-hosted.md +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/pyproject.toml +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/tests/e2e/test_portal_ui.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/tests/fixtures/sample_agentwire.yml +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/tests/fixtures/sample_config.yaml +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/tests/fixtures/sample_scheduler.yaml +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/tests/integration/test_council_portal.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/tests/integration/test_scheduler_board.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/tests/integration/test_send_verified_tmux.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/tests/integration/test_server_websockets.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/tests/integration/test_worktree_cmd.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/tests/unit/test_announcements.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/tests/unit/test_build_agent_command.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/tests/unit/test_channels.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/tests/unit/test_chrome_tabs.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/tests/unit/test_cli_commands.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/tests/unit/test_cli_output.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/tests/unit/test_cli_smoke.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/tests/unit/test_config.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/tests/unit/test_config_cli.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/tests/unit/test_control_plane_protection.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/tests/unit/test_council_cli.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/tests/unit/test_council_inbox.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/tests/unit/test_council_minutes.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/tests/unit/test_council_state.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/tests/unit/test_council_view.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/tests/unit/test_damage_control_bypass.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/tests/unit/test_damage_control_hooks.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/tests/unit/test_damage_control_sync.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/tests/unit/test_dangling_worktrees.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/tests/unit/test_devices.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/tests/unit/test_diff_cli.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/tests/unit/test_doctor_scheduler_staleness.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/tests/unit/test_doctor_task_migration.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/tests/unit/test_doctor_voice.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/tests/unit/test_event_log.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/tests/unit/test_file_io.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/tests/unit/test_guarded_launch_command.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/tests/unit/test_handoff_git_state.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/tests/unit/test_handoff_instructions.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/tests/unit/test_handoff_parser.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/tests/unit/test_handoff_renderer.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/tests/unit/test_history.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/tests/unit/test_hooks_install.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/tests/unit/test_idle_handler.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/tests/unit/test_idle_nag.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/tests/unit/test_init_command.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/tests/unit/test_install_parity.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/tests/unit/test_limits_tick_isolation.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/tests/unit/test_locking.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/tests/unit/test_mcp_server.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/tests/unit/test_mcp_tools_args.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/tests/unit/test_msg_cli.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/tests/unit/test_notify_cli.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/tests/unit/test_onboarding_reinit.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/tests/unit/test_palette_cli.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/tests/unit/test_pip_environment.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/tests/unit/test_portal_api.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/tests/unit/test_posture_default.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/tests/unit/test_project_config.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/tests/unit/test_projects_registry.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/tests/unit/test_prompt_router.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/tests/unit/test_push.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/tests/unit/test_rebuild_guard.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/tests/unit/test_repo_cli.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/tests/unit/test_rich_text_js.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/tests/unit/test_roles.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/tests/unit/test_routes_snapshot.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/tests/unit/test_safety_commands.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/tests/unit/test_safety_disabled_rules.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/tests/unit/test_safety_escape_hatch.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/tests/unit/test_safety_heal.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/tests/unit/test_safety_kill_switch.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/tests/unit/test_scheduler.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/tests/unit/test_scheduler_parsing.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/tests/unit/test_scheduler_zombie.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/tests/unit/test_scratchpad.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/tests/unit/test_security.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/tests/unit/test_server_async.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/tests/unit/test_server_pure.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/tests/unit/test_services.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/tests/unit/test_session_context.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/tests/unit/test_session_created_by_env.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/tests/unit/test_session_ready.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/tests/unit/test_shared_dir_guard.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/tests/unit/test_shim_selfheal.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/tests/unit/test_skill_install.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/tests/unit/test_speech_tags.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/tests/unit/test_ssh.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/tests/unit/test_stt_backend.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/tests/unit/test_stt_cloud.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/tests/unit/test_stt_engine.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/tests/unit/test_task_cli.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/tests/unit/test_tasks.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/tests/unit/test_tasks_cli.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/tests/unit/test_templating.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/tests/unit/test_terminal_resize.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/tests/unit/test_tmux_template.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/tests/unit/test_tts_engine_resolution.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/tests/unit/test_tts_local.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/tests/unit/test_tunnels_probe.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/tests/unit/test_unattended_env_isolation.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/tests/unit/test_usage_limit.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/tests/unit/test_validation.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/tests/unit/test_voice_status.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/tests/unit/test_wiki.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/tests/unit/test_wiki_audit.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/tests/unit/test_window_cycling_binding.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/tests/unit/test_worktree.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/tests/unit/test_worktree_branch_cleanup.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/tests/unit/test_worktree_layout.py +0 -0
- {agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/tests/unit/test_worktree_registry.py +0 -0
|
@@ -479,9 +479,21 @@ def resolve_default_created_by(caller: str | None, target_path: Path) -> str | N
|
|
|
479
479
|
`{project}-{name}`, and would misjudge same/cross-project); if the
|
|
480
480
|
caller's real cwd can't be confirmed, treat it as unknown (no inheritance)
|
|
481
481
|
rather than risk a wrong guess.
|
|
482
|
+
|
|
483
|
+
A service session (agentwire-portal, -tts, -stt, -kokoro, ...) never
|
|
484
|
+
qualifies as a parent: it's infrastructure, not an agent that will ever
|
|
485
|
+
drain its msg inbox, so anything parented to it dead-letters forever. A
|
|
486
|
+
subprocess the portal shells out to inherits its TMUX_PANE and resolves
|
|
487
|
+
``caller`` right back to "agentwire-portal" — this was the root cause of
|
|
488
|
+
a 147-message dead-letter storm (each mailing the owner individually,
|
|
489
|
+
2026-07-19).
|
|
482
490
|
"""
|
|
483
491
|
if not caller:
|
|
484
492
|
return None
|
|
493
|
+
from .services import is_service_session
|
|
494
|
+
|
|
495
|
+
if is_service_session(caller):
|
|
496
|
+
return None
|
|
485
497
|
caller_path = _live_session_cwd(caller)
|
|
486
498
|
if caller_path is None:
|
|
487
499
|
return None
|
|
@@ -453,6 +453,7 @@ def gc_sender(sender: str) -> dict:
|
|
|
453
453
|
# delivered, not lost. Skip GC for this recipient this round.
|
|
454
454
|
continue
|
|
455
455
|
try:
|
|
456
|
+
newly_dead: list[Message] = []
|
|
456
457
|
for path in paths:
|
|
457
458
|
if not path.exists():
|
|
458
459
|
continue # delivered + unlinked just before we locked
|
|
@@ -472,7 +473,7 @@ def gc_sender(sender: str) -> dict:
|
|
|
472
473
|
attempts=msg.attempts, reason="sender_exited",
|
|
473
474
|
)
|
|
474
475
|
dead += 1
|
|
475
|
-
|
|
476
|
+
newly_dead.append(msg)
|
|
476
477
|
except OSError:
|
|
477
478
|
pass
|
|
478
479
|
else:
|
|
@@ -481,6 +482,8 @@ def gc_sender(sender: str) -> dict:
|
|
|
481
482
|
dropped += 1
|
|
482
483
|
except OSError:
|
|
483
484
|
pass
|
|
485
|
+
# One digest per recipient, not one email per message (#836).
|
|
486
|
+
_escalate_dead_letters(newly_dead, "sender_exited")
|
|
484
487
|
finally:
|
|
485
488
|
_release_lock(lock)
|
|
486
489
|
|
|
@@ -608,17 +611,32 @@ def _fmt_ts(ms: int) -> str:
|
|
|
608
611
|
return time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(ms / 1000))
|
|
609
612
|
|
|
610
613
|
|
|
611
|
-
|
|
612
|
-
|
|
614
|
+
# A single stuck recipient (e.g. a session wrongly parented to a service
|
|
615
|
+
# session that can never drain its inbox) can dead-letter dozens of messages
|
|
616
|
+
# in one drain pass — cap the per-message detail in the digest so the email
|
|
617
|
+
# stays readable instead of dumping an unbounded wall of text.
|
|
618
|
+
_ESCALATE_DIGEST_DETAIL_CAP = 10
|
|
619
|
+
|
|
620
|
+
|
|
621
|
+
def _escalate_dead_letters(messages: list[Message], reason: str) -> None:
|
|
622
|
+
"""Email the owner once per batch when load-bearing report-backs dead-letter.
|
|
613
623
|
|
|
614
624
|
``done`` / ``request`` / ``escalation`` are load-bearing — a silently-dropped
|
|
615
625
|
one is a real loss, so we surface it out-of-band via the shared Resend wiring
|
|
616
626
|
(the same owner-escalation channel usage-limit parking uses). ``note`` and
|
|
617
|
-
``ingest`` are not escalated.
|
|
618
|
-
|
|
619
|
-
|
|
627
|
+
``ingest`` are not escalated.
|
|
628
|
+
|
|
629
|
+
*messages* is everything dead-lettered by one caller's batch (one drain
|
|
630
|
+
pass for one recipient, or one sender's GC sweep) — a single digest email
|
|
631
|
+
covers the whole batch instead of one email per message, so a recipient
|
|
632
|
+
that's been permanently undeliverable for a while (e.g. parented to a
|
|
633
|
+
service session that never drains) can't spam the owner's inbox one email
|
|
634
|
+
per stuck message (147 individual emails in ~2s, 2026-07-19). Best-effort:
|
|
635
|
+
a missing key or send failure must never break the drain — each corpse
|
|
636
|
+
already sits in ``dead/`` for ``agentwire msg dead``.
|
|
620
637
|
"""
|
|
621
|
-
if
|
|
638
|
+
batch = [m for m in messages if m.kind in ESCALATE_KINDS]
|
|
639
|
+
if not batch:
|
|
622
640
|
return
|
|
623
641
|
try:
|
|
624
642
|
import socket
|
|
@@ -626,36 +644,47 @@ def _escalate_dead_letter(msg: Message, reason: str) -> None:
|
|
|
626
644
|
from .channels.email import send_email
|
|
627
645
|
|
|
628
646
|
host = socket.gethostname()
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
f"
|
|
643
|
-
""
|
|
644
|
-
"
|
|
647
|
+
if len(batch) == 1:
|
|
648
|
+
msg = batch[0]
|
|
649
|
+
subject = (
|
|
650
|
+
f"[agentwire] undelivered {msg.kind}: {msg.sender} → {msg.to} (dead-lettered)"
|
|
651
|
+
)
|
|
652
|
+
else:
|
|
653
|
+
to = batch[0].to
|
|
654
|
+
subject = (
|
|
655
|
+
f"[agentwire] {len(batch)} undelivered messages → {to} (dead-lettered)"
|
|
656
|
+
)
|
|
657
|
+
noun = "message" if len(batch) == 1 else "messages"
|
|
658
|
+
verb = "was" if len(batch) == 1 else "were"
|
|
659
|
+
lines = [
|
|
660
|
+
f"{len(batch)} load-bearing {noun} on `{host}` {verb} never delivered "
|
|
661
|
+
f"and {'has' if len(batch) == 1 else 'have'} been dead-lettered "
|
|
662
|
+
f"(last defer reason: {reason}).",
|
|
645
663
|
"",
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
664
|
+
]
|
|
665
|
+
for msg in batch[:_ESCALATE_DIGEST_DETAIL_CAP]:
|
|
666
|
+
lines += [
|
|
667
|
+
f"- **{msg.kind}** {msg.sender} → {msg.to}, sent {_fmt_ts(msg.ts)}, "
|
|
668
|
+
f"dead-lettered {_fmt_ts(msg.dead_ts)}, {msg.attempts} attempts:",
|
|
669
|
+
" ```",
|
|
670
|
+
f" {msg.text}",
|
|
671
|
+
" ```",
|
|
672
|
+
]
|
|
673
|
+
remaining = len(batch) - _ESCALATE_DIGEST_DETAIL_CAP
|
|
674
|
+
if remaining > 0:
|
|
675
|
+
lines.append(f"- ...and {remaining} more.")
|
|
676
|
+
lines += [
|
|
649
677
|
"",
|
|
650
|
-
f"Saved in the dead-letter store — review with
|
|
651
|
-
|
|
652
|
-
|
|
678
|
+
f"Saved in the dead-letter store — review with "
|
|
679
|
+
f"`agentwire msg dead -s {batch[0].to}`.",
|
|
680
|
+
]
|
|
681
|
+
result = send_email(subject=subject, body="\n".join(lines))
|
|
653
682
|
_log_event(
|
|
654
|
-
"dead_letter_escalated",
|
|
683
|
+
"dead_letter_escalated", to=batch[0].to, count=len(batch), reason=reason,
|
|
655
684
|
ok=bool(getattr(result, "success", False)),
|
|
656
685
|
)
|
|
657
686
|
except Exception as exc: # escalation is best-effort; never break the drain
|
|
658
|
-
_log_event("dead_letter_escalate_failed",
|
|
687
|
+
_log_event("dead_letter_escalate_failed", to=batch[0].to, count=len(batch), error=str(exc))
|
|
659
688
|
|
|
660
689
|
|
|
661
690
|
def _bump_attempts(messages: list[Message], reason: str = "") -> int:
|
|
@@ -675,6 +704,7 @@ def _bump_attempts(messages: list[Message], reason: str = "") -> int:
|
|
|
675
704
|
burns out on schedule.
|
|
676
705
|
"""
|
|
677
706
|
dead = 0
|
|
707
|
+
newly_dead: list[Message] = []
|
|
678
708
|
for msg in messages:
|
|
679
709
|
if msg.path is None:
|
|
680
710
|
continue
|
|
@@ -705,7 +735,7 @@ def _bump_attempts(messages: list[Message], reason: str = "") -> int:
|
|
|
705
735
|
attempts=msg.attempts, reason=reason,
|
|
706
736
|
)
|
|
707
737
|
dead += 1
|
|
708
|
-
|
|
738
|
+
newly_dead.append(msg)
|
|
709
739
|
except OSError:
|
|
710
740
|
pass
|
|
711
741
|
else:
|
|
@@ -713,6 +743,9 @@ def _bump_attempts(messages: list[Message], reason: str = "") -> int:
|
|
|
713
743
|
_write_message(msg.path, msg)
|
|
714
744
|
except OSError:
|
|
715
745
|
pass
|
|
746
|
+
# One digest email for the whole batch (all share the same recipient —
|
|
747
|
+
# `messages` is always one session's inbox), not one per message (#836).
|
|
748
|
+
_escalate_dead_letters(newly_dead, reason)
|
|
716
749
|
return dead
|
|
717
750
|
|
|
718
751
|
|
|
@@ -143,8 +143,14 @@ lands in a durable inbox and is injected only at a safe boundary.
|
|
|
143
143
|
/ `escalation`) does dead-letter, the owner is emailed via the shared Resend
|
|
144
144
|
wiring (the same channel usage-limit parking uses) so the loss is surfaced
|
|
145
145
|
even if nobody runs `msg dead`. `note` is fire-and-forget and `ingest` never
|
|
146
|
-
auto-delivers, so neither is escalated. Escalation is
|
|
147
|
-
|
|
146
|
+
auto-delivers, so neither is escalated. Escalation is **batched per drain
|
|
147
|
+
pass, not per message** (#829/#830): every message dead-lettered in the
|
|
148
|
+
same batch for one recipient gets a single digest email (detail capped at
|
|
149
|
+
the first 10, "...and N more" beyond that) instead of one email each — a
|
|
150
|
+
recipient stuck permanently undeliverable (e.g. wrongly parented to a
|
|
151
|
+
service session that never drains) can't spam the owner one email per
|
|
152
|
+
stuck message. Escalation is best-effort — a send failure is logged
|
|
153
|
+
(`dead_letter_escalate_failed`) and never breaks the drain.
|
|
148
154
|
|
|
149
155
|
### `prompt_is_empty` — the collision detector
|
|
150
156
|
|
|
@@ -13,7 +13,7 @@ FIXTURES_DIR = Path(__file__).parent / "fixtures"
|
|
|
13
13
|
def _no_real_outbound_email(request, monkeypatch):
|
|
14
14
|
"""No test may send real email — ever.
|
|
15
15
|
|
|
16
|
-
``
|
|
16
|
+
``_escalate_dead_letters`` (and friends) call the live Resend wiring, so a
|
|
17
17
|
test that dead-letters a done/request/escalation message without mocking
|
|
18
18
|
``send_email`` silently emails the owner on every suite run (found the hard
|
|
19
19
|
way: ``test_purge_leaves_ingest_and_dead`` flooded the inbox with
|
|
@@ -115,3 +115,14 @@ class TestResolveDefaultCreatedBy:
|
|
|
115
115
|
monkeypatch.setattr(core, "tmux_session_exists", lambda s: False)
|
|
116
116
|
repo = _make_repo(tmp_path)
|
|
117
117
|
assert core.resolve_default_created_by("myproject-fix-bug", repo) is None
|
|
118
|
+
|
|
119
|
+
def test_service_session_caller_returns_none(self, monkeypatch, tmp_path):
|
|
120
|
+
# Regression (2026-07-19): a session created via the portal web UI
|
|
121
|
+
# inherits the portal server subprocess's TMUX_PANE, so `caller`
|
|
122
|
+
# resolves to the "agentwire-portal" service session. Parenting to it
|
|
123
|
+
# is a bug even when same_project would otherwise match — a service
|
|
124
|
+
# session never drains its msg inbox, so anything parented to it
|
|
125
|
+
# dead-letters forever (147-message escalation-email storm).
|
|
126
|
+
repo = _make_repo(tmp_path)
|
|
127
|
+
monkeypatch.setattr(core, "_live_session_cwd", lambda s: repo)
|
|
128
|
+
assert core.resolve_default_created_by("agentwire-portal", repo) is None
|
|
@@ -760,6 +760,8 @@ class TestDeadLetterEscalation:
|
|
|
760
760
|
assert len(inbox.list_dead("s")) == 1 # still archived for audit
|
|
761
761
|
|
|
762
762
|
def test_request_and_escalation_also_email(self, isolate, monkeypatch):
|
|
763
|
+
# Both dead-letter in the same drain pass (same recipient) — one
|
|
764
|
+
# digest email covers the batch, not one email per kind (#836).
|
|
763
765
|
inbox.enqueue("s", "need creds", kind="request", sender="w")
|
|
764
766
|
inbox.enqueue("s", "stuck!", kind="escalation", sender="w")
|
|
765
767
|
self._occupied_agent(monkeypatch)
|
|
@@ -767,8 +769,9 @@ class TestDeadLetterEscalation:
|
|
|
767
769
|
self._capture_email(monkeypatch, sent)
|
|
768
770
|
for _ in range(inbox.MAX_ATTEMPTS):
|
|
769
771
|
inbox.flush_session("s")
|
|
770
|
-
|
|
771
|
-
assert
|
|
772
|
+
assert len(sent) == 1
|
|
773
|
+
assert "2 undelivered messages" in sent[0]["subject"]
|
|
774
|
+
assert "request" in sent[0]["body"] and "escalation" in sent[0]["body"]
|
|
772
775
|
|
|
773
776
|
def test_note_dead_letter_does_not_email(self, isolate, monkeypatch):
|
|
774
777
|
inbox.enqueue("s", "fyi", kind="note", sender="worker")
|
|
@@ -792,6 +795,49 @@ class TestDeadLetterEscalation:
|
|
|
792
795
|
inbox.flush_session("s")
|
|
793
796
|
assert len(inbox.list_dead("s")) == 1 # drain survived; corpse archived
|
|
794
797
|
|
|
798
|
+
def test_large_batch_sends_one_digest_not_one_per_message(self, isolate, monkeypatch):
|
|
799
|
+
# Regression (2026-07-19): a recipient stuck permanently undeliverable
|
|
800
|
+
# (e.g. wrongly parented to a service session) can accumulate a large
|
|
801
|
+
# backlog that all crosses MAX_ATTEMPTS in the same drain pass. That
|
|
802
|
+
# must fire ONE digest email, not one per message (147 individual
|
|
803
|
+
# emails in ~2s was the real incident).
|
|
804
|
+
for i in range(20):
|
|
805
|
+
inbox.enqueue("s", f"report {i}", kind="done", sender="w")
|
|
806
|
+
self._occupied_agent(monkeypatch)
|
|
807
|
+
sent = []
|
|
808
|
+
self._capture_email(monkeypatch, sent)
|
|
809
|
+
for _ in range(inbox.MAX_ATTEMPTS):
|
|
810
|
+
inbox.flush_session("s")
|
|
811
|
+
assert len(inbox.list_dead("s")) == 20
|
|
812
|
+
assert len(sent) == 1
|
|
813
|
+
assert "20 undelivered messages" in sent[0]["subject"]
|
|
814
|
+
|
|
815
|
+
def _msg(self, i):
|
|
816
|
+
return inbox.Message(
|
|
817
|
+
id=f"id{i}", sender="w", to="s", kind="done", text=f"report {i}",
|
|
818
|
+
ts=1000 + i, dead_ts=2000 + i,
|
|
819
|
+
)
|
|
820
|
+
|
|
821
|
+
def test_digest_detail_cap_boundary(self, isolate, monkeypatch):
|
|
822
|
+
# Exactly at the cap: every message gets detail, no truncation line.
|
|
823
|
+
sent = []
|
|
824
|
+
self._capture_email(monkeypatch, sent)
|
|
825
|
+
batch = [self._msg(i) for i in range(inbox._ESCALATE_DIGEST_DETAIL_CAP)]
|
|
826
|
+
inbox._escalate_dead_letters(batch, "target_gone")
|
|
827
|
+
assert len(sent) == 1
|
|
828
|
+
assert "...and" not in sent[0]["body"]
|
|
829
|
+
assert all(f"report {i}" in sent[0]["body"] for i in range(len(batch)))
|
|
830
|
+
|
|
831
|
+
def test_digest_detail_cap_truncates_beyond_boundary(self, isolate, monkeypatch):
|
|
832
|
+
# One over the cap: detail for the first CAP, a single "...and 1 more."
|
|
833
|
+
sent = []
|
|
834
|
+
self._capture_email(monkeypatch, sent)
|
|
835
|
+
batch = [self._msg(i) for i in range(inbox._ESCALATE_DIGEST_DETAIL_CAP + 1)]
|
|
836
|
+
inbox._escalate_dead_letters(batch, "target_gone")
|
|
837
|
+
assert len(sent) == 1
|
|
838
|
+
assert "...and 1 more." in sent[0]["body"]
|
|
839
|
+
assert f"report {inbox._ESCALATE_DIGEST_DETAIL_CAP}" not in sent[0]["body"]
|
|
840
|
+
|
|
795
841
|
|
|
796
842
|
class TestIdempotentDelivery:
|
|
797
843
|
"""#621: a delivery_unverified false-negative must NOT re-inject a landed
|
|
@@ -959,8 +1005,8 @@ class TestForceFlush:
|
|
|
959
1005
|
class TestGcSender:
|
|
960
1006
|
def test_gc_dead_letters_load_bearing(self, isolate, monkeypatch):
|
|
961
1007
|
emailed = []
|
|
962
|
-
monkeypatch.setattr(inbox, "
|
|
963
|
-
lambda
|
|
1008
|
+
monkeypatch.setattr(inbox, "_escalate_dead_letters",
|
|
1009
|
+
lambda batch, r: emailed.extend((m.kind, r) for m in batch))
|
|
964
1010
|
inbox.enqueue("orch", "PR drafted", kind="done", sender="worker")
|
|
965
1011
|
inbox.enqueue("orch", "need review", kind="request", sender="worker")
|
|
966
1012
|
res = inbox.gc_sender("worker")
|
|
@@ -970,7 +1016,7 @@ class TestGcSender:
|
|
|
970
1016
|
assert emailed and all(r == "sender_exited" for _, r in emailed)
|
|
971
1017
|
|
|
972
1018
|
def test_gc_drops_non_load_bearing(self, isolate, monkeypatch):
|
|
973
|
-
monkeypatch.setattr(inbox, "
|
|
1019
|
+
monkeypatch.setattr(inbox, "_escalate_dead_letters", lambda batch, r: None)
|
|
974
1020
|
inbox.enqueue("orch", "fyi", kind="note", sender="worker")
|
|
975
1021
|
res = inbox.gc_sender("worker")
|
|
976
1022
|
assert res["dropped"] == 1 and res["dead"] == 0
|
|
@@ -981,8 +1027,8 @@ class TestGcSender:
|
|
|
981
1027
|
# A flush draining this inbox holds the per-session lock; gc must NOT
|
|
982
1028
|
# dead-letter (and email) a message that flush is mid-delivery on.
|
|
983
1029
|
emailed = []
|
|
984
|
-
monkeypatch.setattr(inbox, "
|
|
985
|
-
lambda
|
|
1030
|
+
monkeypatch.setattr(inbox, "_escalate_dead_letters",
|
|
1031
|
+
lambda batch, r: emailed.extend(m.id for m in batch))
|
|
986
1032
|
inbox.enqueue("orch", "in flight", kind="done", sender="worker")
|
|
987
1033
|
held = inbox._acquire_lock("orch") # simulate an in-flight flush
|
|
988
1034
|
try:
|
|
@@ -1001,6 +1047,24 @@ class TestGcSender:
|
|
|
1001
1047
|
assert len(inbox.list_messages("orch")) == 1 # other sender's done kept
|
|
1002
1048
|
assert inbox.list_ingest("orch") # ingest untouched
|
|
1003
1049
|
|
|
1050
|
+
def test_gc_batches_one_email_per_recipient(self, isolate, monkeypatch):
|
|
1051
|
+
# Regression (#829/#830): gc_sender must send ONE digest email per
|
|
1052
|
+
# recipient, not one per dead-lettered message — exercised against the
|
|
1053
|
+
# real send_email seam (not a stubbed _escalate_dead_letters), so a
|
|
1054
|
+
# regression back to per-message escalation inside the gc loop would
|
|
1055
|
+
# actually be caught here.
|
|
1056
|
+
sent = []
|
|
1057
|
+
monkeypatch.setattr(
|
|
1058
|
+
"agentwire.channels.email.send_email",
|
|
1059
|
+
lambda **kw: sent.append(kw) or SimpleNamespace(success=True),
|
|
1060
|
+
)
|
|
1061
|
+
inbox.enqueue("orch", "PR drafted", kind="done", sender="worker")
|
|
1062
|
+
inbox.enqueue("orch", "need review", kind="request", sender="worker")
|
|
1063
|
+
res = inbox.gc_sender("worker")
|
|
1064
|
+
assert res["dead"] == 2
|
|
1065
|
+
assert len(sent) == 1
|
|
1066
|
+
assert "2 undelivered messages" in sent[0]["subject"]
|
|
1067
|
+
|
|
1004
1068
|
|
|
1005
1069
|
# =============================================================================
|
|
1006
1070
|
# Session-name validation — path-traversal hardening
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/hooks/damage-control/audit_logger.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/hooks/damage-control/rules/agentwire.yaml
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/hooks/damage-control/rules/containers.yaml
RENAMED
|
File without changes
|
|
File without changes
|
{agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/hooks/damage-control/rules/core.yaml
RENAMED
|
File without changes
|
{agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/hooks/damage-control/rules/databases.yaml
RENAMED
|
File without changes
|
{agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/hooks/damage-control/rules/firebase.yaml
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/hooks/damage-control/rules/outbound.yaml
RENAMED
|
File without changes
|
{agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/hooks/damage-control/rules/publish.yaml
RENAMED
|
File without changes
|
{agentwire_dev-1.65.0 → agentwire_dev-1.65.1}/agentwire/hooks/damage-control/rules/remote.yaml
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|