fix(923): watchdog counts only tool-using turns; narration-only turns no longer burn budget
Observed: stories 917, 918, 920, 910 all turn-limit-killed despite producing
real commits. Tally across their session logs shows 30–55% of assistant
turns were pure narration ("I'll read X next", "Now let me check Y") with
no tool_use. At 80 max_turns the effective work budget was ~44 tool calls,
not enough for a typical bug fix's edit + test + check_criterion cycle.
Changes:
- New optional AgentConfig field max_tool_turns. When set the watchdog
uses it instead of max_turns; only assistant messages whose
data.message.content has at least one tool_use block count.
- count_turns_in_log in agents/pool/auto_assign/watchdog/limits.rs
filters on tool_use. Existing test helper write_fake_session_log now
emits tool_use blocks; added write_fake_mixed_session_log for the
narration regression test.
- agents.toml: coders/coder-opus get max_turns=200 (claude-code's own
--max-turns cap, sized to never bite before the watchdog) and
max_tool_turns=80. qa: 120 / 40. mergemaster: 250 / 100. Budgets
unchanged — the dollar cap remains the runaway-loop backstop, with
~$3-5 worst-case waste if an agent narrates indefinitely.
- Two new regression tests:
* watchdog_does_not_count_narration_only_turns: 5 tool + 30 narration
under max_tool_turns=10 stays Running.
* watchdog_max_tool_turns_overrides_max_turns: 4 tool turns at
max_tool_turns=3 / max_turns=200 still terminates with TurnLimit.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -242,6 +242,15 @@ pub struct AgentConfig {
|
||||
pub disallowed_tools: Option<Vec<String>>,
|
||||
#[serde(default)]
|
||||
pub max_turns: Option<u32>,
|
||||
/// Watchdog cap on **tool-using** assistant turns (story 923).
|
||||
///
|
||||
/// Narration-only turns (assistant messages with no `tool_use` block)
|
||||
/// don't count against this. When unset, the watchdog falls back to
|
||||
/// `max_turns`. Set this lower than `max_turns` so claude-code's own
|
||||
/// `--max-turns` cap (which counts narration) doesn't fire before the
|
||||
/// watchdog.
|
||||
#[serde(default)]
|
||||
pub max_tool_turns: Option<u32>,
|
||||
#[serde(default)]
|
||||
pub max_budget_usd: Option<f64>,
|
||||
#[serde(default)]
|
||||
@@ -325,6 +334,7 @@ impl Default for ProjectConfig {
|
||||
allowed_tools: None,
|
||||
disallowed_tools: None,
|
||||
max_turns: None,
|
||||
max_tool_turns: None,
|
||||
max_budget_usd: None,
|
||||
system_prompt: None,
|
||||
stage: None,
|
||||
|
||||
Reference in New Issue
Block a user