From b38e9be17cb2cf4e315374874b425dbefe0f68c0 Mon Sep 17 00:00:00 2001 From: Patrick Buckley Date: Tue, 21 Jul 2026 17:47:11 -0700 Subject: [PATCH] docs(session): scope the zero-band geometry claims to the default compact threshold The drain comment and the architecture docs stated the zero-budget band relative to the auto-compact threshold as if 0.8 were universal ("well below the auto-compact threshold"); with an operator-set auto_compact_pct under the ~70% zero point the claim reads inverted. State the geometry against the DEFAULT threshold and make explicit what was always true of the mechanism: the trigger's predicate is the exhausted budget itself, never a threshold, so with low thresholds the owed path compacts first and the trigger is its bail/insufficient backstop. --- docs/architecture.md | 12 ++++++++---- turnstone/core/session.py | 18 ++++++++++++------ 2 files changed, 20 insertions(+), 10 deletions(-) diff --git a/docs/architecture.md b/docs/architecture.md index 5e9314f2..382d35c8 100644 --- a/docs/architecture.md +++ b/docs/architecture.md @@ -985,10 +985,14 @@ context budget, and three guarantees apply when that budget reaches zero successful-looking trim). A zero budget also triggers one mid-turn auto-compaction before results are -sized: the response reserve zeroes the budget well below the auto-compact -threshold (near 70% fullness with `max_tokens ≥ context_window/4`), and -without this trigger a session could idle in that band indefinitely with -every tool result floored or dropped. +sized. With `max_tokens ≥ context_window/4` the response reserve zeroes the +budget near 70% fullness — below the default 80% auto-compact threshold — +and without this trigger a session could idle in that band indefinitely +with every tool result floored or dropped. The trigger keys on the +exhausted budget itself, not on any threshold, so it composes with any +operator-set `auto_compact_pct`: with thresholds below the zero point the +ordinary owed-compaction paths fire first and this trigger degrades to a +backstop for the cases where they bailed or freed too little. --- diff --git a/turnstone/core/session.py b/turnstone/core/session.py index 4c3652dc..6fc3535d 100644 --- a/turnstone/core/session.py +++ b/turnstone/core/session.py @@ -6431,14 +6431,20 @@ class ChatSession: and zero_budget_compact_attempts < _ZERO_BUDGET_COMPACT_CAP_PER_SEND and self._generation == my_generation ): - # Zero tool-result budget wedges the loop BELOW the owed - # thresholds: with max_tokens ≥ context_window/4 the - # response reserve zeroes the budget near 70% fullness, - # well under auto_compact_pct, and a stalled model - # appends too little to ever cross it — so without this + # Zero tool-result budget can wedge the loop BELOW the + # owed thresholds: with max_tokens ≥ context_window/4 + # the response reserve zeroes the budget near 70% + # fullness — under the DEFAULT auto_compact_pct, and + # further under any raised one — while a stalled model + # appends too little to ever cross it, so without this # trigger the session can sit in the zero band # indefinitely while every tool result is floored or - # dropped (#883). Zero budget is itself + # dropped (#883). The predicate is the exhausted + # budget itself, never a threshold, so it composes + # with any operator-set auto_compact_pct: thresholds + # below the zero point compact via the owed path + # first, and this branch is its bail/insufficient + # backstop. Zero budget is itself # compaction-owed evidence. ``auto=True`` WITHOUT # ``threshold_pct``, exactly like the ctx-overflow # retry: no threshold was evaluated, so the notice must