feat(delegation): uncap max_spawn_depth (floor 1, no ceiling) (#39772)

* fix: respect disabled auto-compaction on context overflow

Port from anomalyco/opencode#30749.

When compression.enabled is false, NO automatic compaction trigger may
fire. The proactive token-threshold paths (preflight + post-response
should_compress gate) already honoured the setting, but the three
provider-overflow recovery paths in the agent loop — long-context-tier
429, 413 payload-too-large, and context-overflow — called
_compress_context() unconditionally, silently compressing and rotating
the session against the user's explicit choice.

Add a single guard at the top of the overflow-recovery dispatch: when
compression is disabled and the error is one of those three overflow
classes, surface a terminal error (compaction_disabled: True) telling the
user to /compress manually, /new, switch to a larger-context model, or
reduce attachments. Manual /compress (force=True) is unaffected — it never
enters this loop.

Tests: new TestOverflowWithCompactionDisabled (413 + 400 overflow don't
compress when disabled; control case still compresses when enabled).
Existing overflow-recovery tests updated to enable compaction explicitly
(they verify the recovery fires); fixture defaults flipped to True to
match production (compression.enabled defaults to True).

* feat(delegation): uncap max_spawn_depth to match max_concurrent_children

Removed the hard ceiling of 3 on delegation.max_spawn_depth. Depth now has
a floor of 1 and no upper limit, mirroring max_concurrent_children. Cost
(each level multiplies API spend) is the practical limiter, not a constant.

- delegate_tool.py: drop _MAX_SPAWN_DEPTH_CAP, _get_max_spawn_depth() floors
  at 1 instead of clamping to [1,3]; depth-limit error string reworded
- config.py / cli-config.yaml.example: doc comments say floor 1, no ceiling
- docs (configuration, delegation, delegation-patterns): range 1-3 -> >=1
- tests: convert clamp-above-3 change-detector into a no-ceiling invariant,
  drop the _MAX_SPAWN_DEPTH_CAP==3 snapshot assert, fix warning-text assert
This commit is contained in:
Teknium
2026-06-05 04:46:02 -07:00
committed by GitHub
parent 06268f11cc
commit d41427504e
7 changed files with 30 additions and 30 deletions
+15 -11
View File
@@ -134,7 +134,9 @@ MAX_DEPTH = 1 # flat by default: parent (0) -> child (1); grandchild rejected u
# Configurable depth cap consulted by _get_max_spawn_depth; MAX_DEPTH
# stays as the default fallback and is still the symbol tests import.
_MIN_SPAWN_DEPTH = 1
_MAX_SPAWN_DEPTH_CAP = 3
# No upper ceiling on spawn depth — like max_concurrent_children, depth has a
# floor of 1 and no ceiling. Deeper trees multiply API cost, so the default
# stays flat (MAX_DEPTH = 1); raising the config knob is an explicit opt-in.
# ---------------------------------------------------------------------------
@@ -392,7 +394,7 @@ def _get_child_timeout() -> float:
def _get_max_spawn_depth() -> int:
"""Read delegation.max_spawn_depth from config, clamped to [1, 3].
"""Read delegation.max_spawn_depth from config, floored at 1 (no ceiling).
depth 0 = parent agent. max_spawn_depth = N means agents at depths
0..N-1 can spawn; depth N is the leaf floor. Default 1 is flat:
@@ -400,9 +402,11 @@ def _get_max_spawn_depth() -> int:
(blocked by this guard AND, for leaf children, by the delegation
toolset strip in _strip_blocked_tools).
Raise to 2 or 3 to unlock nested orchestration. role="orchestrator"
removes the toolset strip for depth-1 children when
Raise to 2+ to unlock nested orchestration. role="orchestrator"
removes the toolset strip for spawning children when
max_spawn_depth >= 2, enabling them to spawn their own workers.
Like max_concurrent_children, there is no upper ceiling — but each
extra level multiplies API cost, so raise it deliberately.
"""
cfg = _load_config()
val = cfg.get("max_spawn_depth")
@@ -417,16 +421,15 @@ def _get_max_spawn_depth() -> int:
MAX_DEPTH,
)
return MAX_DEPTH
clamped = max(_MIN_SPAWN_DEPTH, min(_MAX_SPAWN_DEPTH_CAP, ival))
if clamped != ival:
floored = max(_MIN_SPAWN_DEPTH, ival)
if floored != ival:
logger.warning(
"delegation.max_spawn_depth=%d out of range [%d, %d]; " "clamping to %d",
"delegation.max_spawn_depth=%d below floor %d; using %d",
ival,
_MIN_SPAWN_DEPTH,
_MAX_SPAWN_DEPTH_CAP,
clamped,
floored,
)
return clamped
return floored
def _get_orchestrator_enabled() -> bool:
@@ -1982,7 +1985,8 @@ def delegate_task(
f"Delegation depth limit reached (depth={depth}, "
f"max_spawn_depth={max_spawn}). Raise "
f"delegation.max_spawn_depth in config.yaml if deeper "
f"nesting is required (cap: {_MAX_SPAWN_DEPTH_CAP})."
f"nesting is required (no hard ceiling, but each level "
f"multiplies API cost)."
)
}
)