Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 15 additions & 15 deletions config-baseline.json
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@
"admission_gate": true,
"workflow_run_timeout_secs": 3600,
"subagent_mem_buffer_pct": 20,
"chat_turn_timeout_secs": 7200,
"chat_turn_timeout_secs": 14400,
"session_start_timeout_secs": 90,
"tool_approval_timeout_secs": 600,
"session_control": true,
Expand Down Expand Up @@ -730,10 +730,10 @@
"sensitive": false,
"tags": [],
"label": "Chat Turn Timeout (secs)",
"help": "Wall-clock ceiling for one chat turn. This is a runaway backstop, so it is clamped to 300s..86400s (24h) and can never be disabled. Raise it above the 2h default for long unattended turns (full test suites, long builds); the ACP transport's prompt wait follows it. Hitting the ceiling is visible: the turn ends with a card naming the limit. For work spanning days, prefer monitor/goal loops — they end the turn between cycles and survive restarts.",
"help": "Wall-clock ceiling for one chat turn. This is a runaway backstop, so it is clamped to 300s..86400s (24h) and can never be disabled. The 4h default covers the longest single turn the shipped budgets produce (a 90-minute test command plus a fix and a re-run, or a blocking subagent wave at its 2h wait cap); the ACP transport's prompt wait follows it. Hitting the ceiling is visible: the turn ends with a card naming the limit. For work spanning many hours or days, prefer monitor/goal loops — they end the turn between cycles and survive restarts, which a single marathon turn cannot.",
"hasChildren": false,
"enumValues": null,
"defaultValue": 7200
"defaultValue": 14400
},
{
"path": "agent.session_start_timeout_secs",
Expand Down Expand Up @@ -3338,10 +3338,10 @@
"enumValues": null,
"defaultValue": {
"check_after_secs": 60.0,
"stale_window_secs": 300.0,
"tool_stall_suspect_secs": 3600.0,
"tool_stall_hard_cap_secs": 3600.0,
"model_silent_probe_secs": 900.0,
"stale_window_secs": 600.0,
"tool_stall_suspect_secs": 5400.0,
"tool_stall_hard_cap_secs": 7200.0,
"model_silent_probe_secs": 1800.0,
"wellness_sample_secs": 3.0
}
},
Expand All @@ -3368,10 +3368,10 @@
"sensitive": false,
"tags": [],
"label": "Stale probe window (s)",
"help": "Idle seconds before an UNKNOWN-verdict model-wait turn is safe-probed via session/cancel. Probes are non-lethal: a live turn auto-recovers.",
"help": "Idle seconds before an UNKNOWN-verdict model-wait turn is safe-probed via session/cancel. Probes are non-lethal, but a probe of a LIVE think cancels and regenerates it, so the window must clear an ordinary silent think. Default 10 min. A think the oracle can attest (an established backend socket) gets the longer model-silent window instead, so this one governs only thinks with no such evidence: a host without procfs, or a backend connection that is momentarily down. Its cost is wedge-recovery latency on a runtime that is already dead, never lost work.",
"hasChildren": false,
"enumValues": null,
"defaultValue": 300.0
"defaultValue": 600.0
},
{
"path": "watchdog.tool_stall_suspect_secs",
Expand All @@ -3382,10 +3382,10 @@
"sensitive": false,
"tags": [],
"label": "Tool stall suspect (s)",
"help": "Idle seconds before an UNKNOWN-verdict in-flight tool is cancelled and the turn routed to tool-stall recovery (continue-nudge, no re-run of the original message). WORKING tools (e.g. a matched live build child) are never cancelled regardless of duration. Default 1h: generous enough for long builds and MCP tools on macOS, where the liveness oracle degrades (no /proc) and cannot distinguish a live build from a stall, while still landing inside the turn's own ceiling (agent.chat_turn_timeout_secs) so recovery is reachable. Enforcement is at handle construction, not config load: a window past the headroom fraction of the transport's per-prompt timeout is clamped with a warning, while one that merely exceeds agent.chat_turn_timeout_secs is warned about but left as set, because the same handle also serves callers that pass a larger prompt timeout (review and cron turns).",
"help": "Idle seconds before an UNKNOWN-verdict in-flight tool is cancelled and the turn routed to tool-stall recovery (continue-nudge, no re-run of the original message). WORKING tools (a matched live build child, an MCP subtree with CPU movement) are never cancelled regardless of duration, so this window governs only what the liveness oracle cannot attest. Default 90 min: it clears every shipped budget a single tool call can legitimately spend silent (the task runner's 90-minute test command, a full test suite with one retry in one shell call) while still landing inside the turn's own ceiling (agent.chat_turn_timeout_secs) so recovery is reachable. Enforcement is at handle construction, not config load: a window past the headroom fraction of the transport's per-prompt timeout is clamped with a warning, while one that merely exceeds agent.chat_turn_timeout_secs is warned about but left as set, because the same handle also serves callers that pass a larger prompt timeout (review and cron turns).",
"hasChildren": false,
"enumValues": null,
"defaultValue": 3600.0
"defaultValue": 5400.0
},
{
"path": "watchdog.tool_stall_hard_cap_secs",
Expand All @@ -3396,10 +3396,10 @@
"sensitive": false,
"tags": [],
"label": "Hard cap (s)",
"help": "Absolute ceiling for UNKNOWN-verdict forbearance (e.g. the extended probably-thinking window). Applies ONLY to UNKNOWN verdicts — never to a WORKING session, which is deferred before this cap is consulted and is therefore bounded only by the turn's own ceiling. Default 1h, clamped against the transport's per-prompt timeout like the suspect window.",
"help": "Absolute ceiling for UNKNOWN-verdict forbearance (e.g. the extended probably-thinking window) and for any per-agent watchdog_tool_stall_* override. Applies ONLY to UNKNOWN verdicts — never to a WORKING session, which is deferred before this cap is consulted and is therefore bounded only by the turn's own ceiling. Default 2h, clamped against the transport's per-prompt timeout like the suspect window.",
"hasChildren": false,
"enumValues": null,
"defaultValue": 3600.0
"defaultValue": 7200.0
},
{
"path": "watchdog.model_silent_probe_secs",
Expand All @@ -3410,10 +3410,10 @@
"sensitive": false,
"tags": [],
"label": "Silent-think probe window (s)",
"help": "Extended probe window for a model-wait with an established backend connection but flat counters (non-streamed server-side reasoning, e.g. long xhigh thinks). Probing a live think cancels and regenerates it, so this window is deliberately generous.",
"help": "Extended probe window for a model-wait with an established backend connection but flat counters (non-streamed server-side reasoning, e.g. long xhigh thinks). Probing a live think cancels and regenerates it, so this window is deliberately generous: 30 min clears the long end of an extended-effort think.",
"hasChildren": false,
"enumValues": null,
"defaultValue": 900.0
"defaultValue": 1800.0
},
{
"path": "watchdog.wellness_sample_secs",
Expand Down
8 changes: 4 additions & 4 deletions docs/architecture/overview.md
Original file line number Diff line number Diff line change
Expand Up @@ -281,11 +281,11 @@ graph TB
older than `session.pool_ttl_secs` (default 1800s) are discarded at claim time.
- **Idle timeout** reclaims a session after `session.timeout_secs`, default
**3600s**.
- **Turn ceiling**: `agent.chat_turn_timeout_secs` defaults to **7200s** (2h),
clamped to 300s..86400s (`CHAT_TURN_TIMEOUT_MAX`, deliberately decoupled from the 7200s default) and never disable-able. It is a runaway backstop, so a
- **Turn ceiling**: `agent.chat_turn_timeout_secs` defaults to **14400s** (4h),
clamped to 300s..86400s (`CHAT_TURN_TIMEOUT_MAX`, deliberately decoupled from the 14400s default) and never disable-able. It is a runaway backstop, so a
turn that hits it ends with a card naming the limit rather than failing
silently. The ACP transport carries its own prompt timeout of the same
magnitude and bounds the turn first.
silently. The ACP transport's prompt timeout follows the configured ceiling
(plus a margin) so the dashboard's card always fires first.
- **Tool-approval window**: `agent.tool_approval_timeout_secs` defaults to
**600s** (10 min). It must expire *inside* the turn that opened it — otherwise
an unanswered prompt is reported as a turn timeout and the real cause is lost —
Expand Down
2 changes: 1 addition & 1 deletion docs/architecture/resource-protection.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ anything that survived a gateway crash. No single mechanism is a single point of
| Context compaction | `session.py` | Chat sessions | `session.autocompact_pct` | No | Sends `/compact` to kiro-cli to free context window |
| Background session recycle | `session.py` | Background sessions (cron, subagent) | 70% context usage (`_BG_RECYCLE_PCT`) | No | Recycles the session before context overflow |
| Watchdog process liveness | `taskrunner.py` | Task runner steps | 2 consecutive dead checks (`_DEAD_THRESHOLD`) at 30s intervals | Yes, part of the watchdog loop | Resets the session to trigger crash recovery |
| Config bound clamp | `config/loader.py` | Subagent count, turns, timeouts and pool size at load time | `subagent_auto_max` and `max_subagents` to 64 (`SUBAGENT_AUTO_MAX_CEILING`), `subagent_max_turns` 1..200, `chat_turn_timeout_secs` 300..86400 (`CHAT_TURN_TIMEOUT_MAX`; 7200 is the default, not the ceiling), `session_start_timeout_secs`, `tool_approval_timeout_secs` 30..7200 and cross-field to 60s under the turn ceiling (`APPROVAL_TURN_MARGIN_SECS`), `loop_stall_exit_after_secs` 10..300, `pool_size` 0..10 (`_SECURITY_BOUNDED_FIELDS`) | No | `_clamp_security_bounds` clamps out-of-range ints, logs a WARNING, emits SEL `config_bounds_clamped` (`outcome=clamped`) |
| Config bound clamp | `config/loader.py` | Subagent count, turns, timeouts and pool size at load time | `subagent_auto_max` and `max_subagents` to 64 (`SUBAGENT_AUTO_MAX_CEILING`), `subagent_max_turns` 1..200, `chat_turn_timeout_secs` 300..86400 (`CHAT_TURN_TIMEOUT_MAX`; 14400 is the default, not the ceiling), `session_start_timeout_secs`, `tool_approval_timeout_secs` 30..7200 and cross-field to 60s under the turn ceiling (`APPROVAL_TURN_MARGIN_SECS`), `loop_stall_exit_after_secs` 10..300, `pool_size` 0..10 (`_SECURITY_BOUNDED_FIELDS`) | No | `_clamp_security_bounds` clamps out-of-range ints, logs a WARNING, emits SEL `config_bounds_clamped` (`outcome=clamped`) |

## Per-workflow coverage matrix

Expand Down
Loading
Loading