fix(ai_mail): inbox-poller spawn_agent now passes --model DEFAULT_MODEL (sonnet). The daemon asymmetry Vera flagged lived in ai_mail's own handlers/dispatch/daemon.py (name collision, not @daemon branch — their scheduled wakes import wake_branch directly and were covered by efb530e0). DEFAULT_MODEL imported from wake.py, single source; 200k window pin already covered via shared dispatch_monitor wrapper. Test asserts --model in captured spawn cmd. 778 tests green, seedgo 100%, both re-run by devpulse. Investigated by @daemon, built by @ai_mail
This commit is contained in:
+6
-2
@@ -20,8 +20,12 @@ PyPI version — not the changelog header.
|
||||
spawned agent — Sonnet 5 is 1M-context native, and without the pin every
|
||||
dispatched agent would silently inherit a 1M window. E2E-proven: a live
|
||||
dispatched probe reported `claude-sonnet-5` + `WINDOW=200000` from inside.
|
||||
- Known gap (daemon-side, next): daemon.py `spawn_agent()` builds its claude
|
||||
command with no `--model` flag, bypassing wake.py resolution entirely.
|
||||
- Follow-up landed same morning: the "daemon gap" was a name collision —
|
||||
the unpatched `spawn_agent()` was ai_mail's own inbox-poller
|
||||
(`handlers/dispatch/daemon.py`), not the @daemon branch. It now passes
|
||||
`--model DEFAULT_MODEL` (imported from wake.py, single source); the 200k pin
|
||||
was already covered via the shared dispatch_monitor wrapper. @daemon's
|
||||
scheduled wakes import `wake_branch` directly and were covered from the start.
|
||||
|
||||
**fix(spawn, commons, prax, hooks)** — S304 audit fix campaign, Track A
|
||||
(DPLAN-0250, four owner dispatches verified + committed by devpulse):
|
||||
|
||||
@@ -34,6 +34,7 @@ from aipass.ai_mail.apps.handlers.json import json_handler
|
||||
from aipass.ai_mail.apps.handlers.dispatch.status import log_dispatch
|
||||
from aipass.ai_mail.apps.handlers.paths import find_repo_root
|
||||
from aipass.ai_mail.apps.handlers.dispatch.test_token import scan_and_ack_test_emails
|
||||
from aipass.ai_mail.apps.handlers.dispatch.wake import DEFAULT_MODEL
|
||||
|
||||
|
||||
# Infrastructure paths
|
||||
@@ -408,6 +409,8 @@ def spawn_agent(
|
||||
"-c",
|
||||
"-p",
|
||||
prompt,
|
||||
"--model",
|
||||
DEFAULT_MODEL,
|
||||
"--max-turns",
|
||||
str(max_turns),
|
||||
"--permission-mode",
|
||||
|
||||
@@ -1317,6 +1317,48 @@ def test_spawn_agent_strips_claude_env_vars(tmp_path, monkeypatch):
|
||||
assert captured_env.get("AIPASS_SESSION_TYPE") == "daemon"
|
||||
|
||||
|
||||
def test_spawn_agent_claude_cmd_includes_model_flag(tmp_path):
|
||||
"""Poller-triggered spawn passes --model DEFAULT_MODEL to the claude invocation."""
|
||||
branch_path = tmp_path / "branch"
|
||||
branch_path.mkdir()
|
||||
(branch_path / "logs").mkdir()
|
||||
|
||||
message = {"from": "@devpulse", "id": "msg1", "subject": "Test task"}
|
||||
config = {"max_turns_per_wake": 50}
|
||||
state = {"daily_counts": {}, "session_cycles": {}}
|
||||
|
||||
captured_args = []
|
||||
|
||||
def capture_popen(*args, **kwargs):
|
||||
captured_args.append(args[0] if args else kwargs.get("args"))
|
||||
mock_proc = MagicMock()
|
||||
mock_proc.pid = 22222
|
||||
return mock_proc
|
||||
|
||||
with (
|
||||
patch(
|
||||
"aipass.ai_mail.apps.handlers.dispatch.daemon.subprocess.Popen",
|
||||
side_effect=capture_popen,
|
||||
),
|
||||
patch(
|
||||
"aipass.ai_mail.apps.handlers.dispatch.daemon._acquire_lock",
|
||||
return_value=(True, "Lock acquired"),
|
||||
),
|
||||
patch("aipass.ai_mail.apps.handlers.dispatch.daemon.log_dispatch"),
|
||||
patch(
|
||||
"aipass.ai_mail.apps.handlers.dispatch.daemon.send_notification",
|
||||
create=True,
|
||||
),
|
||||
):
|
||||
result = spawn_agent(branch_path, "@testbranch", message, config, state)
|
||||
|
||||
assert result is True
|
||||
monitor_cmd = captured_args[0]
|
||||
assert "--model" in monitor_cmd
|
||||
model_idx = monitor_cmd.index("--model")
|
||||
assert monitor_cmd[model_idx + 1] == daemon_mod.DEFAULT_MODEL
|
||||
|
||||
|
||||
def test_spawn_agent_prompt_includes_reply_id(tmp_path):
|
||||
"""Prompt includes explicit reply command with the dispatch email ID."""
|
||||
branch_path = tmp_path / "branch"
|
||||
|
||||
Reference in New Issue
Block a user