Skip to content

Soft threshold as a handoff reserve of turns; document token settings #181

Closed

Description

@lbacik

This was generated by AI during triage.

Split out of #159 (parts 1 and 4). Decisions are recorded in ADR 0004 (docs/adr/0004-handoff-reserve-in-turns-and-seal-based-token-handoff.md) and in the glossary terms Soft threshold and Handoff reserve in CONTEXT.md.

Agent Brief

Category: enhancement
Summary: Place the soft threshold early enough to leave a handoff reserve of N turns at the current context size, and document the token settings correctly.

Current behavior:
Config.soft_threshold_tokens is a fixed share of the budget: max_budget_tokens * (1 - soft_threshold_percentage), which is 3.2M of 4M by default. Every turn re-counts the whole main context. In #155 the main context was about 148K, so the 800K gap covered only about five turns. The crossing is latched after the turn that crosses it, which here was already 127K past the threshold.

.env.example describes the soft threshold relative to MAX_BUDGET_USD, doesn't list MAX_BUDGET_TOKENS, and shows MAX_BUDGET_USD=5, while the default is 20.

Desired behavior:

  • A new setting, HANDOFF_RESERVE_TURNS:
    • It defaults to 6. It must be an integer from 1 to 20; anything else is a startup config error.
    • It means the number of turns guaranteed after the turn that crosses the threshold.
  • The effective soft threshold is the earlier of two rules, computed from the main thread's latest context size (not the peak):
    soft = min(max_budget_tokens · (1 − pct), max_budget_tokens − (reserve_turns + 1) · main_context_tokens)
  • The threshold is evaluated on every counted response (as today) and also in the PreToolUse hook. There is no separate predictive check. Once crossed, it stays crossed, even if a compaction later shrinks the context.
  • If the reserve exceeds the remaining budget (a huge context), the threshold fires immediately. That is correct behaviour, not an error.
  • The rule that set the threshold, percentage or reserve, is logged:
    • token_soft_threshold_crossed carries reserve_turns=, main_context_tokens=, reserve_tokens=, soft_threshold_tokens= and rule=
    • limits_checked carries the effective values
    • token_budget in attempt.json records the effective threshold at crossing and the rule that set it
  • The startup event logs the effective MAX_BUDGET_TOKENS, SOFT_THRESHOLD_PERCENTAGE and HANDOFF_RESERVE_TURNS.
  • .env.example documents MAX_BUDGET_TOKENS, SOFT_THRESHOLD_PERCENTAGE and HANDOFF_RESERVE_TURNS, with their defaults and the formula above. It corrects the MAX_BUDGET_USD example to the real default (20) and describes it as a looser backstop with a startup floor check. The operator onboarding doc uses the same formula.

Key interfaces:

  • Config:
    • new field handoff_reserve_turns, parsed from HANDOFF_RESERVE_TURNS
    • the static soft_threshold_tokens property becomes the percentage rule only, or is replaced
    • the effective threshold depends on the live context size, so it is computed where the ledger reading is available
  • The executor's limit check (_check_limits) uses the effective threshold and the ledger's latest main_context_tokens.
  • The token_budget summary gains the rule and effective threshold fields.

Acceptance criteria:

  • With max_budget_tokens=4_000_000, pct=0.2, reserve_turns=6 and a 150K main context, the threshold is 2,950,000 (reserve rule). With a 50K context it is 3,200,000 (percentage rule). Unit tests on the calculation.
  • A simulated run with a ~150K context crosses the soft threshold with at least reserve_turns turns of budget left before the hard ceiling, counting the crossing turn's overshoot (test).
  • The check also runs in PreToolUse, and a crossing there latches and logs like a response-time crossing (test).
  • When the reserve exceeds the remaining budget, the threshold is crossed on the next check (test).
  • HANDOFF_RESERVE_TURNS parsing: the default is 6; 1 and 20 are accepted; 0, 21, -1 and non-integers are rejected (config tests).
  • The crossing event, limits_checked, the startup event and token_budget carry the fields listed above (tests).
  • .env.example and docs/agents/operator-onboarding.md describe the three token settings and the formula accurately, and MAX_BUDGET_USD matches its real default.

Out of scope:

  • The handoff instruction contents and the skill's commit flow (separate sub-issue: cheaper token handoff).
  • The emergency handoff note (separate sub-issue).
  • Changing the hard ceiling, the ledger's estimation, or the USD backstop logic.
  • Denying read-only commands after the threshold.

Activity

  1. added
    enhancementNew feature or request
    ready-for-agentFully specified implementation issue ready for an unattended agent
    on Oct 8, 2026
  2. self-assigned this
    on Oct 8, 2026
  3. lbacik commented on Oct 8, 2026

    @lbacik
    OwnerAuthor

    Agent Attempt Result: incomplete

    Branch: agent/issue-181
    PR: none

    Evidence

    • Check command: /home/agent/target-venv/bin/python -m pytest → exit code 0
    • Review cycles: 0/2
    • Review findings: all clear

    Details

    Claude SDK completed the implementation workflow.

  4. removed
    ready-for-agentFully specified implementation issue ready for an unattended agent
    on Oct 8, 2026
  5. removed their assignment
    on Oct 8, 2026
  6. added
    ready-for-agentFully specified implementation issue ready for an unattended agent
    on Oct 11, 2026
  7. self-assigned this
    on Oct 11, 2026
  8. added a commit that references this issue on Oct 11, 2026
  9. lbacik commented on Oct 11, 2026

    @lbacik
    OwnerAuthor

    Agent Attempt Result: incomplete

    Branch: agent/issue-181
    PR: none

    Evidence

    • Check command: UV_PROJECT_ENVIRONMENT=/home/agent/venv-py311 uv run --python 3.11 --extra dev ruff check && UV_PROJECT_ENVIRONMENT=/home/agent/venv-py311 uv run --python 3.11 --extra dev pytest && UV_PROJECT_ENVIRONMENT=/home/agent/venv-py313 uv run --python 3.13 --extra dev pytest → exit code 0
    • Review cycles: 0/2
    • Review findings: all clear

    Details

    Claude SDK completed the implementation workflow.

  10. removed
    ready-for-agentFully specified implementation issue ready for an unattended agent
    on Oct 11, 2026
  11. removed their assignment
    on Oct 11, 2026
  12. added
    ready-for-agentFully specified implementation issue ready for an unattended agent
    on Oct 11, 2026
  13. self-assigned this
    on Oct 11, 2026
  14. added a commit that references this issue on Oct 11, 2026
  15. lbacik commented on Oct 11, 2026

    @lbacik
    OwnerAuthor

    Agent Attempt Result: complete

    Branch: agent/issue-181
    PR: #209

    Evidence

    • Check command: UV_PROJECT_ENVIRONMENT=/home/agent/venv-py311 uv run --python 3.11 --extra dev ruff check && UV_PROJECT_ENVIRONMENT=/home/agent/venv-py311 uv run --python 3.11 --extra dev pytest && UV_PROJECT_ENVIRONMENT=/home/agent/venv-py313 uv run --python 3.13 --extra dev pytest → exit code 0
    • Reviews performed: 1
    • Review repair cycles: 0/2
    • Review findings: not collected

    Details

    Claude SDK completed the implementation workflow.

  16. removed
    ready-for-agentFully specified implementation issue ready for an unattended agent
    on Oct 11, 2026
  17. removed their assignment
    on Oct 11, 2026
  18. added a commit that references this issue on Oct 11, 2026
  19. added a commit that references this issue on Oct 14, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions